跳到內容

ESLint

Next.js 提供了一個 ESLint 外掛程式 eslint-plugin-next,已捆綁在基礎配置中,使其能夠捕捉 Next.js 應用程式中的常見問題。

參考

以下 ESLint 外掛程式的建議規則集都用於 eslint-config-next

這將優先於來自 next.config.js 的配置。

規則

完整的規則集如下

在建議的配置中啟用規則描述
@next/next/google-font-display強制使用 Google 字體的 font-display 行為。
@next/next/google-font-preconnect確保 Google 字體使用 preconnect
@next/next/inline-script-id強制對具有內聯內容的 next/script 組件使用 id 屬性。
@next/next/next-script-for-ga當使用 Google Analytics 的內聯腳本時,優先使用 next/script 組件。
@next/next/no-assign-module-variable防止賦值給 module 變數。
@next/next/no-async-client-component防止客戶端組件為 async 函式。
@next/next/no-before-interactive-script-outside-document防止在 pages/_document.js 之外使用 next/scriptbeforeInteractive 策略。
@next/next/no-css-tags防止手動樣式表標籤。
@next/next/no-document-import-in-page防止在 pages/_document.js 之外匯入 next/document
@next/next/no-duplicate-head防止在 pages/_document.js 中重複使用 <Head>
@next/next/no-head-element防止使用 <head> 元素。
@next/next/no-head-import-in-document防止在 pages/_document.js 中使用 next/head
@next/next/no-html-link-for-pages防止使用 <a> 元素導航到內部 Next.js 頁面。
@next/next/no-img-element防止使用 <img> 元素,因為 LCP 較慢且頻寬較高。
@next/next/no-page-custom-font防止頁面專用的自訂字體。
@next/next/no-script-component-in-head防止在 next/head 組件中使用 next/script
@next/next/no-styled-jsx-in-document防止在 pages/_document.js 中使用 styled-jsx
@next/next/no-sync-scripts防止同步腳本。
@next/next/no-title-in-document-head防止將 <title> 與來自 next/documentHead 組件一起使用。
@next/next/no-typos防止在 Next.js 的資料 fetching 函式中出現常見的錯字
@next/next/no-unwanted-polyfillio防止來自 Polyfill.io 的重複 polyfills。

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

範例

Linting 自訂目錄和檔案

預設情況下,Next.js 將對 pages/app/components/lib/src/ 目錄中的所有檔案執行 ESLint。但是,您可以為生產環境建置指定要使用 next.config.jseslint 配置中的 dirs 選項的目錄

next.config.js
module.exports = {
  eslint: {
    dirs: ['pages', 'utils'], // Only run ESLint on the 'pages' and 'utils' directories during production builds (next build)
  },
}

同樣地,--dir--file 標誌可用於 next lint,以 lint 特定目錄和檔案

終端機
next lint --dir pages --dir utils --file bar.js

在 Monorepo 中指定根目錄

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

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

const compat = new FlatCompat({
  // import.meta.dirname is available after 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 規則,並且需要停用快取,請將 --no-cache 標誌與 next lint 一起使用。

終端機
next lint --no-cache

停用規則

如果您想修改或停用支援的外掛程式(reactreact-hooksnext)提供的任何規則,您可以直接使用 .eslintrc 中的 rules 屬性來變更它們

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

const compat = new FlatCompat({
  // import.meta.dirname is available after 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 is available after 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 還會將 TypeScript 專用的 lint 規則與 next/typescript 新增到您的配置中

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

const compat = new FlatCompat({
  // import.meta.dirname is available after 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 > Configs 以取得更多詳細資訊。

使用 Prettier

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

首先,安裝依賴項

終端機
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

然後,將 prettier 新增到您現有的 ESLint 配置中

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

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

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

export default eslintConfig

對 staged 檔案執行 lint

如果您想將 next lintlint-staged 一起使用,以在 staged 的 git 檔案上執行 linter,您必須將以下內容新增到專案根目錄中的 .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],
}

在生產環境建置期間停用 linting

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

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  eslint: {
    // Warning: This allows production builds to successfully complete even if
    // your project has ESLint errors.
    ignoreDuringBuilds: true,
  },
}
 
export default nextConfig

遷移現有配置

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

如果以下條件為真

  • 您已經安裝了以下一個或多個外掛程式(單獨安裝或通過不同的配置(例如 airbnbreact-app)安裝)
    • react
    • react-hooks
    • jsx-a11y
    • import
  • 您已定義與 Next.js 中 Babel 配置方式不同的特定 parserOptions(除非您自訂了 Babel 配置,否則不建議這樣做)
  • 您已安裝了 eslint-plugin-import,並具有 Node.js 和/或 TypeScript 解析器,用於處理匯入

那麼我們建議您移除這些設定(如果您偏好 eslint-config-next 中配置這些屬性的方式),或者直接從 Next.js ESLint 外掛程式擴展

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

外掛程式可以正常安裝在您的專案中,而無需執行 next lint

終端機
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 外掛程式擴展。