0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

テンプレート作成用のNext.js の ESLintとPrettier、turborepo、husky

Last updated at Posted at 2024-04-09

※この記事はvns_templateを作るために書きました。
2024年5月2日


今回設定したツールのコマンドリスト

pnpm run lint
pnpm run lint:debug
pnpm run lint:fix

pnpm run prettier-fix

これらのコマンドを
huskyをつかって、
コミット時とプッシュ時に自動実行させます。


プラグインのインストール

pnpm i -D @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-import eslint-plugin-unused-imports eslint-plugin-storybook

↑のリスト

@typescript-eslint/parser
@typescript-eslint/eslint-plugin
eslint-plugin-react
eslint-plugin-react-hooks
eslint-plugin-import
eslint-plugin-unused-imports
eslint-plugin-storybook


ESLint

Next.js 公式ドキュメント App Router用
Configuring: ESLint | Next.js

ESLint v9がリリースされていますが、Next.jsではそのサポートに追いついていないようなので、v8を利用します。

ESLint v8がサポートしているTypeScriptのバージョンは5.3.3までです。

SUPPORTED TYPESCRIPT VERSIONS: >=4.3.5 <5.4.0

microsoft/TypeScript: TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://github.com/Microsoft/TypeScript

バージョンダウンしておきます。

pnpm add typescript@5.3.3 --save-dev

pnpm install --save-dev eslint @eslint/js

package.jsonファイルもそれに合わせておきます。

package.json
    "typescript": "5.3.3"

ESLintの設定ファイル

.eslintrc.jsonファイルの作成

touch .eslintrc.json

.eslintrc.json
{
  "extends": "next/core-web-vitals"
}

next/core-web-vitals はNext.js専用のESLint設定です。
next/core-web-vitals はNext.jsに組み込まれています。

.eslintignoreファイルの作成

touch .eslintignore

.eslintignore
# config
.eslintrc.json
.prettierrc
next.config.js
tailwind.config.js
tsconfig.json
postcss.config.js

# build dir
build/
bin/
obj/
out/
.next/

# 自動生成されたファイル
package-lock.json
pnpm-lock.yaml

# Storybook
*.stories.ts
*.stories.tsx

# CSSファイル
*.css

# mdxファイル
*.mdx

# すべての画像ファイルを除外する
**/*.png
**/*.jpg
**/*.jpeg
**/*.gif
**/*.ico

node_modules
public

# shadcn/ui ※shadcn/uiのインストール場所なので、eslintの効果範囲に含めないようにします。
src/components/ui/

# supabaseの型ファイル
# ※型ファイルは自動生成なので、eslintの効果範囲に含めないようにします。
types_db.ts
src/types/**


eslint-config-next

デフォルト構成 ( eslint-config-next) には、Next.js ですぐに使用できる最適な lint エクスペリエンスを実現するために必要なものがすべて含まれています。

このルールには

  • eslint-plugin-react
  • eslint-plugin-react-hooks
  • eslint-plugin-next
    を含んでいます。

これらは next.config.js の設定よりも優先されます。

ESLint プラグイン

eslint-plugin-next
は次のルールで構成されています。

  • フォントの設定まわり

    • @next/next/google-font-display: Google Fonts を使うとき、フォントの表示方法を正しく設定しているかチェック
    • @next/next/google-font-preconnect: Google Fonts を読み込む前に、ブラウザが準備するように促しているかチェック
  • next/script コンポーネントまわり

    • @next/next/inline-script-id: インラインスクリプトを含む next/script には id 属性が必須かどうかを教えてくれる
    • @next/next/next-script-for-ga: Google Analytics のインラインスクリプトを使うときは、next/script コンポーネントを使うように勧める
  • Next.js 独自の挙動まわり

    • @next/next/no-assign-module-variable: 特殊な変数 module に値を代入するのを防止
    • @next/next/no-async-client-component: クライアントコンポーネントを async 関数にしないように注意喚起
    • 他にも、特定のファイル以外で特定の機能を使わないように促すルールがあるよ
  • 不要なタグやコンポーネントの使用を防止

    • @next/next/no-css-tags 手動でスタイルシートのタグを書くのを防止

    • no-document-import-in-page next/documentのクライアントからのインポートを防止

    • no-head-element

      要素の直接使用を防ぎ、代わりにnext/headコンポーネントの使用を強制します。
      Next.jsでは、next/headを使用してページの<head>要素を操作することが推奨されています。
    • no-head-import-in-document _document.js内でのnext/headの使用を防止
      _document.jsは、サーバーサイドでのみレンダリングされるため、next/headはここでは機能しません。

    • no-script-component-in-head next/headコンポーネント内でのnext/scriptの使用を防ぎます。next/script<body>内でのみ使用することが推奨されています。

    • no-styled-jsx-in-document pages/_document.jsでのstyled-jsxの使用を防ぎます。

  • パフォーマンス改善のためのルール

    • @next/next/no-img-element: 画像 (img タグ) の使いすぎを防止 (読み込みが遅くなるため)
    • @next/next/no-sync-scripts: 同期スクリプトの使用を減らすように勧める (ページの読み込みが遅くなるため)
  • その他

    • @next/next/no-html-link-for-pages: 内部リンク ( <a> タグ) を使わず、Next.js のナビゲーション機能を使うように促す
    • @next/next/no-page-custom-font: 特定のページだけでカスタムフォントを使わないように注意喚起
    • @next/next/no-typos: データ取得処理 (getStaticProps や getServerSideProps) でよくある入力ミスを防止
    • @next/next/no-unwanted-polyfill: 余計な Polyfill.io の読み込みを防止

Next.js アプリのよくある間違いを防ぐために、Next.js では ESLint ルールが用意されています。
これらのルールは、Next.js のベストプラクティスとアンチパターンを強制するためのものです。


カスタムディレクトリとファイルのリント

デフォルトでは、Next.jsはpages/, app/, components/, lib/, src/ディレクトリのすべてのファイルに対してESLintを実行します。
ただし、next.config.jsのeslint configでdirsオプションを指定することで、本番ビルドで使用するディレクトリを指定することができます。

next.config.js
module.exports = {

・・・

  eslint: {
    dirs: ['apps', 'utils'],
  },
}

↑'apps' ディレクトリと 'utils' ディレクトリでのみ ESLint を実行します。


ESLintのキャッシュ

ESLintのキャッシュはデフォルトで有効になっています。

パフォーマンスを向上させるために、ESLintによって処理されるファイルの情報はデフォルトでキャッシュされます。
これは.next/cacheまたは定義したビルドディレクトリに保存されます。
一つのソースファイルの内容以上に依存するESLintルールを含み、キャッシュを無効にする必要がある場合は、next lintで--no-cacheフラグを使用してください。

キャッシュの無効化

next lint --no-cache


ルールの無効化

個別にルールを変更したり無効にしたい場合は、.eslintrcのrulesプロパティを使って直接変更することができます:

.eslintrc.json
{

  "extends": "next",
  "rules": {
    "react/no-unescaped-entities": "off",
    "@next/next/no-page-custom-font": "off"
  }

}


Core Web Vitals

Next.js の lint 設定と Core Web Vitals

Core Web Vitals とは?

Core Web Vitals は、Google が定めた、ウェブページの読み込み速度やインタラクティブさ、視覚的安定性などを測る指標のことです。
ユーザーが快適にウェブページを利用できるかどうかを判断するのに役立ちます。

Next.js の lint 設定と Core Web Vitals

Next.js には、コードの品質チェックを行う ESLint というツールが組み込まれています。
next/core-web-vitals という設定を使うと、このチェックに Core Web Vitals に関するルールを追加できます。

ポイント

  • next lint コマンドを実行するときに strict オプションを選ぶか、.eslintrc.json ファイルに extends: "next/core-web-vitals" と記述すると、Core Web Vitals に関するルールが有効になります。
  • 有効になると、本来は警告 (warning) レベルだったルールがエラー (error) レベルになり、コードが Core Web Vitals のスコアに悪影響を与える可能性がある箇所を厳しくチェックしてくれます。
  • 新しく Next.js アプリケーションを作成するときには、この next/core-web-vitals 設定が初期設定として自動的に含まれています。

まとめ

Next.js の lint 設定を使って、コードが Core Web Vitals のスコアを悪化させる可能性を事前に見つけ、修正することで、ユーザーに快適なウェブページが提供できます。

.eslintrc.json
{
  "extends": "next/core-web-vitals"
}

Additional Configurations

追加設定

Next.js の lint 設定: 既存設定との統合

すでに別の ESLint 設定を使っている場合でも、eslint-config-next を取り入れることができます。
ただし、 他の設定の後eslint-config-next を継承するようにしてください。

例:

.eslintrc.json
{
  "extends": ["eslint:recommended", "next/core-web-vitals"]
}

next という設定は、parser (構文解析器)、plugins (プラグイン)、settings (設定) などのプロパティのデフォルト値を既に設定済みです。特別な理由がない限り、これらのプロパティを手動で再定義する必要はありません。

もし他の共有可能な設定も取り入れる場合は、これらのプロパティが上書きや変更されないように注意してください。そうでない場合は、next 設定と同じような挙動を持つ設定を削除するか、上記のように Next.js ESLint プラグインから直接継承することをおすすめします。

ポイント:

  • 既存の ESLint 設定がある場合は、eslint-config-next を最後に継承するようにしましょう。
  • next 設定は必要なプロパティをデフォルトで設定済みなので、特別な理由がなければ変更する必要はありません。
  • 他の設定と併用する場合、プロパティの競合に注意しましょう。

Pretter

ESLint には、既存の Prettier 設定と競合する可能性があるコード形式ルールも含まれています。
ESLint と Prettier を連携させるために、ESLint 構成に eslint-config-prettier を含めることをお勧めします。

インストール

pnpm add --save-dev eslint-config-prettier

設定ファイル

既存の ESLint 設定ファイルにprettierを追加します。

.eslintrc.json
{
  "extends": ["next/core-web-vitals", "prettier"]
}



Next.js 公式ドキュメント以外の追加設定

tsconfig.json

TypeScriptを開発しやすくします。

tsconfig.json (変更箇所)
    "strict": false,
    "strictNullChecks": true,

"strict": false は、以下の設定を無効にします。

"noImplicitAny": true:暗黙的にany型として解釈される式を許可しません。
"strictNullChecks": true:nullとundefinedの扱いに関する厳密な型チェックを有効にします。
"strictFunctionTypes": true:関数の型チェックを厳密に行います。
"strictPropertyInitialization": true:クラスのプロパティの初期化を厳密に行います。
"noImplicitThis": true:thisの型チェックを厳密に行います。

↑この5つのうち

"strictNullChecks"だけ有効にします。


ESLint 独自設定

設定ファイル

touch .eslintrc.json

.eslintrc.json
{
  // JavaScriptの実行環境を指定
  "env": {
    "browser": true,
    "es2023": true,
    "node": true
  },
  "root": true,
  // 構文解析に使用するパーサーの指定
  // デフォルトの設定ではES5しかパースできない
  "parser": "@typescript-eslint/parser",
  // parserのオプションを設定
  // JSXやECMAScriptのバージョンの設定など
  "parserOptions": {
     // tsconfig.jsonへのパス
     "project": "./tsconfig.json",
    "EXPERIMENTAL_useProjectService": {
      // 許容する最大ファイル数
      "maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING": 30
    },
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 2020,
    "sourceType": "module"
  },

  // 任意のルール実行時に適用される追加の共有設定
  "settings": {
    "react": {
      "version": "detect"
    }
  },

  // 追加ルールの指定
  // pluginsにルールを指定しても、ルールは適用されていない状態
  // 追加ルールを適用する場合は、extendsかrulesで設定が必要
  "plugins": [
    "react",
    "react-hooks",
    "@typescript-eslint",
    "import",
    "unused-imports"
  ],

  // 共有設定の適用
  // 各pluginで公開されている設定ファイルを指定することで、ルールの設定を適用
  // ルール設定が重複する場合は、後から指定したものが適用される
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:storybook/recommended",
    "next/core-web-vitals",
    "prettier"
  ],

  // 個別のルール設定
  // extendsで指定した共有設定以外の個別設定
  // 0:無効, 1:警告, 2: エラー
  "rules": {
    "no-case-declarations": "off",
    "@typescript-eslint/no-explicit-any": "off",
    // typescript-eslintのban-ts-commentルールについて
    // https://qiita.com/KokiSakano/items/ff8dde69d7f4296e2480
    "@typescript-eslint/ban-ts-comment": [
      "error",
      {
        "ts-expect-error": "allow-with-description",
        "ts-ignore": false,
        "ts-nocheck": false,
        "ts-check": false
      }
    ],
    // TypeScriptで未使用の変数を許可するかどうかを指定します。この例では、offに設定されているため、未使用の変数を許可します。
    "@typescript-eslint/no-unused-vars": "off",
    // 未使用のインポートに関するルールを指定します。この例では、warnに設定されているため、未使用のインポートがある場合に警告を出します。
    "unused-imports/no-unused-imports": "warn",
    // モジュールのインポート順序に関するルールを指定します。この例では、配列の中に複数のグループが定義されています。各グループは、groupsプロパティで定義されています。
    "import/order": [
      "error",
      {
        "groups": [
          // builtin: Node.js に組み込まれているモジュール
          // external: npm install  プロジェクト外部からインストールされたモジュール
          // internal: プロジェクト内のモジュールで、パスを指定してインポートされたもの
          // parent: 親モジュール 相対パスを使用してインポートされたもの
          // sibling: 兄弟モジュール 相対パスを使用してインポートされたもの
          // index: インデックスファイルで、相対パスを使用してインポートされたもの
          // object: オブジェクトファイルで、相対パスを使用してインポートされたもの
          // type: 型ファイルで、相対パスを使用してインポートされたもの
          "builtin",
          "external",
          "internal",
          ["parent", "sibling"],
          "index",
          "object",
          "type"
        ],
        // それぞれのgroupsとの間は1行分空けます。
        "newlines-between": "always",
        // 特定のグループの import 文を除外するかどうかを指定します。
        "pathGroupsExcludedImportTypes": ["builtin", "external"],
        // order オプションは、アルファベット順にします。
        // caseInsensitive オプションは、大文字小文字を無視してアルファベット順に並べるかどうかを指定します。
        "alphabetize": { "order": "asc", "caseInsensitive": true },
        "pathGroups": [
          // pattern: インポートパスのパターンを指定します。この例では、src/ディレクトリ以下のすべてのファイルを指定しています。
          // group: インポートパスが一致した場合に、どのグループに属するかを指定します。この例では、internalグループに属するように指定しています。
          // position: インポートパスが一致した場合に、どの位置に挿入するかを指定します。この例では、beforeに指定しているため、他のグループよりも前に挿入されます。
          { "pattern": "src/**", "group": "internal", "position": "before" }
        ]
      }
    ]
  }
}

ESLint の scripts

package.json
"scripts": {
    "lint": "eslint --ext .ts,.js,.tsx,.jsx src",
    "lint:debug": "eslint --ext .ts,.js,.tsx,.jsx src --debug",
    "lint:fix": "eslint --ext .ts,.js,.tsx,.jsx src --fix",
}

※ESLintの設定ファイルを保存したら

pnpm run lint:fix

lintコマンドを実行しておいてください。


Prettier 独自設定

TailwindCSSのclassNameのプロパティの順番を自動ソートする機能が
eslint-plugin-tailwindcss (<=後から追加された設定)
prettier-plugin-tailwindcss
の両方にあります。

eslint-plugin-tailwindcss だけ導入するので良いそうです。

参考

eslint-plugin-tailwindcss/docs/rules/classnames-order.md at master · francoismassart/eslint-plugin-tailwindcss

francoismassart/eslint-plugin-tailwindcss: ESLint plugin for Tailwind CSS usage

インストール

公式サイト Install Prettier

Configuration File · Prettier

touch .prettierrc.json

package.json
"scripts": {
    "prettier-fix": "prettier --write .",
}

Prettier 設定ファイル

.prettier.json
{
  "arrowParens": "always",
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "none"
}

.prettierignoreファイルの作成

touch .prettierignore

.prettierignore
# Build artifacts
.turbo/
_next/
__tmp__/
dist/
node_modules/
target/
compiled/

types_db.ts
database.types.ts

# Ignore artifacts:
/build
coverage

# dotfile
.env*

# next.js
/.next/
/out/

package-lock.json
pnpm-lock.yaml

# Supabase
/supabase/
src/types/*
src/types/database.types.ts
src/types/types_db.ts

# Storybook
*.stories.ts
*.stories.tsx

# Dependency directories
node_modules

# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# text
*.md
*.txt
*.csv

Prettier コマンド一覧

※通常は VSCode 側を設定すれば、保存時に自動で実行されるので、コマンドを打つことはほとんどありません。

動作確認のため prettier を実行します。

# 全体をフォーマットします。
pnpm run prettier-fix

# src ディレクトリ以下をフォーマットします。
npx prettier src/ --write

# 巨大プロジェクトの場合に時間短縮のためフォルダを指定したい場合
npx prettier [指定フォルダ名] --write

# 直接ファイルを指定する場合
npx prettier src\app\page.tsx --write

# prettier が実行済みかの確認(上書きはしない)
npx prettier . --check

VSCodeの拡張機能

Prettier - Code formatter - Visual Studio Marketplace
https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode

tailwindlabs/tailwindcss-intellisense: Intelligent Tailwind CSS tooling for Visual Studio Code

自動ソート

現在の設定では、自動ソートになっているはずです。

↓ソートされてない

page.tsx
<div className="p-3 border-gray-300 m-4 h-24 lg:p-4 flex border-2 lg:m-4"></div>

↓自動ソート後

page.tsx
<div className="flex h-24 p-3 m-4 border-2 border-gray-300 lg:p-4 lg:m-4"></div>

これは、自動ソート後されているのを確認したら削除しておいてください。


turborepo の導入

push時などにコードのチェックをしてもらいます。

公式ドキュメント

Add Turborepo to your existing project – Turborepo

インストール

グローバルにインストールします。

# install
pnpm add turbo --global

# update
npx @turbo/codemod@latest update

設定ファイル

touch turbo.json

turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "type-check": {}
  }
}

.gitignoreファイルに追加します。

.gitignore
・・・
# turborepo
.turbo

turborepoの実行

※コミット後に実行します。
アプリケーションを起動させていたら停止させておきます。

1回目の実行

turbo type-check build

 Tasks:    1 successful, 1 total
Cached:    1 cached, 1 total
  Time:    182ms >>> FULL TURBO

ビルドが成功すると緑色の文字でsuccessfulとでます。

2回目の実行

turbo type-check build

↑そのまま2回目を実行すると、すぐに終了するのでキャッシュされていることがわかります。

turborepoのコマンド

turbo dev (≒pnpm run dev)
開発モードでアプリケーションを起動します。ソースコードの変更を監視し、変更があるたびにアプリケーションを自動的に再起動します。

turbo type-check build
TypeScriptの型チェックを行い、その後にビルドプロセスを実行します。型チェックは、コード内の型エラーを検出するためのものです。


husky のインストール

per-commit

gitのコミットの前に format を実行します。
package.jsonのscriptを実行します。

pre-push

githubへのpushの前に
buildを実行します。

インストール

pnpm i -D husky
npx husky init

touch .husky/pre-commit
touch .husky/pre-push

turbo buildはturbo repoをインストールしている場合のコマンドです。

↑ファイルに記入するコマンドは自分の好みに設定します。

.husky/pre-commit
pnpm run lint:fix
pnpm run prettier-fix

.husky/pre-push
turbo type-check build

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?