跳到内容

ESLint

Next.js 提供了一个 ESLint 插件 @next/eslint-plugin-next,它已经捆绑在基本配置中,可以在 Next.js 应用程序中捕获常见问题。

设置 ESLint

使用 ESLint CLI (flat config) 快速进行 linting

  1. 安装 ESLint 和 Next.js 配置

    终端
    pnpm add -D eslint eslint-config-next @eslint/eslintrc
  2. 创建包含 Next.js 配置的 eslint.config.mjs

    eslint.config.mjs
    import { defineConfig, globalIgnores } from 'eslint/config'
    import nextVitals from 'eslint-config-next/core-web-vitals'
     
    const eslintConfig = defineConfig([
      ...nextVitals,
      // Override default ignores of eslint-config-next.
      globalIgnores([
        // Default ignores of eslint-config-next:
        '.next/**',
        'out/**',
        'build/**',
        'next-env.d.ts',
      ]),
    ])
     
    export default eslintConfig
  3. 运行 ESLint

    终端
    pnpm exec eslint .

参考

eslint-config-next 中使用了以下 ESLint 插件的所有推荐规则集

规则

完整的规则集如下

在推荐配置中启用规则描述
@next/next/google-font-display使用 Google Fonts 强制执行字体显示行为。
@next/next/google-font-preconnect确保与 Google Fonts 一起使用 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禁止手动 stylesheet 标签。
@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 的重复 polyfills。

我们建议使用适当的集成,以便在开发过程中直接在代码编辑器中查看警告和错误。

移除 next lint

从 Next.js 16 开始,next lint 被移除。

作为移除的一部分,Next 配置文件中的 eslint 选项不再需要,可以安全移除。

示例

在 monorepo 中指定根目录

如果您在 Next.js 未安装在根目录(例如 monorepo)的项目中使用 @next/eslint-plugin-next,您可以使用 eslint.config.mjs 中的 settings 属性告诉 @next/eslint-plugin-next 在哪里找到您的 Next.js 应用程序

eslint.config.mjs
import { defineConfig } from 'eslint/config'
import eslintNextPlugin from '@next/eslint-plugin-next'
 
const eslintConfig = defineConfig([
  {
    plugins: {
      next: eslintNextPlugin,
    },
    settings: {
      next: {
        rootDir: 'packages/my-app/',
      },
    },
    files: [
      // ...files
    ],
    ignores: [
      // ...ignores
    ],
  },
])
 
export default eslintConfig

rootDir 可以是路径(相对或绝对)、glob(即 "packages/*/"),或者路径和/或 globs 的数组。

禁用规则

如果您想修改或禁用支持的插件(reactreact-hooksnext)提供的任何规则,您可以直接在 eslint.config.mjs 中使用 rules 属性更改它们

eslint.config.mjs
import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
 
const eslintConfig = defineConfig([
  ...nextVitals,
  {
    rules: {
      'react/no-unescaped-entities': 'off',
      '@next/next/no-page-custom-font': 'off',
    },
  },
  // Override default ignores of eslint-config-next.
  globalIgnores([
    // Default ignores of eslint-config-next:
    '.next/**',
    'out/**',
    'build/**',
    'next-env.d.ts',
  ]),
])
 
export default eslintConfig

与 Core Web Vitals 结合使用

通过在您的 ESLint 配置中扩展 next/core-web-vitals 规则集来启用它。

eslint.config.mjs
import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
 
const eslintConfig = defineConfig([
  ...nextVitals,
  // Override default ignores of eslint-config-next.
  globalIgnores([
    // Default ignores of eslint-config-next:
    '.next/**',
    'out/**',
    'build/**',
    'next-env.d.ts',
  ]),
])
 
export default eslintConfig

next/core-web-vitals 会将 @next/eslint-plugin-next 更新为对一些默认警告的规则报错,如果它们影响到核心 Web 指标

使用 Create Next App 构建的新应用程序会自动包含 next/core-web-vitals 入口点。

使用 TypeScript

除了 Next.js ESLint 规则外,create-next-app --typescript 还会通过 next/typescript 为您的配置添加 TypeScript 特定的 lint 规则

eslint.config.mjs
import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
import nextTs from 'eslint-config-next/typescript'
 
const eslintConfig = defineConfig([
  ...nextVitals,
  ...nextTs,
  // Override default ignores of eslint-config-next.
  globalIgnores([
    // Default ignores of eslint-config-next:
    '.next/**',
    'out/**',
    'build/**',
    'next-env.d.ts',
  ]),
])
 
export default eslintConfig

这些规则基于 plugin:@typescript-eslint/recommended。有关更多详细信息,请参阅 typescript-eslint > 配置

与 Prettier 结合使用

ESLint 还包含代码格式化规则,这可能会与您现有的 Prettier 设置冲突。我们建议在您的 ESLint 配置中包含 eslint-config-prettier,以使 ESLint 和 Prettier 协同工作。

首先,安装依赖项

终端
pnpm add -D eslint-config-prettier

然后,将 prettier 添加到您现有的 ESLint 配置中

eslint.config.mjs
import { defineConfig, globalIgnores } from 'eslint/config'
import nextVitals from 'eslint-config-next/core-web-vitals'
import prettier from 'eslint-config-prettier/flat'
 
const eslintConfig = defineConfig([
  ...nextVitals,
  prettier,
  // Override default ignores of eslint-config-next.
  globalIgnores([
    // Default ignores of eslint-config-next:
    '.next/**',
    'out/**',
    'build/**',
    'next-env.d.ts',
  ]),
])
 
export default eslintConfig

对暂存文件运行 lint

如果您想将 ESLint 与 lint-staged 结合使用,在暂存的 git 文件上运行 linter,请将以下内容添加到项目根目录的 .lintstagedrc.js 文件中

.lintstagedrc.js
const path = require('path')
 
const buildEslintCommand = (filenames) =>
  `eslint --fix ${filenames
    .map((f) => `"${path.relative(process.cwd(), f)}"`)
    .join(' ')}`
 
module.exports = {
  '*.{js,jsx,ts,tsx}': [buildEslintCommand],
}

迁移现有配置

如果您的应用程序中已经配置了 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',
  ],
}

该插件可以正常安装到您的项目中

终端
pnpm add -D @next/eslint-plugin-next

这消除了由于在多个配置中导入相同的插件或解析器而可能发生的冲突或错误的风险。

额外配置

如果您已经使用单独的 ESLint 配置,并且想要包含 eslint-config-next,请确保它在其他配置之后最后扩展。例如

eslint.config.mjs
import { defineConfig, globalIgnores } from 'eslint/config'
import nextPlugin from '@next/eslint-plugin-next'
 
const eslintConfig = defineConfig([
  nextPlugin.configs['core-web-vitals'],
  // List of ignore patterns.
  globalIgnores([]),
])
 
export default eslintConfig

next 配置已经处理了为 parserpluginssettings 属性设置默认值。除非您需要针对您的用例进行不同的配置,否则无需手动重新声明任何这些属性。

如果您包含任何其他可共享配置,**您需要确保这些属性不会被覆盖或修改**。否则,我们建议删除任何与 next 配置共享行为的配置,或者如上所述直接从 Next.js ESLint 插件进行扩展。

版本更改
v16.0.0next linteslint next.config.js 选项已移除,转而支持 ESLint CLI。可使用代码转换来帮助您迁移。