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) 声明为异步函数。
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'], // 生产构建时仅对 'pages' 和 'utils' 目录运行 ESLint (next build)
  },
}

类似地,next lint 命令可使用 --dir--file 参数来检查特定目录和文件:

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

在 monorepo 中指定根目录

如果在未安装 Next.js 的项目(如 monorepo)中使用 eslint-plugin-next,可以通过 .eslintrc 中的 settings 属性指定 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 可以是相对/绝对路径、通配符(如 "packages/*/")或路径/通配符数组。

禁用缓存

为提高性能,ESLint 默认会缓存已处理文件的信息,存储位置为 .next/cache 或您定义的 构建目录。如果某些 ESLint 规则依赖多个源文件的内容且需要禁用缓存,可使用 next lint--no-cache 参数:

Terminal
next lint --no-cache

禁用规则

如需修改或禁用支持的插件(reactreact-hooksnext)提供的规则,可直接在 .eslintrcrules 属性中进行调整:

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 中影响 核心网页指标 的警告规则升级为错误规则。

使用 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 以使两者协同工作。

首先安装依赖:

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

然后将 prettier 添加到现有 ESLint 配置:

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

对暂存文件运行检查

如需结合 lint-staged 使用 next lint 对 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],
}

在生产构建时禁用代码检查

如果不想在 next build 时运行 ESLint,可将 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
  • 定义了与 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

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 在 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 插件扩展配置。