Prettierことはじめ

# Prettier、はじめました。

## 最初に

JavaScriptの整形ツール"Prettier"を使い始めてみたので、試してみた内容を備忘録的にこちらに書き残していこうと思います。ま、今更感ありますがね。。。:innocent::zap:

基本的に情報は公式ドキュメントを参照しています。

[Prettier](https://prettier.io/)

## Prettierをそのままで使い始めてみる

eslintなどと組み合わせるパターンもありますが、まずはそのままで使ってみようと思います。
対象のプロジェクトルートで下記のコマンドを入力して、``Prettier``をインストールします。

```bash
yarn add prettier --dev --exact
```

あとは``"fmt": "prettier --write src/**/*.js"``というように、``package.json``内の``scripts``にコマンドを定義して実行すれば、完璧です。
(``--write``オプションで整形したコードで上書きます)


```json
  "scripts": {
    "fmt": "prettier --write src/**/*.js"
  },
```

#### 追記: 複数の拡張子を対象にする
ちなみに下記のように設定することで、複数の拡張子に対応することができます。
これはかなり便利で、自分自身はよくこのように設定することが多いです。

```json
  "scripts": {
    "fmt": "prettier --write **/*.{js,json,md,html}"
  },
```

#### 指定した階層以下すべてのファイルをprettierの対象とする

ちなみに下記のような書き方でprettierを実行した場合、階層の深さ自体も指定していることになります。

例えば、

```bash
prettier --write src/**/*.{js,json,md,html}
```

このような書き方をしている場合、下記のように格納されているファイルはprettier対象となりますが、

```bash
src/hoge/hoge.js
src/fuga/fuga.js
```

下記のファイルは対象になりません。

```bash
src/hoge.js
src/hoge/fuga/hoge.js
```

階層の深さは関係なく、`src`配下の全ディレクトリ内にあるすべてのjsファイルをprettier対象としたい場合は下記のように指定する必要があります。


```bash
prettier --write 'src/**/*.js'

# または
prettier --write "src/**/*.js"
```

`package.json`内に記述する場合は下記のようになります。

```json
  "scripts": {
    "fmt": "prettier --write 'src/**/*.js'"
  }
```

または、

```json
  "scripts": {
    "fmt": "prettier --write \"src/**/*.js\""
  }
```

もしカレント以下の全てのファイルの`js, json, md, html`ファイルを`prettier`対象としたい場合は下記のように`package.json`内で設定すると良いと思います。

```json
  "scripts": {
    "fmt": "prettier --write '**/*.{js,json,md,html}'"
  }
```

#### package.json内でPrettierのオプションを設定する


``package.json``内にPrettierのオプションを指定することもできるようなので、私は下記のようにオプションを指定しました。

```json
  "prettier": {
    "singleQuote": true,
    "semi": false
  },
```

* セミコロンはいらない
* 文字列はシングルクォートにする

という二つの指定です。

今回の場合だと、あとは``yarn run fmt``とコマンド叩くことで整形してくれます。
簡単ですね。

公式見てみるとCLI上でのオプションもたくさんありそうなので、色々と試してみるのも面白いかもしれません。

[Prettier - CLI](https://prettier.io/docs/en/cli.html)

## Prettier with Eslint

``Eslint``と組み合わせて使う方法。
公式ドキュメントを意訳してみた。

> ESLintを使用している場合、ワークフローにPrettierを統合するのは簡単です。 PrettierをESLintに統合するには、2つの異なる方法がありますが どちらか一方、またはその両方を有効にすることができます。

２つ方法があるらしいので、その２つとも試してみることにします。

### Use ESLint to run Prettier

プロジェクトで既にESLintを導入していて、一回のコマンドで全てのスタイルチェックを実行するような場合、ESLintに対してPrettierの実行を依頼することができるようです。
``eslint-plugin-prettier``を使ってESLintルールを適用したPrettierを追加するだけのようです。

試してみます。

```bash
yarn add --dev prettier eslint-plugin-prettier
```

公式を見ると、``.eslintrc.json``に下記の記述を追記していました。

```json
{
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
}
```

実際に自身の方で試してみたプロジェクトではjs形式の``.eslint.js``でしたが、記述にあまり変わりはないので割愛します。一応こんな感じで足してみました。

```diff
diff --git a/.eslintrc.js b/.eslintrc.js
index 1256756..15dafce 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -11,6 +11,7 @@ module.exports = {
     "parserOptions": {
         "sourceType": "module"
     },
+    "plugins": ["prettier"],
     "rules": {
         "indent": [
             "error",
@@ -23,6 +24,12 @@ module.exports = {
         "quotes": [
             "error",
             "single"
+        ],
+        "prettier/prettier": [
+            "error", {
+                "singleQuote": true,
+                "semi": false
+            },
         ]
     }
 };
```

[実際に足してみたソース(shinshin86/Try-TodoList-At-Vue)](https://github.com/shinshin86/Try-TodoList-At-Vue/blob/d5bb6a99e5a1d0c5039d547ea39f671c6594a4ad/.eslintrc.js)

↑のコードの14行目と、28行目から33行目までの箇所が足した箇所となります。


これで普段通り``eslint``を走らせると、prettierによるチェックが走ります。
prettierのデフォルトのルールだと、このプロジェクトでのeslintとのルールに差があるので、prettier側でめちゃくちゃエラーが出ました。
上のdiffにもある通り、ルールを変更しています。

``--fix``オプションを付けた``ESLint``を走らせると、コード整形を行ってくれます。


### Turn off ESLint's formatting rules

ESLintを使ってPrettierを実行する場合でも、別々に両方のツールを実行する場合でも、2つのフォーマット間で矛盾するルールというのが出てくると思います。
それを無効にする方法として(Prettierが気にしない他のルールを守りながら)、``eslint-config-prettier``を使う方法が提示されています。
これが二つ目。

要は、ESLintとPrettierの処理で重複する部分を無効化してくれるツールということみたい。

導入は下記の手順。

```bash
yarn add --dev eslint-config-prettier
```

``.eslintrc.json``に下記の記述を追加

```jsonnet
{
  "extends": ["prettier"]
}
```

[公式ドキュメント](https://prettier.io/docs/en/eslint.html#turn-off-eslint-s-formatting-rules)によると、これによって無効になるルールが幾つかあるけど、
Prettierと矛盾する特定のオプションでそれらを使用しない限りは[こちらのドキュメント](https://github.com/prettier/eslint-config-prettier#special-rules)を参考にそれらを戻すことができるそう。

ココらへんの細かいことについては、ちょっと実際に使ってみないとよくわからないので、後日機会見つけて試してみようと思います。

### 2つを有効にする

``eslint-plugin-prettier``は、``eslint-plugin-prettier``と``eslint-config-prettier``の両方を有効にする「推奨」設定を公開しているようです。
下記の記述を``.eslint.json``に記述します。

```json
{
  "extends": ["plugin:prettier/recommended"]
}
```

自身の場合は最終的に``.eslint.js``がこんな感じになりました。
(先程のソースに上記設定を追加したもの)

```diff
     "extends": [
       "eslint:recommended",
-      "plugin:vue/recommended"
+      "plugin:vue/recommended",
+      "plugin:prettier/recommended"
     ],
     "parserOptions": {
         "sourceType": "module"
     },
-    "plugins": ["prettier"],
     "rules": {
         "indent": [
             "error",
```

こちらの設定を使うときは上記2つのプラグインが入っている必要があるので、最初から2つを有効にするのなら下記のコマンドでインストールすればOKです。

```bash
yarn add --dev eslint-plugin-prettier eslint-config-prettier
```

## prettier-eslintを使ったやり方(追記)
eslintと併せて使う方法としては、下記のような方法もあるみたい

> prettier-eslintを使うことでprettierで整形した結果をeslint --fixに渡すことができるようになります。

[prettierの使い方 - Qiita (eslintと合わせて使う)](https://qiita.com/kiida/items/405bb07c4b52bfee0219#eslint%E3%81%A8%E5%90%88%E3%82%8F%E3%81%9B%E3%81%A6%E4%BD%BF%E3%81%86)

インストールするものは下記。

```bash
yarn add -D eslint prettier-eslint prettier-eslint-cli
```


## precommitフック

precommitフックを利用すると、prettierを実行して整形したものだけをコミットすることができるようです。

公式ページの[Prettier - Pre-commit Hook](https://prettier.io/docs/en/precommit.html)を見てみると、何種類かの方法を提案してくれていますが、今回は一番上の``lint-staged``、``husky``を使う方法を最小構成で試してみようと思います。

まずは必要なパッケージのインストール

```bash
yarn add prettier lint-staged husky --dev
```


``package.json``に``scripts``と``lint-staged``を追加するので、``package.json``は下記のようになります。

```json
{
  "scripts": {
    "precommit": "lint-staged"
  },
  "lint-staged": {
    "*.{js,json,css,md}": ["prettier --write", "git add"]
  },
  "devDependencies": {
    "husky": "^0.14.3",
    "lint-staged": "^7.0.4",
    "prettier": "^1.11.1"
  }
}
```

実際にサンプルコード書いて試してみます。

```js
const sample = () => {
  return 'hello prettier'
}

console.log(sample())
```
このような、なんの面白みもないサンプルコードを書いて、
``git add sample.js``とした後、
``yarn run precommit``すると、addされたファイルに対してのみ``prettier``を通してくれます。
あとは整形されたコードをcommitすればOKです。

```js
const sample = () => {
  return "hello prettier";
};

console.log(sample());
```
↑が整形後のコード。


ただ、こちらの方の記事を見てみると([prettierの使い方 - precommitフックを使う] (https://qiita.com/kiida/items/405bb07c4b52bfee0219#precommit%E3%83%95%E3%83%83%E3%82%AF%E3%82%92%E4%BD%BF%E3%81%86))、commit時に勝手に整形してくれているようですね。。。

Prettierの[公式ドキュメント(Pre-commit Hook)](https://prettier.io/docs/en/precommit.html)を読んでみると、use caseのところに

>Prettierの上にESLintなど、他のツールと共に使用する必要がある時などに便利です

と書かれているので、ここらへんは他のツールと連携ありきで使うものなのかもしれません。
(ここらへんの理解はまだ浅いので、もしかしたら解釈がおかしいかもしれませんが)


試しに参照させていただいた方の記事を参考に、eslintを組み合わせたやり方で実行してみたところ、コミット時に自動的に整形がされました。


### 追記

precommitフックの自動実行について、 @sounisi5011 さんよりコメントにて補足説明をいただきました！
[こちらのコメント](https://qiita.com/shinshin86/items/c8b1f6b22b1bef3074c7#comment-4834331725e20ba45bdd) を読むと、どのようにコミット時に自動整形が行われているかが理解ができます。
(非常にわかりやすく説明していただいているので`gitフック`や`husky`、`lint-staged`の理解が浅いと思われている方は一読をオススメします。→私はこのコメント読んでとても勉強になりました。)

## エディターとの連携(Vim編)

私は``Vim``ユーザなので、Vimとの連携を試してみます。

[sbdchd/neoformat](https://github.com/sbdchd/neoformat), [w0rp/ale](https://github.com/w0rp/ale), [prettier/vim-prettier](https://github.com/prettier/vim-prettier)など、複数種類があるようですが、私は[sbdchd/neoformat](https://github.com/sbdchd/neoformat)を使った方法で設定します。


私の現在のメインVim環境が``NeoVim&dein.vim``なので``plugin.toml``に下記のように記載します。

```toml
[[plugins]]
repo = 'sbdchd/neoformat'
```

プロジェクト内で``prettier``がインストールされているケースでのみ使用したいと考えているので、下記のような記述を``init.vim``に記述します。。。
が、これ、めちゃくちゃスマートじゃないね💦

一応、下記を参考にしながら書いてみていますが、自身の未熟さを呪う、そんな春の昼下がり🌸
[sbdchd/neoformat - Config [Optional]](https://github.com/sbdchd/neoformat#config-optional)


```vim
"----------------------------------------------------
" JavaScript - Prettier
"----------------------------------------------------
let g:neoformat_javascript_prettier = {
      \ 'exe': getcwd() .'/node_modules/.bin/prettier',
      \ 'args': ['--stdin', '--no-semi', '--single-quote'],
      \ 'stdin': 1,
      \ }
```

可能であれば、プロジェクト単位で設定している``prettier``を反映させた形でformatしたいのだけど、パッと良い考えが浮かんでいないので、一旦はこちらで。
良い案浮かんだら更新します。
(これだとプロジェクトルート and prettierがプロジェクトにインストールされていないと動きません😱)

## エディターとの連携(Atom編)

色々とやり方はありそうですが、私は公式が提供している[prettier-atom(Github)](https://github.com/prettier/prettier-atom)を導入することにしました。

下記のようにapmコマンドからinstallすることもできますが、

```bash
apm install prettier-atom
```

私は普通にGUI上からインストールしてしまいます。

<img width="757" alt="2018-04-198.11.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/205976/307662b0-e71b-b1ee-7e5f-cff2f40bf8c7.png">

インストールすると、依存関係上他にも必要なものがあるよとメッセージが出てくるので、諸々幾つかのパッケージもインストールしました。

<img width="487" alt="2018-04-19 8.12.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/205976/822a76a1-00b1-a78a-2e8a-1b235e37321e.png">

インストール完了すると、GUI上からPrettierの設定が確認できるので、わかりやすいですね。

<img width="780" alt="2018-04-19 8.18.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/205976/9696136b-9c2a-c484-2978-f6abd0c9d22f.png">

デフォルトだと、``ctrl + alt + f``でprettierのformatを実行するようですが、保存時に自動で実行させたり実行するkey bindingを変えたりなどは設定からできるようなので、導入もしやすそうです。

というわけで、少しずつ使っていこうと思います。



## 参照
[Prettier](https://prettier.io/)
[prettierの使い方](https://qiita.com/kiida/items/405bb07c4b52bfee0219)
[sbdchd/neoformat](https://github.com/sbdchd/neoformat)
[prettier/prettier-atom](https://github.com/prettier/prettier-atom)