前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

ESLint 9新特性、重大变化与从8升级的完整攻略

首页2024-04-28 14:40:12Front-End
ESLint前端开发代码规范Flat Config版本升级

把一个跑了三年的项目从 ESLint 8 升到 9,第一次 npx eslint . 直接吐出一堆红字,说找不到配置文件。项目根目录明明躺着 .eslintrc.json,ESLint 就是当没看见。这不是 bug,是 9.0 把默认配置系统整个换掉了。

ESLint 9.0.0 在 2024 年 4 月正式发布,是这个工具历史上改动最大的一次。Flat Config 从可选变成默认,一批格式化程序被踢出核心包,推荐规则集调整,规则 API 也做了破坏性改革。这篇把这些变化逐条拆开,配上 8 和 9 的对比表格,让你知道升级过程中每个报错对应的是哪一项改动。

在本篇文章中,我们将从浅入深,和大家一起学习以下知识:

  • Node.js 版本要求变化,以及为什么 19.x 被排除在外
  • Flat Config 的结构、字段含义与和 eslintrc 的对应关系
  • 老项目怎么用 FlatCompat 过渡,什么时候该彻底重写配置
  • 移除的格式化程序、规则和 context 方法的完整清单
  • 规则默认行为的几处静默变化,最容易在升级后误伤代码
  • 新增的 --stats、--inspect-config 和 loadESLint() 怎么用
  • 写插件的人需要改哪些地方
  • 一份可以照着走的六步升级流程

# 一、先确认 Node 版本

升级第一件事不是装 ESLint,是看 Node。

ESLint 9 不再支持 Node.js v18.18.0 以下的版本,也不再支持 v19.x。最低要求是 v18.18.0 或更高。

# 检查Node.js版本
node -v

# 如果版本过低,需要升级Node.js
nvm install 20
nvm use 20
@前端进阶之旅: 代码已经复制到剪贴板

v19 被整个排除掉这件事经常有人问。原因是 Node 的奇数版本号是非 LTS 的短期发布线,19.x 早就过了维护期,ESLint 没有理由为一条已经停止支持的分支付出兼容成本。如果你线上还在跑 v19,升级 ESLint 之前先把 Node 挪到 20 或者 18.18 以上,这一步绕不过去。

版本确认完再装。

# 安装最新版本的ESLint
npm install eslint@9 --save-dev

# 或指定版本
npm install eslint@9.0.0 --save-dev
@前端进阶之旅: 代码已经复制到剪贴板

# 二、Flat Config 是怎么回事

ESLint 9 最大的变化是 Flat Config 成为默认配置格式,原来基于 .eslintrc.* 的方式正式被弃用。

新的配置文件名有三种。

  • eslint.config.js
  • eslint.config.mjs
  • eslint.config.cjs

ESLint 会从当前工作目录往上找这三个文件,找不到就报错,而不是回退去读 .eslintrc.json。开头那个「找不到配置文件」的报错就是这么来的。

那为什么要换。老的 eslintrc 系统有几个绕不开的设计问题。extends 的继承链是字符串解析出来的,你很难知道最终生效的规则是哪一层给的;插件名要遵守 eslint-plugin- 前缀约定,ESLint 自己去 node_modules 里找,路径解析在 monorepo 里经常出错;env 这种预设集合是硬编码在 ESLint 内部的,加一个新环境要改核心代码。

Flat Config 的思路是把这些全部交还给 JS 模块系统。配置文件就是一个导出数组的普通模块,插件是你自己 import 进来的对象,继承就是数组展开,谁覆盖谁一目了然。

# 新配置文件的结构

// eslint.config.js
export default [
  {
    name: 'my-configuration',
    files: ['**/*.js'],
    ignores: ['**/dist/**'],
    languageOptions: {
      ecmaVersion: 2022,
      sourceType: 'module',
      globals: {
        browser: true,
        node: true,
        es2022: true
      }
    },
    linterOptions: {
      noInlineConfig: false,
      reportUnusedDisableDirectives: 'warn'
    },
    plugins: {
      react: reactPlugin
    },
    rules: {
      'no-unused-vars': 'error',
      'react/react-in-jsx-scope': 'off'
    }
  }
];
@前端进阶之旅: 代码已经复制到剪贴板

数组里每一项叫一个 config object,ESLint 会按顺序把匹配当前文件的所有配置项合并,后面的覆盖前面的。这个规则很简单,但正是因为简单,你才能靠肉眼推断出最终结果。

各字段的作用整理成表。

属性 说明
name 配置名称,用于错误消息中识别配置
files glob模式,指定配置适用的文件
ignores glob模式,指定忽略的文件
languageOptions JavaScript语言配置
linterOptions Linter过程相关设置
plugins 插件配置
rules 规则配置
settings 共享设置

有个坑要注意。ignores 写在带 files 的配置项里,只对这一项生效;单独写一个只有 ignores 的配置项,才是全局忽略。另外 .eslintignore 文件在 Flat Config 下彻底不被读取了,从 8 升上来最容易漏掉这一步,表现是构建产物目录突然开始被 lint,报出成千上万条错误。

用官方推荐规则集的写法也变了。

// eslint.config.js
import js from '@eslint/js'

export default [
  js.configs.recommended,
  {
    rules: {
      'no-unused-vars': 'warn'
    }
  }
]
@前端进阶之旅: 代码已经复制到剪贴板

以前写 extends: ['eslint:recommended'],现在要装 @eslint/js 然后 import 进来。这个包是从 ESLint 核心里拆出去的,装 eslint 时不会自动带上,得单独装。

# 老项目怎么过渡

如果项目庞大到没法一次性重写配置,@eslint/eslintrc 提供了 FlatCompat,可以把老格式的配置塞进新系统。

// eslint.config.js
import { FlatCompat } from '@eslint/eslintrc'
import path from 'path'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const compat = new FlatCompat({
  baseDirectory: __dirname
})

export default [
  ...compat.extends('standard', 'react'),
  ...compat.env({
    es2022: true,
    node: true
  }),
  ...compat.plugins('react'),
  {
    rules: {
      'semi': 'error'
    }
  }
]
@前端进阶之旅: 代码已经复制到剪贴板

compat.extends() 对应老的 extends,compat.env() 对应 env,compat.plugins() 对应 plugins 数组。它做的事情是把老写法翻译成等价的 config object 数组再展开进去。

我的建议是把 FlatCompat 当过渡手段而不是终点。它能让你今天就完成升级,但配置的可读性会变差,而且社区的配置包陆续都提供原生 Flat Config 导出之后,留着 compat 层反而是负担。等你依赖的几个 config 包都出了新版本,就该把它拆掉。

如果你想看一份已经完全是 Flat Config 写法、跑在 Next.js 项目上的完整配置,可以看我另一篇 基于 ESLint 9 配置前端开发规范,那篇把规则取舍也一条条说了。

# 三、ESLint 8 与 9 的对比清单

这一节是升级时最实用的部分,遇到报错先来这里对一眼。

# 配置方式

特性 ESLint 8 ESLint 9
配置文件 .eslintrc.json eslint.config.js
配置格式 对象形式 数组形式
插件引用 plugins: ['react'] plugins: { react: reactPlugin }
环境变量 env属性 languageOptions.globals
全局变量 globals属性 languageOptions.globals
推荐规则 extends: ['eslint:recommended'] js.configs.recommended

env 这一行的变化影响面最广。以前写 env: { browser: true },ESLint 内部会把浏览器的一整套全局变量塞进来。现在没有这个预设了,要么自己列,要么装 globals 这个包,写成 globals: { ...globals.browser }。忘了这一步的典型症状是满屏的 'window' is not defined。

# API 变化

特性 ESLint 8 ESLint 9
主类 ESLint ESLint (原FlatESLint)
加载配置 自动 loadESLint()
CLI eslint CLI eslint CLI (默认flat config)
环境变量 ESLINT_USE_FLAT_CONFIG=false 默认开启

ESLINT_USE_FLAT_CONFIG=false 这个环境变量是 9.x 留的后门,设了它 ESLint 会退回去读 eslintrc。实在来不及改配置又必须先升 ESLint 的话,可以拿它救一下急,但要清楚这是临时方案,后续大版本会把这条路封掉。

# 移除的格式化程序

移除的格式化器 替代npm包
checkstyle eslint-formatter-checkstyle
compact eslint-formatter-compact
jslint-xml eslint-formatter-jslint-xml
junit eslint-formatter-junit
tap eslint-formatter-tap
unix eslint-formatter-unix
visualstudio eslint-formatter-visualstudio

保留在核心里的只有 stylish、html、json、json-with-metadata 四个。

这条对 CI 影响最大。很多流水线用 --format junit 把结果喂给测试报告系统,升级之后直接报找不到 formatter,构建全红。改法很简单,把对应的 eslint-formatter-* 包装上就行,用法不变。踩到这个坑的人特别多,因为本地跑 lint 用的是默认 stylish,根本发现不了。

# 移除的规则

移除的规则 替代方案
valid-jsdoc 使用 eslint-plugin-jsdoc
require-jsdoc 使用 eslint-plugin-jsdoc

这两条本来就长期处于弃用状态,JSDoc 相关的检查交给专门的插件做更合适。

# 命令行参数

fe
  • 一、先确认 Node 版本
  • 二、Flat Config 是怎么回事
    • 新配置文件的结构
    • 老项目怎么过渡
  • 三、ESLint 8 与 9 的对比清单
    • 配置方式
    • API 变化
    • 移除的格式化程序
    • 移除的规则
    • 命令行参数
    • 规则默认行为
    • 内联注释
  • 四、新增的几个能力
    • no-useless-assignment 规则
    • 性能统计 --stats
    • 配置检查器 --inspect-config
    • loadESLint() API
  • 五、几条规则的具体变化
    • no-inner-declarations
    • no-useless-computed-key
    • no-unused-vars
    • complexity
  • 六、写插件的人要改什么
    • 函数式规则不再工作
    • 规则必须声明 meta.schema
    • context 上的方法搬家了
    • 用 @eslint/compat 兜底
  • 七、照着走的六步升级流程
  • 总结
  • 参考

← 大文件上传实战,Node.js 分片上传断点续传与秒传完整落地微前端落地方案对比,qiankun 无界 Module Federation 怎么选 →