Closed10

Next.js の ESLint Integration を調査する

thincellerthinceller

2021年5月25日現在、最新の Next.js のバージョンであるv10.2.3 では、実験的機能として ESLint 統合が組み込まれている。
今後正式な機能としてリリースされる際にドキュメント化されていくものであると思うが、現在わかっている範囲でどのようなものが提供されようとしているのか調査する。

thincellerthinceller

アプリケーションの作成

まず 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

これで準備は完了

thincellerthinceller

ESLint 統合を使ってみる

Discussion の手順通りに進める。
まずはnext.config.jsを作成して、eslintフラグを有効化する。

$ touch next.config.js
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 を実行してくれたらしい。
ファイルを確認してみると以下のようになっていた。

.eslintrc
{
  "extends": "next"
}

eslint-config-nextの設定をそのまま利用するようになっている。


以上で一通りの手順は終わり

thincellerthinceller

バージョン情報も残しておくためにこの時点での package.json を書いておく

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"
  }
}
thincellerthinceller

補足

  • 空の ESLint 設定ファイルが .eslintrc でなく、.eslintrc.json または .eslintrc.yml のときでも同じ様に動作した
  • eslintおよびeslint-config-nextがインストール済み かつ ESLint の設定ファイルが存在しないときは、 next build 時に自動で設定ファイルが作られたり ESLint が実行されたりすることはなかった。
  • ESLint が実行されるのはビルド時のみで、開発サーバーでは lint のエラーがある状態でも以前と変わりなく動作する。
thincellerthinceller

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"})

といった説明がされている。
https://github.com/vercel/next.js/discussions/24900

リポジトリは Vercel の next.js リポジトリの packages/eslint-config-next にある。
https://github.com/vercel/next.js/tree/canary/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-a11yeslint-config-next に含めると良いのでは、といったコメントも寄せられている。
eslint-plugin-jsx-a11y は create-react-app の ESLint 設定にも含められているので、業界の標準?として eslint-config-next にもあると確かに嬉しいかもしれない。
https://github.com/vercel/next.js/discussions/24900#discussioncomment-741770

thincellerthinceller

@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.

https://github.com/vercel/next.js/discussions/24900

ドキュメントのようなものはまだ存在しないので、この plugin のルールを直接見に行ってみる。
コードは eslint-config-next と同様に nextjs リポジトリの packages/eslint-plugin-next にある。
https://github.com/vercel/next.js/tree/canary/packages/eslint-plugin-next/lib/rules

以下、各ルールの簡単な説明

  • no-css-tags
    • <link rel="stylesheet" href="" /> を使わないようにする
  • no-sync-scripts
    • <scripts>asyncdefer を使って非同期で取得するようにする
  • 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-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 で開発する上でこれらを自動で解析できるようになるのは良いことなので、積極的に使っていきたい。

このスクラップは2021/06/18にクローズされました