ESLint 插件

Next.js 提供了一個 ESLint 插件 eslint-plugin-next,已內建於基礎配置中,可幫助您捕捉 Next.js 應用程式中的常見問題和錯誤。

參考

eslint-config-next 中使用了以下 ESLint 插件的推薦規則集:

這些配置將優先於 next.config.js 中的設定。

規則

完整的規則集如下:

在推薦配置中啟用規則描述
Check Icon@next/next/google-font-display強制使用 Google 字型時的 font-display 行為。
Check Icon@next/next/google-font-preconnect確保使用 Google 字型時包含 preconnect
Check Icon@next/next/inline-script-id強制在 next/script 元件中為內聯內容添加 id 屬性。
Check Icon@next/next/next-script-for-ga使用 Google Analytics 的內聯腳本時,優先使用 next/script 元件。
Check Icon@next/next/no-assign-module-variable防止對 module 變數進行賦值。
Check Icon@next/next/no-async-client-component防止客戶端元件 (Client Components) 成為 async 函式。
Check Icon@next/next/no-before-interactive-script-outside-document防止在 pages/_document.js 之外使用 next/scriptbeforeInteractive 策略。
Check Icon@next/next/no-css-tags防止手動添加樣式表標籤。
Check Icon@next/next/no-document-import-in-page防止在 pages/_document.js 之外導入 next/document
Check Icon@next/next/no-duplicate-head防止在 pages/_document.js 中重複使用 <Head>
Check Icon@next/next/no-head-element防止使用 <head> 元素。
Check Icon@next/next/no-head-import-in-document防止在 pages/_document.js 中使用 next/head
Check Icon@next/next/no-html-link-for-pages防止使用 <a> 元素導航至內部 Next.js 頁面。
Check Icon@next/next/no-img-element防止使用 <img> 元素,因其會導致 LCP 變慢和頻寬增加。
Check Icon@next/next/no-page-custom-font防止僅在頁面中使用自訂字型。
Check Icon@next/next/no-script-component-in-head防止在 next/head 元件中使用 next/script
Check Icon@next/next/no-styled-jsx-in-document防止在 pages/_document.js 中使用 styled-jsx
Check Icon@next/next/no-sync-scripts防止使用同步腳本。
Check Icon@next/next/no-title-in-document-head防止在 next/documentHead 元件中使用 <title>
Check Icon@next/next/no-typos防止 Next.js 資料獲取函式 中的常見拼寫錯誤
Check Icon@next/next/no-unwanted-polyfillio防止從 Polyfill.io 載入重複的 polyfill。

我們建議使用適當的 整合工具,在開發過程中直接在程式碼編輯器中查看警告和錯誤。

範例

對自訂目錄和檔案進行程式碼檢查

預設情況下,Next.js 會對 pages/app/components/lib/src/ 目錄中的所有檔案執行 ESLint。不過,您可以在 next.config.jseslint 配置中使用 dirs 選項來指定生產建置時要檢查的目錄:

next.config.js
module.exports = {
  eslint: {
    dirs: ['pages', 'utils'], // 僅在生產建置 (next build) 時對 'pages' 和 'utils' 目錄執行 ESLint
  },
}

同樣地,next lint 可以使用 --dir--file 標記來檢查特定目錄和檔案:

Terminal
next lint --dir pages --dir utils --file bar.js

在 monorepo 中指定根目錄

如果您在專案中使用 eslint-plugin-next,而 Next.js 未安裝在根目錄中(例如 monorepo),您可以在 .eslintrc 中使用 settings 屬性來告訴 eslint-plugin-next 在哪裡找到您的 Next.js 應用程式:

eslint.config.mjs
import { FlatCompat } from '@eslint/eslintrc'

const compat = new FlatCompat({
  // import.meta.dirname 在 Node.js v20.11.0 之後可用
  baseDirectory: import.meta.dirname,
})

const eslintConfig = [
  ...compat.config({
    extends: ['next'],
    settings: {
      next: {
        rootDir: 'packages/my-app/',
      },
    },
  }),
]

export default eslintConfig

rootDir 可以是路徑(相對或絕對)、glob(例如 "packages/*/")或路徑和/或 glob 的陣列。

停用快取

為了提高效能,ESLint 處理的檔案資訊預設會被快取。這些資訊儲存在 .next/cache 或您定義的 建置目錄 中。如果您包含任何依賴於多個原始檔內容的 ESLint 規則,並需要停用快取,請在 next lint 中使用 --no-cache 標記。

Terminal
next lint --no-cache

停用規則

如果您想修改或停用支援的插件(reactreact-hooksnext)提供的任何規則,可以直接在 .eslintrc 中使用 rules 屬性進行變更:

eslint.config.mjs
import { FlatCompat } from '@eslint/eslintrc'

const compat = new FlatCompat({
  // import.meta.dirname 在 Node.js v20.11.0 之後可用
  baseDirectory: import.meta.dirname,
})

const eslintConfig = [
  ...compat.config({
    extends: ['next'],
    rules: {
      'react/no-unescaped-entities': 'off',
      '@next/next/no-page-custom-font': 'off',
    },
  }),
]

export default eslintConfig

與 Core Web Vitals 一起使用

當首次執行 next lint 並選擇 strict 選項時,會啟用 next/core-web-vitals 規則集。

eslint.config.mjs
import { FlatCompat } from '@eslint/eslintrc'

const compat = new FlatCompat({
  // import.meta.dirname 在 Node.js v20.11.0 之後可用
  baseDirectory: import.meta.dirname,
})

const eslintConfig = [
  ...compat.config({
    extends: ['next/core-web-vitals'],
  }),
]

export default eslintConfig

next/core-web-vitals 會更新 eslint-plugin-next,將影響 Core Web Vitals 的預設警告規則升級為錯誤。

對於使用 Create Next App 建立的新應用程式,next/core-web-vitals 入口點會自動包含在內。

與 TypeScript 一起使用

除了 Next.js ESLint 規則外,create-next-app --typescript 還會透過 next/typescript 將 TypeScript 專用的檢查規則新增到您的配置中:

eslint.config.mjs
import { FlatCompat } from '@eslint/eslintrc'

const compat = new FlatCompat({
  // import.meta.dirname 在 Node.js v20.11.0 之後可用
  baseDirectory: import.meta.dirname,
})

const eslintConfig = [
  ...compat.config({
    extends: ['next/core-web-vitals', 'next/typescript'],
  }),
]

export default eslintConfig

這些規則基於 plugin:@typescript-eslint/recommended。詳情請參閱 typescript-eslint > 配置

與 Prettier 一起使用

ESLint 也包含程式碼格式化規則,這可能會與您現有的 Prettier 設定衝突。我們建議在 ESLint 配置中包含 eslint-config-prettier,以讓 ESLint 和 Prettier 協同工作。

首先,安裝相依套件:

Terminal
npm install --save-dev eslint-config-prettier

yarn add --dev eslint-config-prettier

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

bun add --dev eslint-config-prettier

然後,在現有的 ESLint 配置中加入 prettier

eslint.config.mjs
import { FlatCompat } from '@eslint/eslintrc'

const compat = new FlatCompat({
  // import.meta.dirname 在 Node.js v20.11.0 之後可用
  baseDirectory: import.meta.dirname,
})

const eslintConfig = [
  ...compat.config({
    extends: ['next', 'prettier'],
  }),
]

export default eslintConfig

對暫存檔案執行程式碼檢查

如果您想將 next lintlint-staged 一起使用,以對暫存的 git 檔案執行檢查,您需要在專案根目錄的 .lintstagedrc.js 檔案中加入以下內容,以指定使用 --file 標記。

.lintstagedrc.js
const path = require('path')

const buildEslintCommand = (filenames) =>
  `next lint --fix --file ${filenames
    .map((f) => path.relative(process.cwd(), f))
    .join(' --file ')}`

module.exports = {
  '*.{js,jsx,ts,tsx}': [buildEslintCommand],
}

在生產建置時停用程式碼檢查

如果您不希望 ESLint 在 next build 期間執行,可以在 next.config.js 中將 eslint.ignoreDuringBuilds 選項設為 true

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  eslint: {
    // 警告:即使您的專案有 ESLint 錯誤,這也會允許生產建置成功完成。
    ignoreDuringBuilds: true,
  },
}

export default nextConfig

遷移現有配置

如果您的應用程式中已經配置了 ESLint,我們建議直接從此插件擴展,而不是包含 eslint-config-next,除非滿足以下幾個條件。

推薦的插件規則集

如果滿足以下條件:

  • 您已經安裝了一個或多個以下插件(單獨安裝或透過其他配置如 airbnbreact-app 安裝):
    • react
    • react-hooks
    • jsx-a11y
    • import
  • 您定義了特定的 parserOptions,與 Next.js 中的 Babel 配置不同(除非您 自訂了 Babel 配置,否則不建議這樣做)
  • 您安裝了 eslint-plugin-import 並定義了 Node.js 和/或 TypeScript 的 解析器 來處理導入

那麼我們建議,如果您偏好 eslint-config-next 中配置的這些屬性,可以移除這些設定,或者直接從 Next.js ESLint 插件擴展:

module.exports = {
  extends: [
    //...
    'plugin:@next/next/recommended',
  ],
}

該插件可以正常安裝在您的專案中,無需執行 next lint

Terminal
npm install --save-dev @next/eslint-plugin-next

yarn add --dev @next/eslint-plugin-next

pnpm add --save-dev @next/eslint-plugin-next

bun add --dev @next/eslint-plugin-next

這樣可以避免由於在多個配置中導入相同的插件或解析器而導致的衝突或錯誤。

其他配置

如果您已使用獨立的 ESLint 配置並想包含 eslint-config-next,請確保它是最後一個擴展的配置,位於其他配置之後。例如:

eslint.config.mjs
import js from '@eslint/js'
import { FlatCompat } from '@eslint/eslintrc'

const compat = new FlatCompat({
  // import.meta.dirname is available after Node.js v20.11.0
  baseDirectory: import.meta.dirname,
  recommendedConfig: js.configs.recommended,
})

const eslintConfig = [
  ...compat.config({
    extends: ['eslint:recommended', 'next'],
  }),
]

export default eslintConfig

next 配置已自動處理 parserpluginssettings 屬性的預設值設定。除非您的使用情境需要不同配置,否則無需手動重新宣告這些屬性。

如果您包含任何其他可共享的配置,必須確保這些屬性不會被覆寫或修改。否則,我們建議移除與 next 配置行為重複的任何配置,或直接從上述提到的 Next.js ESLint 插件擴展。