create-react-appをベースに作っているWebアプリに、途中からeslint-config-airbnbの設定およびコード整形ツールのprettierを入れたくなることがあり、想定以上に苦戦したのでメモ。
なお、便宜上0からセットアップするような形で書いている(検証している)が、ある程度動いているものに導入して移行するようなケースを想定している。
0. 前提条件など
検証環境:
- Linux(Ubuntu20.04LTS)
- node 14.16.0
- npm6.14.11
nodejsまわりのパッケージインストール・管理はyarnではなくnpmを使って行っている。
1. 構築手順
1-1. create-react-app
最新版(執筆時: 4.0.3)ではグローバルインストールが非推奨になった(参考: 公式README)ので、以下のように適当なディレクトリ上にcreate-react-appをインストールする:
mkdir tmp
cd tmp
npm init -y
npm i create-react-app
上記の例ではtmp/
にcreate-react-appがインストールされる。
実際にアプリ(gitプロジェクト)を作る場所をtmpの下に作る場合はnpx create-react-app hoge
などのようにすれば良いが、今回は外側に作りたかったので例えば以下のようにする
# create-react-appをインストールしてあるtmpの上のディレクトリへ移動
cd ..
# tmp下の実行ファイルの絶対パスを指定してcreate-react-appを実行
tmp/node_modules/.bin/create-react-app path/to/test-app
上記のようにすると指定したパスにtest-app
という名前でreactアプリが作成される:
cd path/to/test-app; tree -a -L 1
# .
# ├── .git
# ├── .gitignore
# ├── README.md
# ├── node_modules
# ├── package-lock.json
# ├── package.json
# ├── public
# └── src
1-2. eslint
上記で作ったtest-app
に移動し、eslintの設定を行う。
eslintはデフォルトでcreate-react-appで生成されたアプリ内に含まれているため、そのままnpx
で実行出来る。
オススメ設定などはnpx eslint --init
で自動的に設定することができ、今回は人気の高そうなairbnb設定を入れてみる
npx eslint --init
# 対話形式で色々聞かれるので、今回は以下のように設定
? How would you like to use ESLint? …
▸ To check syntax, find problems, and enforce code style
? What type of modules does your project use? …
▸ JavaScript modules (import/export)
? Which framework does your project use? …
▸ React
? Does your project use TypeScript?
▸ No
? Where does your code run? … (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
? How would you like to define a style for your project? …
▸ Use a popular style guide
? Which style guide do you want to follow? …
▸ Airbnb: https://github.com/airbnb/javascript
? What format do you want your config file to be in? …
▸ JavaScript
? Would you like to install them now with npm?
▸ Yes # yarnを使う人はNo
これにより、開発用パッケージ(devDependencies
)にeslint関係のものがいくつかインストールされ、.eslintrc.js
が生成される。しかし、そのままだと不都合な部分もあるのでここなどを参考に次のように編集しておく:
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'plugin:react/recommended',
'airbnb',
'react-app', // 手動で追加
'react-app/jest', // 手動で追加
],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: 'module',
},
plugins: [
'react',
],
rules: {
'react/react-in-jsx-scope': 'off', // 手動で追加: suppress errors for missing 'import React' in files
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }], // 手動で追加: allow jsx syntax in js files (for next.js project), should add ".ts" if typescript project
},
};
↑で"手動で追加"と入れている部分がデフォルトで生成されているものに手を加えた箇所。
extends
部分について、実はcreate-react-appにより生成されたpackage.json
内にデフォルトでeslintの設定があるため、その部分を移動させたもの。
...
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
...
上記部分を.eslintrc.js
に移し、package.json
からは不要(優先順位的に読み込まれない、参考)ので消しておく。
rules
部分について、
-
'react/react-in-jsx-scope': 'off'
- 例えば分割されて呼び出されるソースコードなどでは必ずしも明示的に
import React from 'react'
を行わなくても良い
- 例えば分割されて呼び出されるソースコードなどでは必ずしも明示的に
-
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }]
- デフォルトでは拡張子が
.js
のファイルでjsxを使うとエラーになるため、それを抑制する - create-react-appがデフォルトで作る
App.js
が上記エラーに対象になり、不便なため
- デフォルトでは拡張子が
ここまでである程度は設定出来ているが、eslintでエラーが出る状況だとnpm run start
やnpm run build
が通らない:
npm run start
# 以下のようなエラーが出て実行(コンパイル)出来ない
Failed to compile.
src/App.js
Line 10:16: `code` must be placed on a new line react/jsx-one-expression-per-line
Line 10:39: ` and save to reload. ` must be placed on a new line react/jsx-one-expression-per-line
src/index.js
Line 11:34: Missing trailing comma comma-dangle
src/reportWebVitals.js
Line 1:25: Expected parentheses around arrow function argument arrow-parens
Line 3:32: Expected a line break after this opening brace object-curly-newline
Line 3:74: Expected a line break before this closing brace object-curly-newline
Search for the keywords to learn more about each error.
厳格にやる場合はこれが正しい挙動だが、既存プロジェクトに途中から導入する、移行するといったケースでは正直かなり不便である。(更にeslintの設定に過不足があるケースも考えられる。)そこで、アプリの実行やビルドは許容するようにしたい。
上記の問題に対しては、developmentおよびproduction用の環境変数を設定して対処する:
- 公式ドキュメントより:
今回はnpm run start
とnpm run build
両方を実行出来るようにするため、以下の2つのファイルを作成してプロジェクトのルートディレクトリに配置する:
SKIP_PREFLIGHT_CHECK=true
ESLINT_NO_DEV_ERRORS=true
EXTEND_ESLINT=true
(↑開発時のみの設定、EXTEND_ESLINT=true
は不要かも?)
DISABLE_ESLINT_PLUGIN=true
(プロダクション用ビルド時のみの設定、eslintのエラーを全無視するので本来良くないが、移行時などでは暫定的にOKとする)
とりあえず以上の設定でeslintの導入をしつつ、実行やビルドは出来るようになった。
1-3. prettier
実際に動かしているアプリなどだと上記まででおびただしい数のerrorが出てくる。いちいち手作業で直すのも面倒だし、コード整形自体はeslintよりもprettierの方が得意そうなので簡単に設定してみる。
まずはprettierと、eslintとの連携ツール(eslint-config-prettier)のインストール:
npm i -D prettier eslint-config-prettier
なお、eslint-plugin-prettierは最近非推奨になったとの話なので入れないでおく。
次に、
などを参考にして必要に応じて.prettierrc.js
などを用意し、prettier用の設定を作成:
module.exports = {
printWidth: 80,
tabWidth: 2,
singleQuote: true,
semi: true,
trailingComma: 'all',
};
次に、prettierを実行しやすいようにpackage.json
のscripts
部分に"format": "prettier --write ./src/**/*.{js,jsx}"
を入れておく:
...
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"format": "prettier --write ./src/**/*.{js,jsx}" // 追加
},
...
これで、
npm run prettier
のように実行することでsrc/
以下の*.js
, *.jsx
の拡張子のファイルがprettierで整形されるようになる。
また、prettierで整形する部分についてはeslintの設定を切るようにすることが出来る(というか、eslintとpretterで競合しないようにするためにあった方が良いらしい)。
これは先程インストールしたeslint-config-prettier
を使って行うものであり、今回であれば.eslintrc.js
のextends
の最後にprettier
を追加すれば良い(※参考):
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'plugin:react/recommended',
'airbnb',
'react-app',
'react-app/jest',
'prettier', // 追加
],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: 'module',
},
plugins: [
'react',
],
rules: {
'react/react-in-jsx-scope': 'off',
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
},
};
これによってeslintの出すエラー・警告からprettierで整形する部分が除外される。
2. まとめ
create-react-appで生成したものに対して、手作業でファイルの編集や追加をいくつかやったので最後に簡単にまとめておく。
上記の手順を実行後のプロジェクトのファイルは以下のような感じ:
tree -a -L 1
.
├── .env.development # 追加
├── .env.production # 追加
├── .eslintrc.js # 追加、変更
├── .git
├── .gitignore
├── .prettierrc.js # 追加
├── README.md
├── node_modules
├── package-lock.json # 変更(但し、自動的に編集されるので意識しない)
├── package.json # 変更
├── public
└── src
各ファイルの変更・追加内容は基本的にこれまでの記述の通り。
但し、package.json
についてはいきなり最終形のものを置いてnpm i
などを実行すればこれまでの手順のnpm i -D ***
などを省くことが出来る。そこで、以下に最終的なpackage.json
を掲載する:
{
"name": "test-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^12.8.3",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.3",
"web-vitals": "^1.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"format": "prettier --write ./src/**/*.{js,jsx}"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"eslint": "^7.22.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"prettier": "^2.2.1"
}
}
3. 今後の課題など
-
node-sass
によりsassを導入したりcss-moduleを使いつつ、prettierによる整形をcssやscssにも適用したい(stylelint
など?)- →この記事を参照
- jsdocの導入
- ドキュメントのビルド
- jsdoc部分のフォーマットチェックもlinterで行う
-
eslint-plugin-jsdoc などが使えそう
- typescriptを使う場合、eslint-plugin-tsdoc などが使えそう
-
git commit
するときに自動でeslint --fix
とprettier --write
を対象ファイルにかける- https://prettier.io/docs/en/precommit.html のようにいくつか選択肢がありそう
- typescriptを使った場合(
create-react-app --template typescript
)で同様の設定を出来るようにする -
create-react-app
だけでなく、nextjsやgatsbyなど他のフレームワークでも同様のことが出来ると嬉しい
など
(追記)
eslint --fix
eslint自体にもフォーマット機能があり、例えばpackage.json
のscripts
に
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"eslintfmt": "eslint --fix ./src/**/*.{js,jsx}" // 追記
},
のように追記しておき、
npm run eslintfmt
のようにして実行する事ができる。
修正内容はeslintの設定次第だが、varやletを適切にconstなどに変える、などprettierでは出来ないような修正もやってくれたりする。
ただ、筆者の環境だと行末に余分な空白が入ったり、みたいなことも起こったりする。
設定が悪いだけかもしれないが、単純な整形自体はprettierの方が得意な気がするので、個人的には
- eslintで修正 → prettierで再整形
のような感じで両方使って整形している。
.prettierignore
, .eslintignore
上記の設定だと、src/
の下にあるファイル全てがeslint, prettierをかける対象となるが、
自動生成されたjsファイルなど、編集したくないものが対象内になってしまうことがある。
そこで、
- https://prettier.io/docs/en/ignore.html
- https://eslint.org/docs/user-guide/configuring/ignoring-code#the-eslintignore-file
を参考に、
.gitignore
のような感覚で.prettierignore
および.eslintignore
ファイルをプロジェクトのルートディレクトリに配置すれば対象から除外することが出来る。
参考
-
https://qiita.com/h-yoshikawa44/items/14a114da903fb0eff886#%E5%8F%82%E8%80%83
-
eslint比較(airbnb, google, standard)