技術メモ

プログラミングとか電子工作とか

Nuxt.jsでESLint(Prettier)が使いたいけどよくわかんなくなったのでまとめた

f:id:ysmn_deus:20190810104633p:plain

こんにちは、靖宗です。
特にチームでのJavaScript案件はやってないんですが、チームじゃなくてもESLintを導入するべきなんじゃないかと感じ、導入してみることにしました。
とはいえよくわかんないので記事にしながら学習します。
とりあえず今回はTypeScriptを対象としていません。別の記事にまとめます。

ESLint

ESLintとは?

ESLintは2013年の6月にNicholas C. Zakasさん(オライリーの「ハイパフォーマンスJavaScript」などの著者)によって作られたツールです。
実行前にJavaScriptソースコードを解析するもので、基本的な間違いを検出するだけでなく、フォーマット(セミコロンの有無など)も検出して指摘してくれます。
まさにチーム開発では重宝されるツールでしょう。

他に似たツールにJSLintなどがあったのですが、最近ではあまり聞かなくなりました。
基本的にはESLint一択なんでしょう。

導入方法

使うプロジェクトでnpmかyarnでインストールすれば良さげです。

npm install eslint --save-dev

or

yarn add -D eslint

設定ファイルを作らなければただ容量を食ってるだけの代物ですが、基本準備はこれだけです。
ただ、今回はNuxt.jsで使う想定なので、nuxtのプロジェクトを作成しながら設定していきたいと思います。

Nuxt.jsのプロジェクトを作成する

まずはコマンドでnuxtのプロジェクトを作成します。

yarn create nuxt-app eslint-test

プロジェクト名はeslint-testとしました。

...
? Choose linting tools ESLint, Prettier
? Choose test framework Jest
? Choose rendering mode Universal (SSR)

nuxtのウィザードに従ってESlintとPrettierを有効にしました。
Jestまで色々書くか微妙ですが、とりあえず導入しておきます。

.eslintrc(ESLintの設定ファイル)の作成

.eslintrcを作成します。
この設定ファイルは6種類の記述手段があるらしく

  • .eslintrc.js
  • .eslintrc.yaml
  • .eslintrc.yml
  • .eslintrc.json
  • .eslintrc
  • package.json

というファイルに記述することができるそうです。
package.jsonに記述する方法はファイルが少なくて済むんですが、煩雑になるので避けた方が良いのでは?と思います。
nuxtなどで用意すると.eslintrc.jsが勝手に生成されるので、基本これで行きます。

ちなみに一番最初に書かれている中身がこれ

module.exports = {
  root: true,
  env: {
    browser: true,
    node: true
  },
  parserOptions: {
    parser: 'babel-eslint'
  },
  extends: [
    '@nuxtjs',
    'prettier',
    'prettier/vue',
    'plugin:prettier/recommended',
    'plugin:nuxt/recommended'
  ],
  plugins: [
    'prettier'
  ],
  // add your custom rules here
  rules: {
  }
}

とりあえず詳細は後回しにするとして、設定ファイルはcreate nuxt-appで用意すれば既に生成されています。

ESLintの実行

試しにstore/index.jsを生成して適当な事を書いてみます。

function helloWorld() {
  console.log('hello!')
}

helloWorld();

ESLintをコマンドから実行してみます。
ESLintは

eslint [JavaScriptファイル名]

で実行可能です。
プロジェクトのルートフォルダで

node_modules/.bin/eslint store/index.js

を実行します。

プロジェクトのパス/eslint-test/store/index.js
  5:13  error  Delete `;`  prettier/prettier

✖ 1 problem (1 error, 0 warnings)
  1 error and 0 warnings potentially fixable with the `--fix` option.

prettier/prettierのルールでセミコロンが着いてる!しばくぞ!と怒られています。どうやらprettierの方ではデフォルトでセミコロンは悪役の様です。
こういったフォーマットの規約などをチェックするのがESLintの役割です。

--fix

ちなみにエラー分を見ると「1 error and 0 warnings potentially fixable with the --fix option.」とあります。こういう場合は

node_modules/.bin/eslint store/index.js --fix

と実行すると、該当箇所を良い感じに修正してくれます。
ただし、後述するようにこの辺は全部Prettierに任せようと思います。
(とは言っても実行されるコマンドは同じみたいですが)

ESLintの設定ファイル

ここでようやくESLintの設定ファイルに関して見ていきましょう。

ルールの追加(rules)

ESLintのルールを追加するには設定ファイルに追記していきます。
細かい設定は.eslintrc.jsrulesに記載します。

...
    "rules": {
        "semi": ["error", "always"]
    }

設定項目はESLintの公式サイトや諸先輩方の設定ファイルを参考にさせて貰うとして、基本的には
設定項目: [設定のオンオフ, オプションの値]
という構成になります。設定のオンオフはerror(あったらエラーを送出する), warn(警告だけする), off(無視)が設定できます。
オプションは設定項目で色々ですが、例えばsemiではalwaysにすると「無いと怒る」、neverにすると「あると怒る」といった感じです。

ルートの指定(root)

nuxtのウィザードでESLintの設定ファイルを生成するとrootという設定項目があります。
これは「プロジェクトルートがここなので、これ以上親の階層は気にしなくて良い」という設定のようです。
ESLintは階層ごとに配置することもできるそうなので(たぶんそんなに頻繁にすることはない)、どこまで親をたどるのか明確にするときに設定するのでしょう。
基本そのままで大丈夫そうです。

環境の設定(env)

初期設定ではbrowsernodeがtrueになっていると思います。
スクリプト実行環境を指定出来るオプションのようで、ブラウザとNode.jsで実行されることを想定しています。
基本このままでも大丈夫そうですが、念のためes6jestを追加しておきます。

...
  env: {
    browser: true,
    node: true,
    es6: true,
    jest: true
  },
...

parserOptionsの設定(parserOptions)

上記でes6を追加しましたが、それだけではimport文などのES Moduleの機能までチェックできないようです。
そこで、設定ファイルの項目parserOptionsを設定していきます。

...
  parserOptions: {
    "sourceType": "module"
  },  
...

parserOptionsの項目に"sourceType": "module"を追加します。
これでES6に対応したはずです。

また、デフォルトではbabel-eslintが設定されていますが、いろんな設定を付加してくれる反面いろいろありすぎて推奨されない見方もあるそうなので、個人的な判断ですが削除します。
ちなみに、たぶんなんですがbabel-eslintを設定しておけばes6の記述と上記のmoduleの記述は不要になると思います。お好きな方をどうぞ。

ついでにJSXもチェックできるようにしておきます。

...
  parserOptions: {
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
...

nuxtなんであんま使わないと思いますが。

拡張ルールセット(extends)

ライブラリなど既に定義されているルールを取り込みたい時があります。むしろそれだけで事足りる事が多いんじゃないでしょうか?
そういうときの設定項目としてextendsがあります。nuxtのデフォルトでは何種類か指定されていると思います。

基本的な流れとしては

  • npmかyarnでルールを追加する
  • "extends"に追記する

といった感じです。楽勝ですね。
試しにかの有名なairbnbのルールを適応してみます。パッケージはeslint-config-airbnb-baseです。

yarn add -D eslint-config-airbnb-base

お次にeslintrcに追記。

...
  extends: [
    'airbnb-base',
    '@nuxtjs',
    'prettier',
    'prettier/vue',
    'plugin:prettier/recommended',
    'plugin:nuxt/recommended'
  ],
...

一番上に追記したのは、'plugin:prettier/recommended'の設定が後ろに回さないとうまく動かない事があるという噂を聞いたことがあるからです。
この噂に従い、基本的に後から追加したものは上から順に追記していきます。(ここは曖昧なので気になる方は調べて下さい。)

プラグイン(plugins)

先ほどのextendsのなかにplugin:prettier/recommendedなどplugin:で始まるものがあります。
これらはpluginsの項目で設定したプラグインの推奨設定で、プラグインを導入すると使えるルールだそうです。
全部extendsでどうにかならんの?という気がしないでもないんですが、おそらく内部構造的にプラグインとして別途読み込まなければならないルール(たとえば、上記のES6なんかはES Moduleの為にparserOptionsが必要になったのは内部構造によるもの)の際にはpluginに追記する必要があるんでしょう。
このへんは導入するルールによるものかと思います。その都度確認しましょう。

今回はnuxtの為に導入しているので、vueのルールを追加します。
なんでデフォルトで入らないか謎ですが、追加で加えていきます。

yarn add -D eslint-loader eslint-plugin-vue

大体セットでeslint-loaderも追加してるんですが、ホットリロードの為だと思います。
設定ファイルを書き換えます。

...
  extends: [
    'airbnb-base',
    '@nuxtjs',
    'prettier',
    'prettier/vue',
    'eslint:recommended',
    'plugin:vue/recommended',
    'plugin:nuxt/recommended',
    'plugin:prettier/recommended'
  ],
  plugins: [
    'vue',
    'prettier'
  ],
...

'plugin:vue/recommended'を追加したついでに'eslint:recommended'も追加しました。

ESLintの設定はだいたいこんなもんで良さそうです。

Prettier

PrettierはESLintと併用されることの多いソースコードを整形してくれるツールです。
要するにeslint --fixのつよいバージョンといったところでしょうか。
eslintだけでもええやん!て気もするんですが、どうも整形機能としてはPrettierの方が優れているらしく、併用するひとが多いイメージです。
冗長なのが嫌いな方は別に導入しなくても良いと思います。(チェック自体はESLintがやってくれるので)

導入方法

nuxtのウィザードで導入すると設定は既に完了しています。
後から導入する場合はeslint-config-prettiereslint-plugin-prettierをyarnかnpmでインストールすれば大丈夫だと思います。
設定に関しては

...
  extends: [
...
    'prettier',
    'prettier/vue',
...
    'plugin:prettier/recommended'
  ],
  plugins: [
...
    'prettier'
  ],
...

が該当します。

Prettierのルール

Prettierはあくまで補助ツールなので、全ての構文チェックなどはしていません。
イメージとしてはESLintの苦手な整形部分"だけ"を担当しているツールという認識が正しそうです。
なので、extendsの'plugin:prettier/recommended'を一番最後に持ってこないとPrettierで整形したあとにESLintで怒られる構文になったりするので、必ずこの設定は最後に書きましょう。

また、prettierの設定はESLintのrulesに記載することができ、

...
  rules: {
    "prettier/prettier": [
      "error",
      {
        "semi": true
      }
    ]
  }
...

と書くことで、ESLintでセミコロン無しを警告するし、Prettierでコードフォーマットする際にセミコロンを追加したりできます。
基本的にESLintでもPrettierでも指定出来る設定はPrettierで設定するのが良さそうです。(どうせ上書きされるので)
Prettierで指定出来るオプションは下記の通りです。

prettier.io

その他

大体上記までで設定などは完了なのですが、ESLintやPrettierはファイルウォッチャーなどで「保存したら勝手に整形する」といった設定が望ましいです。(いちいちコマンド実行するのはめんどい)
nuxt公式のホットリロードを設定しておけばローカルでサーバーを動かしている際にチェックできるのでそれで良いと思いますが、気になる方はお使いのIDEのファイルウォッチャーにeslintのコマンドを登録するのをお勧めします。

参考

eslint.org prettier.io qiita.com qiita.com qiita.com yokotakenji.me