( )

create-react-appで作成した雛形 + VSCodeにESLintとPrettierを導入する

開発関連技術

開発環境, VSCode, JavaScript, TypeScript, React, ESLint, Prettier


前回、DockerでReact + Swagger 環境を作ろうという記事を書いたのですが、VSCode へ ESLint 導入時に少し手間取ったので別記事にしました。
あわせてコード整形ツールである Prettier も導入したので、その手順を書いておきます。

※この記事は Qiita からの転載です。

※2021/03/22追記 eslint-plugin-prettierが非推奨になったりと情報が古くなったので、全体的に書き直しました。
※2021/08/22追記 --template typescriptで TypeScript にした場合にも対応しました。

ESLint#

静的解析ツールです。
コーディングする上でのルールを決められるので、チーム開発するうえでコードのスタイルを統一できます。

セットアップの確認#

create-react-app で作成された雛形では、すでに ESLint に関するパッケージが導入されており。
yarn.lock でreact-scriptsの依存関係となっているのを確認できます。
create-react-app を--template typescriptとしていても、同様です。

以下は[email protected]で作成した React プロジェクトの例です。

yarn.lock
※一部抜粋
[email protected]:
  version "4.0.3"
  resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.3.tgz#b1cafed7c3fa603e7628ba0f187787964cb5d345"
  integrity sha512-S5eO4vjUzUisvkIPB7jVsKtuH2HhWcASREYWHAQ1FP5HyCv3xgn+wpILAEWkmy+A+tTNbSZClhxjT3qz6g4L1A==
  dependencies:
    "@babel/core" "7.12.3"
    "@pmmmwh/react-refresh-webpack-plugin" "0.4.3"
    "@svgr/webpack" "5.5.0"
    "@typescript-eslint/eslint-plugin" "^4.5.0"
    "@typescript-eslint/parser" "^4.5.0"
    babel-eslint "^10.1.0"
    babel-jest "^26.6.0"
    babel-loader "8.1.0"
    babel-plugin-named-asset-import "^0.3.7"
    babel-preset-react-app "^10.0.0"
    bfj "^7.0.2"
    camelcase "^6.1.0"
    case-sensitive-paths-webpack-plugin "2.3.0"
    css-loader "4.3.0"
    dotenv "8.2.0"
    dotenv-expand "5.1.0"
    eslint "^7.11.0"
    eslint-config-react-app "^6.0.0"
    eslint-plugin-flowtype "^5.2.0"
    eslint-plugin-import "^2.22.1"
    eslint-plugin-jest "^24.1.0"
    eslint-plugin-jsx-a11y "^6.3.1"
    eslint-plugin-react "^7.21.5"
    eslint-plugin-react-hooks "^4.2.0"
    eslint-plugin-testing-library "^3.9.2"
    eslint-webpack-plugin "^2.5.2"
    file-loader "6.1.1"
    fs-extra "^9.0.1"
    html-webpack-plugin "4.5.0"
    identity-obj-proxy "3.0.0"
    jest "26.6.0"
    jest-circus "26.6.0"
    jest-resolve "26.6.0"
    jest-watch-typeahead "0.6.1"
    mini-css-extract-plugin "0.11.3"
    optimize-css-assets-webpack-plugin "5.0.4"
    pnp-webpack-plugin "1.6.4"
    postcss-flexbugs-fixes "4.2.1"
    postcss-loader "3.0.0"
    postcss-normalize "8.0.1"
    postcss-preset-env "6.7.0"
    postcss-safe-parser "5.0.2"
    prompts "2.4.0"
    react-app-polyfill "^2.0.0"
    react-dev-utils "^11.0.3"
    react-refresh "^0.8.3"
    resolve "1.18.1"
    resolve-url-loader "^3.1.2"
    sass-loader "^10.0.5"
    semver "7.3.2"
    style-loader "1.3.0"
    terser-webpack-plugin "4.2.3"
    ts-pnp "1.2.0"
    url-loader "4.1.1"
    webpack "4.44.2"
    webpack-dev-server "3.11.1"
    webpack-manifest-plugin "2.2.0"
    workbox-webpack-plugin "5.1.4"
  optionalDependencies:
    fsevents "^2.1.3"

設定に関してはpackage.jsonに記述があり、デフォルトではこの設定で ESLint が動作します。

package.json
"eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },

最低限のセットアップはすでに行われているので、あとはそれをカスタマイズしていくだけです。

CLI で動かしてみる#

チェックを行いたいファイルパスを指定して実行します。

コマンド例。

# JS
yarn run -s eslint './src/**/*.{js,jsx}'

# TS
yarn run -s eslint './src/**/*.{js,jsx,ts,tsx}'

自動整形までやりたい場合は--fixをつけて実行します。

コマンド例。

# JS
yarn run -s eslint './src/**/*.{js,jsx}' --fix

# TS
yarn run -s eslint './src/**/*.{js,jsx,ts,tsx}' --fix

注意点として、自動整形は必ずしも全ての問題個所を直してくれるわけではありません。
自動整形で対応できない箇所は、自分たちで直す必要があります。

VSCode エディタ上で ESLint を動作させる際は、あまりコマンドを使用しなくなりそうですが、CI でのテスト時に使用したりということがあります。
使いやすいようにpackage.jsonの scripts にコマンドを設定しておくとよいです。

TypeScript 向けの例。

package.json
"scripts": {
  .
  .
  .
  "lint:eslint": "eslint './src/**/*.{js,jsx,ts,tsx}'",
  "fix:eslint": "yarn lint:eslint --fix"
}

VSCode 上で動かす#

インストールして再起動。
特に問題なければこれだけでチェックが動作します。

ファイル保存時に自動整形を走らせたい場合は、VSCode の設定ファイルにその旨追記します。
デフォルトのフォーマッタは無効にして、ESLint によるフォーマットをかけるイメージです。

.vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "editor.formatOnSave": false,
}

ESLint の設定ファイル#

設定の定義の仕方としては、以下の4パターンがあります。

  • package.jsonの eslintConfig に書く
  • JavaScript ファイル(例 .eslintrc.js)に書く
  • JSON ファイル(例 .eslintrc.json)に書く
  • YAML ファイル(例 .eslintrc.yml)に書く

個人的な好みとしては2番目です。
別ファイルにしておいた方が、一度作成した設定を別プロジェクトで使いまわしたりしやすいです。

設定の記述方式は公式をご参照ください。

それと、ESLint のチェックから除外したいファイルがある場合は、.eslintignore ファイルを作って書いておくことで対応できます。

.eslintignore
node_modules/

ESLint の設定ファイルを対話式で作成#

ESLint の設定ファイルは対話式で作成も可能です。
まずこれで雛形を作成して、そこからカスタマイズしていくとよいです。

以下は回答の流れの例です。

yarn run -s eslint --init

ESLint をどのように使用しますか?

? How would you like to use ESLint?
  To check syntax only
  To check syntax and find problems
 To check syntax, find problems, and enforce code style

どんなモジュールを使用していますか?

? What type of modules does your project use?
 JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these

どのフレームワークを使用していますか?

? Which framework does your project use?
 React
  Vue.js
  None of these

TypeScriptは使用していますか?

? Does your project use TypeScript? No / Yes

コードはどこで実行されますか?

? Where does your code run? (Press <space> to select, <a> to toggle all, <i> to invert selection)
 Browser
  Node

プロジェクトのスタイルをどのように定義しますか?

? How would you like to define a style for your project?
 Use a popular style guide
  Answer questions about your style
  Inspect your JavaScript file(s)

どのスタイルガイドをフォローしますか?

? Which style guide do you want to follow? (Use arrow keys)
 Airbnb (https://github.com/airbnb/javascript)
  Standard (https://github.com/standard/standard)
  Google (https://github.com/google/eslint-config-google)

設定ファイルのフォーマットはどれにしますか?

? What format do you want your config file to be in? (Use arrow keys)
 JavaScript
  YAML
  JSON

npm でこれらのパッケージをインストールしますか?
(yarn でインストールしたい場合は No を選択して、案内されたパッケージを手動でインストールする必要があります)

eslint-plugin-react@^7.14.3 eslint-config-airbnb@latest eslint@^5.16.0 || ^6.1.0 eslint-plugin-import@^2.18.2 eslint-plugin-jsx-a11y@^6.2.3 eslint-plugin-react-hooks@^1.7.0
? Would you like to install them now with npm? No / Yes
  No

この回答例だと、以下のような設定ファイルが作られます。

.eslintrc.js
// TypeScript を使わないと回答した場合
module.exports = {
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "plugin:react/recommended",
        "airbnb"
    ],
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "react"
    ],
    "rules": {
    }
};
.eslintrc.js
// TypeScript を使うと回答した場合
module.exports = {
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "plugin:react/recommended",
        "airbnb"
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "@typescript-eslint"
    ],
    "rules": {
    }
};

スタイルガイドの導入#

ESLint の設定ファイルを対話式で作成時の回答にもありましたが、企業などのスタイルガイドを準拠した ESLint の共有設定が存在します。
全く一からルール設定をするのは大変なので、この共有設定を適用して、適宜カスタマイズするとよいです。

以下は Airbnb の共有設定を使用する例です。

パッケージをインストール。

yarn add -D eslint-config-airbnb

設定の extends に追加(.eslintrc.jsでの例)

extends: [
  'plugin:react/recommended',
  'airbnb', // 追記
]

トラブルシューティング#

ルート階層に設定ファイルがない場合#

VSCode の ESLint 拡張は、ワークスペースに追加したフォルダの直下に設定ファイル(.eslintrc.jspackage.jsonなど)がある前提で動作します。
直下にない場合は、VSCode の設定ファイルで別途指定する必要があります。

※例(app 直下に設定ファイルがある場合)

{
  "eslint.workingDirectories": [
	  "./app"
  ]
}

React のバージョン検知に問題がある場合#

ESLint 実行時に
eslint-plugin-react の設定で React のバージョンが指定されていません
と表示されることがあります。

Warning: React version not specified in eslint-plugin-react settings. See https://github.com/yannickcr/eslint-plugin-react#configuration .

ESLint の設定ファイルに以下を追記することで、バージョンを自動検知させることが可能です。

.eslintrc.js
settings: {
  react: {
    version: 'detect'
  }
}

しかし、Docker コンテナの中に Node.js 環境があるが、ローカルの VSCode 上で ESLint 拡張を動かしている(ローカルに Node.js 環境がない)。
などといった、環境によって次の Warning が出ることもあります。

Warning: React version was set to "detect" in eslint-plugin-react settings, but the "react" package is not installed. Assuming latest React version for linting.

上記のような環境においては、さすがにバージョン検知ができないようです。

この場合は ESLint の設定に、明示的にバージョンを指定することで対応できます。

.eslintrc.js
settings: {
  react: {
    version: '17.0.2'
  }
}

@typescript-eslint/typescript-estree のサポートバージョン外の場合#

TypeScript のバージョンにより、@typescript-eslint/typescript-estree がサポートしているバージョンでないとの Warning が表示されることがあります。

=============

WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.

You may find that it works just fine, or you may not.

SUPPORTED TYPESCRIPT VERSIONS: >=3.3.1 <4.2.0

YOUR TYPESCRIPT VERSION: 4.3.5

Please only submit bug reports when using the officially supported version.

=============

あくまで Warning のため、ESLint 自体は動作します。
気になる方は、バージョンを合わせる。
そのままのバージョンを使う方は、そのバージョンではバグレポート受付に対応していないことを理解したうえで使用しましょう。

Prettier#

幅広いファイル形式に対応したコードフォーマッタです。
ESLint とあわせて導入しておくと、さらなるコードの品質向上に繋がります。

react-scriptsの依存関係に Prettier に関するものはないので、追加でライブラリをインストールしていく必要があります。

連携セットアップ#

ライブラリインストール。

yarn add -D prettier eslint-config-prettier

ESLint の設定ファイルに追記。

.eslintrc.js
extends: [
  'plugin:react/recommended',
  'airbnb',
  'prettier', // 追記
],

ESLint と Prettier はルール競合することがあるので、eslint-config-prettier を適用することで競合するルールを無効化して調整します。
その性質上、追加するのは extends の最後にしてください。

ちなみに eslint-config-prettier は、競合しているルールがないかチェックする CLI ツールを持っていたりします。

# JS
yarn run -s eslint-config-prettier './src/**/*.{js,jsx}'

# TS
yarn run -s eslint-config-prettier './src/**/*.{js,jsx,ts,tsx}'

問題なければ以下のような表示になります。

No rules that are unnecessary or conflict with Prettier were found.

CLI で動かしてみる#

チェックを行いたいファイルパスを指定して実行します。

# JS
yarn run -s prettier --check './{public,src}/**/*.{js,jsx,html,gql,graphql,json}'

# TS
yarn run -s prettier --check './{public,src}/**/*.{js,jsx,ts,tsx,html,gql,graphql,json}'

自動整形までやりたい場合は--writeをつけて実行します。

# JS
yarn run -s prettier --check './{public,src}/**/*.{js,jsx,html,gql,graphql,json}' --write

# TS
yarn run -s prettier --check './{public,src}/**/*.{js,jsx,ts,tsx,html,gql,graphql,json}' --write

このコマンドも ESLint の時と同様に、package.jsonの scripts に追加しておくとよいです。

TypeScript 向けの例。

package.json
"scripts": {
  .
  .
  .
  "check:prettier": "prettier --check './{public,src}/**/*.{js,jsx,ts,tsx,html,gql,graphql,json}'",
  "fix:prettier": "yarn check:prettier --write",
}

ESLint とセットで1コマンド実行したい場合は、下記のようにする手もあります。

TypeScript 向けの例。

package.json
"scripts": {
  .
  .
  .
  "lint-check": "yarn lint:eslint && yarn check:prettier",
  "lint:eslint": "eslint './src/**/*.{js,jsx,ts,tsx}'",
  "check:prettier": "prettier --check './{public,src}/**/*.{js,jsx,ts,tsx,html,gql,graphql,json}'",
  "fix": "yarn fix:eslint && yarn fix:prettier",
  "fix:eslint": "yarn lint:eslint --fix",
  "fix:prettier": "yarn check:prettier --write",
}

VSCode 上で動かしてみる#

インストールして必要に応じて再起動。

VSCode の設定ファイルに以下を追記。

.vscode/settings.json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "[javascript]": {
    "editor.formatOnSave": true
  },
  "[javascriptreact]": {
    "editor.formatOnSave": true
  },
  "[json]": {
    "editor.formatOnSave": true
  },
  // TypeScript の場合は以下も
  "[typescript]": {
    "editor.formatOnSave": true
  },
  "[typescriptreact]": {
    "editor.formatOnSave": true
  },
}

VSCode のデフォルトのフォーマッタとして Prettier を設定。
加えて、上記3つのファイル形式において、保存時に自動整形が動作するようにしています。

Prettier の設定ファイル#

設定の定義の仕方としては、以下の6パターンがあります。

  • package.jsonの prettier に書く
  • .prettierrcファイルに書く
  • JavaScript ファイル(例 .prettierrc.js)に書く
  • JSON ファイル(例 .prettierrc.json)に書く
  • YAML ファイル(例 .prettierrc.yml)に書く
  • TOML ファイル(例 .prettierrc.toml)に書く

個人的な好みとしては2番目です。
ESLint と同様に別ファイルにしておいた方が、一度作成した設定を別プロジェクトで使いまわしたりしやすいです。

設定の記述方式は公式をご参照ください。

それと、Prettier のチェックから除外したいファイルがある場合は、.prettierignoreファイルを作って書いておくことで対応できます。

補足:glob を Windows にも対応させる(※2021/11/17追記)#

上記では ESLint、Prettier のコマンドで、実行パスである glob 部分をシングルクォートで囲うようにしていました。
Mac や Linux といった Unix 環境であれば、これで問題ないのですが、Windows だとうまく動作しません。

Windows にも対応させる場合は、シングルクォートでなくダブルクォートで囲う必要があります。

package.json
"scripts": {
  .
  .
  .
  "lint-check": "yarn lint:eslint && yarn check:prettier",
  "lint:eslint": "eslint \"./src/**/*.{js,jsx,ts,tsx}\"",
  "check:prettier": "prettier --check \"./{public,src}/**/*.{js,jsx,ts,tsx,html,gql,graphql,json}\"",
  "fix": "yarn fix:eslint && yarn fix:prettier",
  "fix:eslint": "yarn lint:eslint --fix",
  "fix:prettier": "yarn check:prettier --write",
}

参考リンクまとめ#