見出し画像

Nuxt.js2.xでESLintの設定を読み解きつつ、airbnbのルールを追加設定してみた

はじめに

SSR をやりたいが、Vue.js2.x 系や Vuetify を利用した開発をしたいと思い、Nuxt.js を使った開発をやってみる事にした。開発の前には開発環境を整えるのがやっぱり重要なので、今回は CLI で Nuxt.js のプロジェクトを作成した後の ESLint の設定を確認しつつ、追加で airbnb のルールもチェックできるようにする設定をやってみたいと思う。

公式にある "yarn create nuxt-app {project-name}" でアプリケーションを構築した際の設定は以下。

create-nuxt-app v5.0.0
✨  Generating Nuxt.js project in nuxt-test
? Project name: nuxt-test
? Programming language: JavaScript
? Package manager: Yarn
? UI framework: Vuetify.js
? Template engine: HTML
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: ESLint, Prettier, Lint staged files, Commitlint
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Server (Node.js hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using typescript)
? Continuous integration: GitHub Actions (GitHub only)
? What is your GitHub username? yuta-katayama-23
? Version control system: Git

ESLint の設定

はじめにのような初期設定を行うと、ESLint の設定は以下のようになっている。

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

上記の ESLint の設定は 3 つを継承したルールになっている(その他の ESLint の設定項目についてはNode.js(ES6 で実装)における ESLint・Prettier の設定を 1 からやってみたなどを参照)。それぞれを少し整理すると、以下のようにまとめられるだろう。

  • plugin:nuxt/recommended:eslint-plugin-nuxt
    Nuxt のための ESLint プラグインで、Nuxt のための基本的な ESLint の設定をここから継承している
    .vue ファイルに対する ESLint を実行するたえに必要になるvue-eslint-parserもこのライブラリが設定してくれている。実際のコードで言うとbase.js
    ちなみに、parserOptions.parser は ESLint の configuration には存在しない(Specifying Parser Optionsを参照)が、vue-eslint-parser のparserOptions.parserによってそれが利用できるようになっているようである。

上記のように設定ができている状態で、ESLint でチェックをすると以下のように意図した通りチェックができている事が確認できる。

$ yarn lint:js
yarn run v1.22.19
$ eslint --ext ".js,.vue" --ignore-path .gitignore .

/home/study/workspace/japan-specialty-map/pages/index.vue
   94:3   warning  The "asyncData" property should be above the "created" property on line 86  vue/order-in-components
   95:9   error    Unexpected isServer in asyncData                                            nuxt/no-env-in-context
   96:13  error    'foo' is assigned a value but never used                                    no-unused-vars
   99:3   warning  The "fetch" property should be above the "created" property on line 86      vue/order-in-components
   99:11  error    Unexpected isClient in fetch                                                nuxt/no-env-in-context
  101:13  error    'foo' is assigned a value but never used                                    no-unused-vars

✖ 6 problems (4 errors, 2 warnings)
// ESLintでエラーが出るようにわざと実装したindex.vue(抜粋)
<script>
export default {
  async created() {
    const a = () => {};
    for (let index = 0; index < 10; index++) {
      await a();
    }
  },
  asyncData(context) {
    if (context.isServer) {
      const foo = "bar";
    }
  },
  fetch({ isClient }) {
    if (isClient) {
      const foo = "bar";
    }
  },
};
</script>

上記の設定でもある程度の静的解析チェックができているが、for 文内での await などパフォーマンス上問題のあるコードに関してエラーが出ないなど不十分な部分もある。そこでそれらのチェックをしてくれる airbnb のルールも継承させる設定を追加する。追加で継承させるものは@vue/eslint-config-airbnbになる。設定の手順は公式に書いてある通り。

$ yarn add @vue/eslint-config-airbnb @rushstack/eslint-patch

上記のコマンドでインストールしたら、 .eslintrc.js に require("@rushstack/eslint-patch/modern-module-resolution") と '@vue/eslint-config-airbnb' を追記すればいい。

require("@rushstack/eslint-patch/modern-module-resolution")

module.exports = {
  ...
  extends: ['@nuxtjs', 'plugin:nuxt/recommended', '@vue/eslint-config-airbnb', 'prettier'],
  ...
}

airbnb のルールが意図通り設定できているか?確かめるために、再度 ESLint のチェックを実行してみると、以下のように for 文内の await でエラー("no-await-in-loop")が出るようになっている(for 文内の awai の問題点についてはfor ループ内で await したら ESLint に too heavyweight って言われたから本当なのか試してみた  ESLint の no-await-in-loop ルールの意味を参照)。

$ yarn lint:js
yarn run v1.22.19
$ eslint --ext ".js,.vue" --ignore-path .gitignore .

/home/study/workspace/japan-specialty-map/pages/index.vue
   88:37  error    Unary operator '++' used                                                    no-plusplus
   89:7   error    Unexpected `await` inside a loop                                            no-await-in-loop
   93:3   warning  The "asyncData" property should be above the "created" property on line 86  vue/order-in-components
   94:9   error    Unexpected isServer in asyncData                                            nuxt/no-env-in-context
   95:13  error    'foo' is assigned a value but never used                                    no-unused-vars
   98:3   warning  The "fetch" property should be above the "created" property on line 86      vue/order-in-components
   98:11  error    Unexpected isClient in fetch                                                nuxt/no-env-in-context
  100:13  error    'foo' is assigned a value but never used                                    no-unused-vars

✖ 8 problems (6 errors, 2 warnings)

※parserOptions.parser の@babel/eslint-parser だが、この設定は初期段階では不要と思われる。@babel/eslint-parser というのはECMAScript の実験的な仕様「ECMAScript throw expressions」を使ってみたいので ESLint を設定してみたで触れていたように、実験的な仕様の構文をパースするためのもので、実験的な仕様の構文を利用していない場合には不要。
実際に、parserOptions.parser を削除した状態で ESLint でチェックを実行してみたが、問題なくチェックできている事が確認できた。

補足  ESLint のコマンドについて

はじめにのような初期設定を行うと、以下のように自動で script や
lint-staged の設定が行われるが、そのコマンドの意味について少し見ていきたいと思う。

{
  ...
  "scripts": {
    ...
    "lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "lintfix": "prettier --write --list-different . && yarn lint:js --fix",
    "prepare": "husky install"
  },
  "lint-staged": {
    "*.{js,vue}": "eslint --cache",
    "*.**": "prettier --check --ignore-unknown"
  },
  ...
}
  • eslint --ext ".js,.vue" --ignore-path .gitignore . 
    "eslint ." とすると、カレントディレクトリ(eslint コマンドを実行しているディレクトリ)のだいる全部に対する ESLint のチェックを実行する ただ、その中で ESLint のチェック対象を制限するために、--extというオプションで .js と .vue ファイルのみを解析対象に限定しつつ、--ignore-pathオプションで .gitignore に指定されているファイルは除外して ESLint のチェックを実行するようにしている

  • yarn lint:js --fix
    これは上記の eslint --ext .js,.vue --ignore-path .gitignore . に--fixオプションを付けて実行するコマンドで、ESLint のチェック結果で違反があり、自動で修正できるものを修正するというコマンド

  • eslint --cache
    これは lint-staged で git commit などの対象ファイルの内、.js と .vue ファイルに対して ESLint を実行するためのコマンドで、--cacheオプションにより、変更のあったファイルに対してのみ ESLint を実行するようにしている(lint-staged の詳細については依存モジュール(ライブラリ)のライセンスをチェックする仕組みを導入してみたなどを参照していただきたい)
    ※ lint-staged の方で、既に変更されたファイルに対してのみコマンドを実行するという設定ができているので、 eslint --cache とするのは冗長かもしれない(変更のあったファイルでしか ESLint でのチェックを行わないため)

まとめとして

今回は Nuxt.js2.x での環境構築として、ESLint の設定を読み解きつつ追加の設定を行ってみた。やはりこの設定のフェーズを飛ばしてしまうと、後で ESLint の設定を入れた時・最初からESLintを設定しない事で以下のような苦労をするので、最初に工数をケチらずにやるべきだろうなと改めて感じた。

  1. 既に実装されたコードが多くなると、ESLintによる修正が膨大になり、修正後に問題なく期待通りに動いているのか?の検証が難しくなる

  2. 保守をしていく上でコードの書き方のルールが静的解析のチェックルールで統一されていないことで保守がしずらい

  3. 潜在的なバグを埋め込むことになり、後で思わぬバグが出てしまう


執筆者プロフィール:Katayama Yuta
認証認可(SHIFTアカウント)や課金決済のプラットフォーム開発に従事。リードエンジニア。
経歴としては、SaaS ERPパッケージベンダーにて開発を2年経験。 SHIFTでは、GUIテストの自動化やUnitテストの実装などテスト関係の案件に従事したり、DevOpsの一環でCICD導入支援をする案件にも従事。その後現在のプラットフォーム開発に参画。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/

みんなにも読んでほしいですか?

オススメした記事はフォロワーのタイムラインに表示されます!