JavaScript
初心者
入門
ESLint
prettier

Prettier 入門 ~ESLintとの違いを理解して併用する~

はじめに

Prettierに関しての備忘録です。

  • 「Prettierの何が便利なのかよくわからない」
  • 「ESLintと何が違うのかよくわからない」
  • eslint --fixでコード整形ができるからPrettierの必要性が感じられない」

といった人達向けに書いた記事であり

  • Prettierの基本情報、利用目的、利用方法を理解する
  • 何故ESLintだけではなくPrettierも利用するのかを理解する
  • PrettierとESLintの併用方法を理解する

ことを目的としています。

ESLint自体の説明は記載しておりませんので、ご注意ください。

解説に利用しているコードの最終形態はGitHub上にあります。

hira777/integrate-prettier-into-eslint

Prettierとは?

コードフォーマッター(ソースコードを整形してくれるツール)のこと。読み方はプリティア(のはず)。

去年リリースされたものだが、既にESLintのスター数を超えており勢いがすごい。

以下の形式にサポートしている。

  • JavaScript(ES2017も含む)
  • JSX
  • Flow
  • TypeScript
  • CSS, Less, and SCSS
  • JSON
  • GraphQL
  • Markdown(GFMも含む)

何故コードフォーマッタを利用するのか(コードを整形するのか)

  • ソースコードは綺麗に保つため(コードのスタイルの一貫性を保つため)
  • コードレビュー時に、設計や命名などの重要な箇所に集中するため(コードのスタイルの指摘に時間を割くのを防ぐため)
  • 複数のメンバーが各自の整形ルールを適用し、更新する度に余計な差分が発生することを防ぐため
  • ソースコードを綺麗にするための労力(スタイル定義の議論や時間)を費やさなくて済むため
  • ツールに任せられることはツールに任せてしまった方が今後楽になるため

Prettierを利用してみる

Prettierを利用してソースコードが整形されたファイルを出力してみる。

ディレクトリ構成

今回Prettierを利用するディレクトリ構成は以下を前提とする。

.
├── package.json
└── app.js

package.json

パッケージをローカルインストールするため、package.jsonは以下のコマンドで生成する。

npm init

or

yarn init

app.js

ソースコードを整形するファイル。

スペースの数が統一されておらず、無駄な改行が存在したりとコードが汚い状態。

整形前のapp.js
class Person{
  constructor(name) {
    this.name =   name;
  }

}


const profile = {
  name: 'soarflat', sex: 'male', location: 'Tokyo'

};

const hoge = ()=>{
  console.log('hoge');
}

const fooBar = (foo, bar) =>{
    console.log(foo);
  console.log(bar)
};

fooBar(111, 
    {
        hoge: 'hoge!'
    }
)

Prettierのインストール

npmyarnでローカルインストールする。

npm install prettier -D

or

yarn add prettier -D

ローカルインストールしたPrettierを実行するためにPATHを通す

prettierコマンドを実行できるようにするため、以下のようにPATHを通す。

export PATH=$PATH:./node_modules/.bin

※「PATHを通す」が不明な方は以下をご覧ください。

Prettierの実行

app.jsに対してprettierコマンドを実行する。ファイルを上書きするために--writeオプションをつける。

prettier app.js --write

コマンドを実行すれば、整形されたファイルが出力される。

整形後のapp.js
class Person {
  constructor(name) {
    this.name = name;
  }
}

const profile = {
  name: "soarflat",
  sex: "male",
  location: "Tokyo"
};

const hoge = () => {
  console.log("hoge");
};

const fooBar = (foo, bar) => {
  console.log(foo);
  console.log(bar);
};

fooBar(111, {
  hoge: "hoge!"
});

整形されたファイルを出力できたが

ESLintでもコード整形はできるし、結局Prettierの何が良いのかわからないため、PrettierはESLintより何が優れており、何故利用(併用)すべきかを説明していく。

何故Prettierを利用(ESLintと併用)するのか

ESLintでもeslint --fixでコード整形ができるが、Prettierのコード整形の方が優れているから。

具体的には以下の通り。

  • ESLintでは整形できないコードを整形できる
  • ESLintと比べて手軽で確実に整形できる

ESLintでは整形できないコードを整形できる

以下のような一行の文字数が長いコードはESLintでエラーが出力されるが、整形はされない。

foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne());

一方、Prettierでは以下のように整形される。

foo(
  reallyLongArg(),
  omgSoManyParameters(),
  IShouldRefactorThis(),
  isThereSeriouslyAnotherOne()
);

上記のような整形をしてくれれば、複数のメンバーがエラーに対する独自の修正を適用し、更新するたびに差分が出てしまうような事態を防ぐことができる。

そのため、Prettierを利用した方がコードのスタイルの一貫性は保たれる。

ESLintと比べて手軽で確実に整形できる

eslint --fixは設定に該当したエラーのみを整形する。そのため、設定次第ではコードを整形しきれない。整形を厳密に行うためには、多くの設定を指定する必要があり、設定自体が複雑になる(設定ファイルがすごい行数になる)可能性がある。

一方、Prettierはデフォルトのスタイル(整形ルール)が存在するため、prettierコマンドを実行するだけでコードが整形される。スタイルの変更も可能だが、こだわりがなければデフォルトのままで問題ないし、確実に整形してくれる。また、Prettierは良くも悪くも設定できる項目が少ないため、設定が複雑になる可能性が低い。

そのため、Prettierを利用した方が手軽で確実に整形できる。

PrettierはESLintよりもコード整形が優れているが

上記の理由でPrettierを利用すべきだが、Prettierはコードフォーマッタのため、ESLintのような構文チェック機能はない。

そのため、コードの整形はPrettierが行い、コードの構文チェックはESLintが行うように併用する。

ESLintとの併用

併用方法はいくつかあるが、今回はPrettierの設定をESLintで利用できるようにする。

そのため、eslint --fixを実行時に、Prettierの整形ルールでコードを整形し、整形したコードに対して構文チェックが実行されるようにする。

この方法は以下のメリットがある。

  • eslint --fixだけでコードの整形と構文チェックができる
  • 既存の.eslintrcにも、少し設定を記述するだけで利用できる

併用に必要なパッケージのインストール

上記の併用方法で必要なパッケージをインストールする。

npm install eslint eslint-config-prettier eslint-plugin-prettier -D

or

yarn add eslint eslint-config-prettier eslint-plugin-prettier -D

それぞれのパッケージの詳細は以下の通り。

  • eslint(ESLint本体)
  • eslint-config-prettier(ESLintのフォーマット関連のルールを全て無効にする、ようはPrettierが整形した箇所に関してエラーを出さなくなる)
  • eslint-plugin-prettier(PrettierをESLint上で実行する)

.eslintrcの設定

先ほどPrettierを実行したディレクトリに.eslintrc(ESLintの設定ファイル)を作成する。

そのため、ディレクトリ構成は以下のようになる。

.
├── .eslintrc
├── package.json
└── app.js

.eslintrcの内容は以下の通り

.eslintrc
{
  "env": {
    "es6": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:prettier/recommended"
  ],
  "rules": {
    "prettier/prettier": [
      "error",
      {
        "singleQuote": true,
        "trailingComma": "es5"
      }
    ]
  }
}

Prettierに関連する記述は

"plugin:prettier/recommended"

"rules": {
  "prettier/prettier": [
    "error",
    {
      "singleQuote": true,
      "trailingComma": "es5"
    }
  ]
}

である。 "singleQuote": trueなどのオプションは以下のオプションを指定できる。

Options · Prettier

また、prettierに関連するextendsは必ずextends配列内の最後に記述する。

以下のような記述だとうまく動作しないことがあるため注意。

"extends": [
  "plugin:prettier/recommended"
  "eslint:recommended",  
]

PrettierとESLintを併用した状態でeslint --fixを実行してみる

コードの整形、構文チェックができた。

git commit時にeslint --fixが実行されるようにする

上記の方法でコード整形と構文チェックが可能になったが、eslint --fixを実行しない限りコードは整形されないため、整形されていないコードがコミットされてしまう可能性がある。

これを防ぐために、エディタと連携してファイル保存時にeslint --fixを実行する手段がある(WebStormでの連携方法は後述)。個人での開発ではそれで問題ないが、複数人開発の場合、全員がそれぞれのエディタプラグインを導入するコストがかかる。

そのため、整形したコードのみを確実にコミットしたいのであればgit commit時にeslint --fixが実行されるようにする。

Gitにはコミット前に指定のスクリプトを実行できるpre-commitフックと言う仕組みがあるため、それを利用する。

pre-commitフックに必要なパッケージをインストール

npm install lint-staged husky -D

or

yarn add lint-staged husky -D

package.jsonpre-commitフックの設定を記述する

package.jsonに以下の記述を追加する。

"scripts": {
  "precommit": "lint-staged"
},
"lint-staged": {
  "*.js": [
    "eslint --fix",
    "git add"
  ]
}

記述後のpackage.jsonは以下のようになる。

package.json
{
  "name": "prettier-tutorial",
  "version": "1.0.0",
  "scripts": {
    "precommit": "lint-staged"
  },
  "lint-staged": {
    "*.js": [
      "eslint --fix",
      "git add"
    ]
  }
  "devDependencies": {
    "eslint": "^4.18.1",
    "eslint-config-prettier": "^2.9.0",
    "eslint-plugin-prettier": "^2.6.0",
    "husky": "^0.14.3",
    "lint-staged": "^7.0.0",
    "prettier": "^1.10.2"
  },
  "license": "MIT"
}

これでgit commit時にeslint --fixが実行されるようになった。

git commit時にeslint --fixが実行されるか確認する

git commit時にeslint --fixが実行され、エラーを解消しなければコミットできなくなった。

終わり

コードは綺麗に越したことはないし、手軽に導入できるので少しでも魅力に感じたら利用してみましょう。

pre-commitフックまで利用するのは堅苦しく感じる方もいると思いますので、とりあえずはコマンドで整形するかエディタと連携させれば良いと思います。

(番外編) WebStormと連携し、ファイル保存時にeslint --fixが実行されるようにする

筆者がWebStormを利用しているので、WebStormでの解説になります。他のエディタやIDEを利用している方は「エディタ名 eslint」などで検索すれば、連携方法が見つかると思います。

WebStormとの連携手順

手順は以下の通り

  • ESLintを有効にする
  • キーマップにeslint --fixの実行を登録する

ESLintを有効にする

Preferences(Winの場合はSettings)を開き、Languages and Frameworks > JavaScript > Code Quality Tools > ESLintでESLintを有効にする。

strom.jpg

キーマップにeslint --fixの実行を登録する

今回はファイル保存時にeslint --fixの実行をしたいため、⌘Sを押した時にESLintが実行されるようにする(WinはCtrl+Sだと思うが、登録方法は同じなので、Macを前提とした説明する)。

同じくPreferences上にあるKeymap項目内にFix ESLint Problemsがあるので、それを選択し、Add Keyboard Shortcutをクリックする。

storm2.jpg

Add Keyboard Shortcutをクリックするとキーマップの登録画面が表示されるので、その状態で登録したいキー(今回は⌘S)を入力する。

storm3.jpg

上記の状態でOKを押し、画面右下のOKも押してPreferencesを閉じれば連携の設定は完了。

WebStormとの連携が完了した状態で、ファイルを保存してみる

storm4.gif

ファイル保存時にコードの整形ができて、エラーも出力された。