Next.js の ESLint Integration を調査する
2021年5月25日現在、最新の Next.js のバージョンであるv10.2.3 では、実験的機能として ESLint 統合が組み込まれている。
今後正式な機能としてリリースされる際にドキュメント化されていくものであると思うが、現在わかっている範囲でどのようなものが提供されようとしているのか調査する。
以下の Discussion に現状での ESLint 統合の利用の仕方が説明されている。
まず実際にこの通りに動かしてみる。
アプリケーションの作成
まず Next.js アプリケーションをセットアップする。
create-next-app
で TypeScript ベースな Next.js アプリケーションを作成する。
$ npx create-next-app --typescript
プロジェクト名(今回はnextjs-eslint-integration-sample
として)を入力すると Next.js のプロジェクトが作成される。
以下のコマンドを実行すると開発サーバーが立ち上がり、create-next-app のデフォルトのページが表示される。
$ cd nextjs-eslint-integration-sample
$ yarn dev
これで準備は完了
ESLint 統合を使ってみる
Discussion の手順通りに進める。
まずはnext.config.js
を作成して、eslint
フラグを有効化する。
$ touch next.config.js
module.exports = {
experimental: {
eslint: true
}
}
次に、空の ESLint 設定ファイルを作成する。
$ touch .eslintrc
ESLint の設定ファイルが空の状態で yarn build
、つまり next build
を実行すると Next.js がメッセージを表示する。
$ yarn build
yarn run v1.22.10
$ next build
info - Using webpack 5. Reason: no custom webpack configuration in next.config.js https://nextjs.org/docs/messages/webpack5
warn - You have enabled experimental feature(s).
warn - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use them at your own risk.
info - Checking validity of types
It looks like you're trying to use ESLint but do not have the required package(s) installed.
Please install eslint and eslint-config-next by running:
yarn add --dev eslint eslint-config-next
If you are not trying to use ESLint, please remove the .eslintrc file from your application.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
「ESLint を使おうとしているならパッケージが足りていないのでインストールしてね、そうでなければ.eslintrc
は削除してね」といったところ。
メッセージの言う通りにコマンドを実行してリトライしてみる。
$ yarn add --dev eslint eslint-config-next
$ yarn build
yarn run v1.22.10
$ next build
info - Using webpack 5. Reason: no custom webpack configuration in next.config.js https://nextjs.org/docs/messages/webpack5
warn - You have enabled experimental feature(s).
warn - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use them at your own risk.
info - Checking validity of types
We detected ESLint in your project and updated the .eslintrc file for you.
Failed to compile.
./pages/_app.js
3:18 Error: 'Component' is missing in props validation react/prop-types
3:29 Error: 'pageProps' is missing in props validation react/prop-types
./pages/api/hello.js
3:1 Warning: Assign arrow function to a variable before exporting as module default import/no-anonymous-default-export
./pages/index.js
60:11 Warning: Do not use <img>. Use Image from 'next/image' instead. See https://nextjs.org/docs/messages/no-img-element. @next/next/no-img-element
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
.eslintrc
になにやら書き込んで ESLint を実行してくれたらしい。
ファイルを確認してみると以下のようになっていた。
{
"extends": "next"
}
eslint-config-next
の設定をそのまま利用するようになっている。
以上で一通りの手順は終わり
バージョン情報も残しておくためにこの時点での package.json を書いておく
{
"name": "nextjs-eslint-integration-sample",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "10.2.3",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"eslint": "^7.27.0",
"eslint-config-next": "^10.2.3"
}
}
補足
- 空の ESLint 設定ファイルが
.eslintrc
でなく、.eslintrc.json
または.eslintrc.yml
のときでも同じ様に動作した -
eslint
およびeslint-config-next
がインストール済み かつ ESLint の設定ファイルが存在しないときは、next build
時に自動で設定ファイルが作られたり ESLint が実行されたりすることはなかった。 - ESLint が実行されるのはビルド時のみで、開発サーバーでは lint のエラーがある状態でも以前と変わりなく動作する。
eslint-config-next
今回登場した eslint-config-next
というパッケージについて。
以下の Discussion では、
eslint-config-next is a shareable config that bundles multiple useful plugins (next, react, and react-hooks) and can easily be included in any Next.js application’s .eslintrc file with ({ "extends": "next"})
といった説明がされている。
リポジトリは Vercel の next.js リポジトリの packages/eslint-config-next
にある。
packages/eslint-config-next/index.js
を見てみると、
-
eslint-plugin-react
の recommended -
eslint-plugin-react-hooks
の recommended -
@next/eslint-plugin-next
の recommended
なルールが有効化されており、かついくつかのルールがオーバーライドされている。
また、TypeScript ファイルに関しては overrides によって @typescript-eslint
が利用されるようになっている。
総じて、すぐに Next.js で利用できる、利用すべき ESLint 設定が揃えられているように思う。
必要であれば自身の .eslintrc
の rules をオーバーライドすればよさそう。
上記の Discussion に eslint-plugin-jsx-a11y
も eslint-config-next
に含めると良いのでは、といったコメントも寄せられている。
eslint-plugin-jsx-a11y
は create-react-app の ESLint 設定にも含められているので、業界の標準?として eslint-config-next
にもあると確かに嬉しいかもしれない。
@next/eslint-plugin-next
eslint-config-next
の中で唐突に出てきた @next/eslint-plugin-next
は、Next.js アプリケーションでの一般的な問題に焦点を当てた ESLint Plugin らしい。
eslint-plugin-next is an ESLint plugin that aims to catch common issues and problems in a Next.js application. There are a list of initial rules that this plugin will provide, but we would love to hear more suggestions.
ドキュメントのようなものはまだ存在しないので、この plugin のルールを直接見に行ってみる。
コードは eslint-config-next
と同様に nextjs リポジトリの packages/eslint-plugin-next
にある。
以下、各ルールの簡単な説明
-
no-css-tags
-
<link rel="stylesheet" href="" />
を使わないようにする
-
-
no-sync-scripts
-
<scripts>
はasync
かdefer
を使って非同期で取得するようにする
-
-
no-html-link-for-pages
-
<a>
タグの href に pages ディレクトリのパスを指定できないようにする
-
-
no-img-element
-
<img>
タグは使わずにnext/image
を使うようにする
-
-
no-unwanted-polyfillio
- Next.js によってサポートされている Polyfill.io の polyfill が重複しないようにする
-
no-page-custom-font
- page レベルで Google Font を指定しないようにする
- 単一のページでしか指定した Google Font が使われないから?
-
no-title-in-document-head
-
next/head
は document レベルではなく page レベルでしか利用しないようにする
-
-
google-font-display
- Google Font に
font-display
プロパティを設定するようにする
- Google Font に
-
google-font-preconnect
- Google Font の preconnect を有効化する
-
link-passhref
-
next/link
コンポーネントの子コンポーネントが anchor 要素ではないときにpassHref
を付けるようにする
-
-
no-document-import-in-page
-
pages/_document.js
でのみnext/document
をインポートできるようにする
-
-
no-head-import-in-document
-
pages/_document.js
ではnext/head
をインポートできないようにする
-
どれも Next.js によるアプリケーションのパフォーマンス最適化を最大化するためのルール。
Next.js で開発する上でこれらを自動で解析できるようになるのは良いことなので、積極的に使っていきたい。
今回調査のために作成したリポジトリ
Nextjs 11 がリリースされ、正式に ESLint Integration がサポートされた。
ドキュメントにも詳細が記載されているのでこのスクラップは閉じる。