Menu

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防止客户端组件使用异步函数。
@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防止在 next/documentHead 组件中使用 <title>
@next/next/no-typos防止在 Next.js 的数据获取函数 中出现常见拼写错误
@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 中指定根目录

如果你在 Next.js 未安装在根目录的项目中使用 eslint-plugin-next(例如 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 可以是路径(相对或绝对)、通配符(例如 "packages/*/")或路径和/或通配符的数组。

禁用缓存

为了提高性能,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 并选择严格选项时,会启用 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 的 lint 规则添加到你的配置中:

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 > Configs

与 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

然后,将 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 检查

如果你想将 next lintlint-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

如果你不希望 ESLint 在 next build 期间运行,可以在 next.config.js 中将 eslint.ignoreDuringBuilds 选项设置为 true

next.config.ts
TypeScript
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 配置,否则不建议这样做)
  • 你安装了带有 Node.js 和/或 TypeScript resolverseslint-plugin-import 来处理导入

那么我们建议移除这些设置(如果你喜欢 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 插件扩展。