
1. 为什么保存时自动修正值得花时间配置我见过太多人把 ESLint 当成报错看看就好的工具编辑器里那一排红波浪线改完当前文件刷新一下又冒出来日复一日地在同一个空格、同一个分号上反复折腾。真正把 ESLint 自动修正配到位之后绝大多数格式类问题在文件保存的那一瞬间就被抹平了你能省下的不是几分钟而是每天被切碎的注意力。这篇内容就是围绕VSCode 配置 ESLint 自动修正这件事把配置链路从头到尾讲透包括装什么、填什么、为什么这么填、哪些坑一定会踩。先说清楚这篇东西适合谁。如果你已经在用 VSCode 写 JavaScript、TypeScript、Vue、React 这类前端或 Node 项目被 ESLint 的报错烦过但还没跑通保存即修复那这篇就是给你写的。如果你连 ESLint 都还没在项目里装起来也不用着急退出去我会在第二节把项目侧的准备一并交代清楚跟着做完就能对上。完全没用过 VSCode 的读者也能看懂配置项的含义只是操作时需要对着位置找一下。配置 ESLint 自动修正这件事情表面上是装个插件、勾个选项实际上它牵扯到三层东西项目本地的 ESLint 依赖与配置、VSCode 里的 ESLint 扩展、编辑器与语言服务之间怎么对接。这三层只要有一层没对齐表现就是保存没反应报错飘红但修复无效文件里一半红一半不红。很多人卡住的原因不是不懂 ESLint而是这三层的职责边界没理清改了半天改的是错的地方。我自己最早配这套东西的时候犯的错是把 ESLint 扩展的配置写在全局 settings 里结果换了个项目 ESLint 直接不工作了排查了两个小时才发现是全局配置里指了一个固定的工作目录。这种坑后面我会专门拎出来讲。所以这篇不会只给你一段 JSON 让你复制而是把每个字段为什么存在、删掉会怎样都讲明白这样你自己遇到变体也能判断。还有一点要提前说ESLint 的版本迭代比较快尤其是 9.x 之后引入的扁平配置flat config和之前的.eslintrc体系差别不小配置字段名、文件位置、扩展的识别逻辑都有变化。这篇内容会同时覆盖两套体系遇到差异明显的地方我会用表格对照避免你照着旧教程配完发现不生效。这个区分很关键因为目前网上大量教程还是.eslintrc时代写的你直接照抄在 9.x 项目里大概率会失效。接下来我会按项目侧准备、扩展层配置、settings.json 关键字段、新旧配置体系差异、常见报错排查这条线展开每个部分都给了可复现的操作和判断标准。你按顺序走基本能在十几分钟内把保存自动修正跑起来。2. 项目侧的准备ESLint 依赖与配置文件的正确姿势很多人一上来就装 VSCode 插件装完发现没反应其实问题出在项目侧——VSCode 的 ESLint 扩展本质上是个壳真正干活的 ESLint 引擎得来自你项目本地的 node_modules。这一点必须先理解否则后面所有排查都是白费。2.1 为什么必须是项目本地依赖而不是全局安装ESLint 官方从很早就明确建议把 ESLint 装在项目本地而不是全局。原因有三个每个都实际影响你后续的使用体验。第一是版本一致性。团队里每个人的机器上如果都装全局 ESLint版本不一样同一份代码在不同人那里报的错可能不同CI 跑出来的结果和本地也对不上。装在本地并写进devDependencies配合锁文件能保证谁拉下来都是同一个版本规则行为完全一致。第二是插件和配置的解析。ESLint 的插件体系比如eslint-plugin-vue、typescript-eslint/eslint-plugin在解析时会沿着目录向上查找node_modules本地安装能让这些解析路径稳定落在项目内。全局安装经常出现插件找不到或者加载到了另一个项目的插件这种诡异问题。第三是 VSCode 扩展的工作方式。ESLint 扩展默认会去工作区根目录找 ESLint 的安装位置找不到时会往上层目录找。如果你的项目没装而某个祖先目录恰好装了编辑器可能加载到那个版本导致配置和规则对不上报出一堆莫名其妙的错误。本地安装可以从根上避免这类错位。安装命令本身不复杂用你项目里的包管理器即可# npm npm install eslint --save-dev # pnpm pnpm add -D eslint # yarn yarn add -D eslint装完之后package.json的devDependencies里应该能看到eslint并且在node_modules/.bin下有可执行的eslint。这两点都满足才算项目侧第一步到位。2.2 初始化配置文件的两套体系ESLint 目前有两条配置路线你项目里属于哪条直接决定了后面 VSCode 配置的写法。传统体系.eslintrc.*配置文件是.eslintrc.js、.eslintrc.cjs、.eslintrc.json或.eslintrc.yml字段用extends、plugins、rules、env这些。ESLint 8.x 及以前的主力也是目前网上教程最多的一套。扁平体系eslint.config.jsESLint 9.x 起的默认方案用一个eslint.config.js或.mjs/.cjs导出数组每个数组元素是一个配置对象通过files指定适用的文件范围。它的好处是配置可组合、作用域清晰坏处是新教程少、和老插件生态的兼容需要额外处理。初始化的快捷方式是运行npx eslint --init这个交互式命令会问你几个问题用来做什么只检查语法、检查语法并发现问题、检查语法问题并强制代码风格、项目用什么模块体系、用哪个框架、是否用 TypeScript、代码跑在浏览器还是 Node、配置文件的格式。按你项目实际情况选择最后它会帮你装好对应的插件并生成配置文件。如果你项目里已经有一套配置就别重复初始化直接确认它是什么体系即可。判断方法很简单根目录下有没有eslint.config.js系列文件有就是扁平体系只有.eslintrc.*那就是传统体系。两个都存在的话以扁平体系为准9.x 下eslint.config.js优先级更高但建议把旧的删掉避免混淆。2.3 一个能跑起来的最小配置示例为了后面验证自动修正有效果你项目里最好有一条能被自动修复的规则。最典型的就是分号和引号。下面给两套体系的最小可用配置你按自己的体系取一份。传统体系.eslintrc.cjsmodule.exports { root: true, env: { browser: true, es2022: true, node: true, }, parserOptions: { ecmaVersion: latest, sourceType: module, }, extends: [eslint:recommended], rules: { semi: [warn, always], quotes: [warn, single], no-unused-vars: warn, }, };扁平体系eslint.config.jsimport js from eslint/js; export default [ js.configs.recommended, { files: [**/*.js], rules: { semi: [warn, always], quotes: [warn, single], no-unused-vars: warn, }, }, ];这里的root: true值得单独说一句。它告诉 ESLint当前目录是这个项目的根不要再往上找配置文件。没有它ESLint 会一路往上查到用户主目录甚至更上层如果那里恰好有个配置你的规则就会被合并进来行为变得不可预测。扁平体系里没有root字段因为它默认就是从配置文件所在目录开始算根算是把这层不确定性去掉了。规则的严重等级用off、warn、error三档或者对应的0、1、2。这里有个和自动修正强相关的点只有被标记为可修复fixable的规则才能被--fix自动改动。semi、quotes、indent、no-extra-semi、comma-dangle这些都是可修复的而no-unused-vars、no-undef这类是不可自动修复的只能靠你手动改或借助其他工具。理解这个区别你就不会奇怪为什么保存后有些红色消失了、有些还留着。配好之后先在命令行验证一遍这一步能帮你把项目侧的问题提前排掉npx eslint src --ext .js,.ts,.vue如果命令能正常输出问题列表没有报找不到配置文件或插件加载失败说明项目侧已经就绪可以进入编辑器配置了。3. VSCode 扩展层选对插件与理解它的工作方式项目侧准备好之后轮到 VSCode 这一层。这里的核心是装哪个扩展、扩展如何找到你项目的 ESLint、以及它默认会做哪些事。搞明白这三点配置起来就不容易迷糊。3.1 ESLint 扩展与几个容易混淆的替代品VSCode 里搜索 ESLint排在最前面的通常是Microsoft 官方的dbaeumer.vscode-eslint扩展 ID 是dbaeumer.vscode-eslint发布者是 Microsoft。这个就是你需要的那个。装它别装那些名字里带 ESLint 但实际是别的用途的。市面上还有几个容易混的扩展实际作用你要不要装ESLintdbaeumer集成 ESLint支持保存自动修复必装Prettier - Code formatter独立格式化工具和 ESLint 职责部分重叠视情况建议和 ESLint 分工Format on save 类辅助扩展大多只是帮你改 settings功能可手写不需要关于 Prettier 和 ESLint 的关系这里必须点一下因为它是高频踩坑点。两者都能管格式但定位不同ESLint 负责代码质量和一部分风格规则Prettier 专注纯格式化。如果你两个都开保存自动修复很可能出现Prettier 格式化完ESLint 又改回去或者反过来文件内容在两次保存之间抖动。正确做法是二选一主责常见组合是让 Prettier 管格式、用eslint-config-prettier关掉 ESLint 里和 Prettier 冲突的规则或者干脆全用 ESLint不装 Prettier。本文聚焦 ESLint 自动修正所以默认你不装 Prettier 或已经做好分工。3.2 扩展是怎么找到 ESLint 的理解扩展的查找逻辑是排查 90% 问题的钥匙。dbaeumer.vscode-eslint的默认行为大致是这样的它从当前打开的文件所在目录开始向上逐级查找node_modules/eslint找到第一个就用那个。同时配置项eslint.workingDirectories会改变这个起点。如果你没配它扩展就以每个文件所在目录为起点找如果你配了固定的工作目录它就只从那里找。这个机制带来两个实际后果。后果一多包仓库monorepo里子包各自有自己的 ESLint 和配置扩展能正确地按子包解析这是好事。后果二如果你在某个目录下有个孤儿node_modules或者祖先目录有旧版本 ESLint扩展可能加载错版本报出和命令行不一致的错误。判断扩展到底加载了哪个 ESLint 有个实用方法打开一个文件按CtrlShiftPmacOS 是CmdShiftP调出命令面板搜索并执行ESLint: Show Output Channel然后在输出面板里看它的日志通常会打印出它使用的 ESLint 路径和版本。这个步骤在排查阶段非常关键后面第 5 节会反复用到。3.3 扩展默认不做自动修复一个反直觉的点装了 ESLint 扩展默认它只报错不修复。保存文件时它不会主动帮你改代码除非你显式打开对应开关。这就是很多人装了插件还是没自动修的直接原因。扩展提供了几种触发修复的途径保存时修复editor.codeActionsOnSave里配置source.fixAll.eslint保存即触发。手动命令命令面板里的 ESLint: Fix all auto-fixable Problems对当前文件执行一次修复。快捷键绑定把这个命令绑到快捷键上需要时按一下。日常使用最顺的是保存时修复因为不打断思路。但手动命令也有价值尤其是你不想每次保存都动代码或者排查到底是哪条规则改了文件时手动触发一次更容易对照。我的建议是两个都留着保存时修复正常开着但把eslint.codeActionsOnSave.mode设为problems之外的场景时用手动命令兜底。顺带说一个默认值eslint.codeActionsOnSave.mode有两个可选值all和problems。all表示把能修的都修包括未被认定为问题的格式问题problems只修当前文件里被 ESLint 报出来的问题。默认是all。大多数场景用all更省事但如果你的项目对某些格式有特殊要求、不希望编辑器过度修改就改成problems只修真正报错的规则。4. settings.json 的关键字段每一行都值得解释到了核心的编辑器配置环节。下面这段是常见的工作区级配置我把它拆开逐项讲清楚你照着理解完再决定要不要全抄。{ eslint.enable: true, eslint.validate: [ javascript, javascriptreact, typescript, typescriptreact, vue, html ], eslint.workingDirectories: [{ mode: auto }], eslint.codeActionsOnSave.mode: all, editor.codeActionsOnSave: { source.fixAll.eslint: explicit }, [javascript]: { editor.defaultFormatter: dbaeumer.vscode-eslint } }4.1eslint.validate哪些文件该被管eslint.validate决定扩展对哪些语言的文件启动检查。默认值覆盖了 JS 系列但如果你写 Vue 的单文件组件、或者想在 HTML 里的内联脚本上也生效就必须手动加进去。这里有个容易忽略的细节Vue 文件默认是不在validate列表里的很多人配了 ESLint 之后发现.vue文件里保存不修复就是漏了这一项。加上vue之后扩展才会去检查 Vue 文件里的script部分。不过要注意validate只影响编辑器里是否启用检查Vue 文件真正能不能被解析还取决于项目里有没有装eslint-plugin-vue以及 parser 配置。如果插件没装加了vue反而可能报解析器找不到之类的错。所以顺序是先在项目里装好 Vue 的 ESLint 插件和 parser再来validate里加语言类型。还有一个eslint.probe字段和validate配合使用。probe决定扩展尝试检查哪些语言的文件只在文件类型没有明确声明时用。大多数情况下你不需要动它validate覆盖到就够。4.2eslint.workingDirectories单包与多包的分水岭这个字段是单包项目和 monorepo 项目差异最大的地方也是配置出错后最难排查的地方。单包项目项目根目录有一个package.json、一个 ESLint 配置、一份node_modules。这种情况下eslint.workingDirectories: [{ mode: auto }]是最省心的写法。auto模式让扩展自己判断工作目录——对每个打开的文件沿着目录向上找最近的package.json以那个目录作为 ESLint 的工作目录。这基本能覆盖单包和大部分多包场景。monorepo 或多根工作区可能每个子包有自己的package.json和配置也可能配置在根目录但依赖在子包。auto模式有时会判断错尤其是当你在根目录打开、但文件属于某个子包、根目录又有自己的node_modules时。这时候可以显式列出{ eslint.workingDirectories: [./packages/app, ./packages/lib] }显式列出能消除歧义代价是每加一个包就得改配置。所以我的经验是先试auto出问题再显式列。auto能解决就别手写维护成本低。还有一支特殊写法是给工作目录指定changeProcessCWD{ eslint.workingDirectories: [ { directory: ./packages/app, changeProcessCWD: true } ] }changeProcessCWD的作用是在运行 ESLint 时把进程的工作目录切到指定目录。某些依赖相对路径解析的插件比如某些处理路径别名的场景需要它。不确定要不要开时先别开遇到路径别名在编辑器里报错但命令行没问题再考虑。4.3editor.codeActionsOnSave保存时动作的总开关真正触发保存修复的是这一段{ editor.codeActionsOnSave: { source.fixAll.eslint: explicit } }source.fixAll.eslint是 ESLint 扩展注册的一个代码动作code action意思是在保存时运行所有 ESLint 可修复的问题。注意这里写的是字符串值explicit不是布尔值true。这是 VSCode 在较新版本里做的改动为的是区分显式保存触发的动作和自动保存触发的动作。这三个值的行为差别值得记住取值行为true保存和自动保存都会触发修复旧写法仍可用但不推荐explicit只有手动保存Ctrl/CmdS时触发自动保存不触发never从不触发选explicit的好处是开了自动保存的人不会因为每次停顿都触发一轮修复避免代码在你没主动保存时被改得不知不觉。如果你没开自动保存用true或explicit体验差不多但建议统一用explicit语义更明确。如果你的 VSCode 版本比较老可能不认字符串值那就退回用true。判断方法配了explicit后保存没反应、也没有代码动作执行就试试true。4.4 全局设置还是工作区设置同一个字段写在两处效果可能完全不同。全局设置User Settings对所有项目生效工作区设置Workspace Settings只对当前项目生效。ESLint 相关的配置强烈建议写在工作区设置里也就是项目根目录的.vscode/settings.json。理由很直接ESLint 的行为和项目强相关不同项目可能用不同版本的 ESLint、不同配置体系、不同的validate语言列表。写在全局换个项目就可能冲突。我之前把eslint.workingDirectories写死在全局里指向某个具体项目换项目后扩展直接不工作排查了很久才发现是全局配置在捣乱。写进工作区文件还有一个额外好处配置能跟着仓库走团队其他人克隆下来就能用不用人手一个口头教程。工作区设置文件的路径是项目根/.vscode/settings.json。VSCode 里通过CtrlShiftP执行 Preferences: Open Workspace Settings (JSON) 会直接打开这个文件不用手动建目录。4.5 一个容易忽略的开关默认格式化器上面配置里那段[javascript]: { editor.defaultFormatter: dbaeumer.vscode-eslint }它的作用是当你在 JS 文件里执行格式化文档时用 ESLint 来做。这属于可选配置。如果你同时装了 Prettier这段就要想清楚——两个格式化器抢活会乱。如果你不用 Prettier配上是合理的它让手动格式化和保存修复走同一套规则输出一致。特别提醒一句网上有些配置把editor.formatOnSave打开、同时也开了source.fixAll.eslint这时候保存会先走格式化器再走 ESLint 修复两个动作叠加。如果格式化器不是 ESLint可能出现格式化改一遍、ESLint 又改一遍的循环感。最稳妥的组合是只开source.fixAll.eslint保存修复不依赖formatOnSave或者确保两者用的是同一套规则来源。5. 新旧配置体系下编辑器行为的具体差异前面说了.eslintrc和eslint.config.js两套体系这里专门讲它们在 VSCode 集成场景下的差异因为这部分坑最多网上旧教程也最容易误导人。5.1 文件名与查找顺序传统体系下扩展找的是.eslintrc.js、.eslintrc.cjs、.eslintrc.json、.eslintrc.yml这些从文件所在目录向上找找到最近的用。加上root: true会在那一层停止向上查找。扁平体系下扩展找的是eslint.config.js或.mjs、.cjs从工作目录开始找。扁平配置没有向上逐级合并的概念除非你自己在配置里 import 别的配置一个项目一份语义简单很多。两者同时存在时9.x 的 ESLint 优先用eslint.config.jsdbaeumer扩展在新的版本里也跟随这个行为。如果你的项目正在从旧体系迁移迁移期间最好把旧文件删掉或改名别让它们并存否则编辑器行为和命令行行为可能不一致你会怀疑人生。5.2 扩展版本对扁平配置的支持dbaeumer.vscode-eslint对扁平配置的支持是逐步加入的较早的扩展版本只认.eslintrc。如果你项目已经切到eslint.config.js但扩展是老版本很可能出现命令行能跑编辑器不报错也不修复的情况。判断和解决方式打开扩展面板看dbaeumer.vscode-eslint的版本如果比较旧就更新到最新。更新后重启 VSCode用 Developer: Reload Window 命令比完全重启快。然后用前面说的 ESLint: Show Output Channel 确认它加载到了正确的配置文件和 ESLint 版本。这里有个实际的排查顺序建议先看扩展版本再看输出日志最后才去改配置。很多人一遇到不生效就狂改 settings结果根因是扩展太旧改多少都白搭。5.3 传统体系里的 parser 与插件配置在.eslintrc体系里TypeScript、Vue 这些非纯 JS 的场景需要显式指定 parser 和插件例如module.exports { root: true, parser: vue-eslint-parser, parserOptions: { parser: typescript-eslint/parser, ecmaVersion: latest, sourceType: module, }, plugins: [typescript-eslint, vue], extends: [ eslint:recommended, plugin:vue/vue3-recommended, plugin:typescript-eslint/recommended, ], rules: {}, };这段配置里parser和parserOptions.parser是两层外层vue-eslint-parser负责解析.vue文件结构内层typescript-eslint/parser负责解析script langts里的 TS 语法。少配一层Vue TS 项目就会报解析错误。这种嵌套 parser 的写法是传统体系里比较绕的地方编辑器里如果表现是整个文件语法错误飘红八成是这里没配好。5.4 扁平体系里的对应写法换成eslint.config.js同样的 Vue TS 场景大致是这样import js from eslint/js; import vue from eslint-plugin-vue; import tseslint from typescript-eslint; export default [ js.configs.recommended, ...tseslint.configs.recommended, ...vue.configs[flat/recommended], { files: [**/*.vue], languageOptions: { parserOptions: { parser: tseslint.parser, ecmaVersion: latest, sourceType: module, }, }, }, ];扁平体系用languageOptions.parserOptions.parser表达同样的嵌套关系用对象的files字段限定作用范围不再需要extends字符串。这套写法的好处是组合清晰每个来源一目了然代价是插件必须已经适配扁平配置部分老插件还没适配遇到这种就得暂时留在旧体系或者找社区提供的兼容层。5.5 用一张表对照两套体系的关键差异维度传统.eslintrc扁平eslint.config.js配置发现向上逐级查找就近合并从工作目录找单一文件停止条件root: true天然以配置所在目录为根语法对象 extends/plugins数组 files限定parser 配置parserparserOptions.parserlanguageOptions.parserOptions.parser扩展支持全版本支持较新版本扩展才支持组合方式字符串引用预设直接 import 并展开理解了这张表你再看任何一篇 ESLint 配置教程都能迅速判断它属于哪套体系、能否直接用在你的项目里。这是我自己踩过多次坑之后总结出的最省时间的判断方法。6. 保存不修复按这条链路一步步排查配置都写好了保存还是没动静这是最高频的问题。下面这条排查链路是我实际用下来覆盖面最广的按顺序走基本能定位到根因。关键原则是从外到内先确认项目侧再确认扩展侧最后确认配置侧别一上来就怀疑配置。6.1 第一步确认项目侧 ESLint 能跑在项目根目录执行npx eslint src/**/*.{js,ts,vue}如果这个命令本身就报错比如找不到 eslint、配置文件解析失败、插件加载失败那问题在项目侧编辑器再怎么配都没用。常见情况有依赖没装全、配置文件语法有误、插件版本和 ESLint 主体版本不兼容。命令能正常输出问题列表说明项目侧没问题进入下一步。如果输出的问题里那些本该可修复的规则比如分号没有在--fix后被修掉那就是规则配置或 parser 的问题不是编辑器的问题。顺便跑一次带--fix的npx eslint src/**/*.{js,ts,vue} --fix文件被正确修改说明 ESLint 引擎和规则都正常问题一定在编辑器侧。这一步的对照价值极大能立刻把排查范围砍掉一半。6.2 第二步确认扩展加载的 ESLint 路径命令面板执行 ESLint: Show Output Channel在输出面板里找类似这样的行ESLint server is running. ESLint library loaded from: /path/to/project/node_modules/eslint/lib/api.js重点看那个路径。如果它指向的不是你项目里的node_modules而是某个全局位置、另一个项目、或者一个不存在的路径那编辑器用的就不是你项目里的 ESLint。修复方式是检查eslint.workingDirectories是否正确或者把工作目录显式指到项目根{ eslint.workingDirectories: [{ directory: ., changeProcessCWD: false }] }同时确认项目根确实有node_modules/eslint。如果路径对了但还是不修复看日志里有没有 ESLint version 那一行确认版本和项目package.json里的一致。6.3 第三步确认保存动作真的触发了有时候扩展正常、ESLint 正常但保存动作没触发修复。这里排查三个点第一editor.codeActionsOnSave里是否写对了键名。必须是source.fixAll.eslint拼错一个字母都不生效。注意不是source.fixAll那会触发所有提供 fixAll 的来源也不是eslint.fixAll。第二值的类型是否符合你的 VSCode 版本。前面说过新版用explicit或true老版只认true。写了个新版才认的值在老版上就是静默失效没有任何提示。第三文件的语言是否在eslint.validate里。比如你在改.vue文件但validate里只写了javascript那这个文件根本不在扩展的管辖范围自然不会修复。验证方法打开文件时看编辑器右下角的语言模式确认是不是你预期的语言再看validate数组里有没有对应项。6.4 第四步规则本身是否可修复前面强调过只有可修复的规则才能被自动修。如果你文件里的红波浪全是no-unused-vars、no-undef、eqeqeq这类那保存后它们不会消失因为 ESLint 修不了。判断某个规则能不能自动修可以去 ESLint 官方规则文档看该规则有没有扳手图标表示 fixable。这一步容易被忽略但确实有一批人是因为等一个修不了的规则自动修好而困惑。6.5 一份常见症状与对策的对照表把上面几个环节的典型表现整理成表方便你直接对号入座症状可能原因对策保存完全没反应保存动作没配或值类型不对检查source.fixAll.eslint的键和值报错飘红但不修规则不可自动修复确认规则是否 fixable部分文件不修validate未包含该语言把语言加进validate编辑器报错和命令行不一致加载了错误的 ESLint 版本检查工作目录与输出日志修复后文件抖动Prettier 与 ESLint 同时改二选一主责关掉冲突规则Vue 文件不生效缺 Vue 插件/parser 或 validate 未加装插件、配 parser、加 validate6.6 一个被低估的排查手段手动命令当保存修复不工作时先用命令面板的 ESLint: Fix all auto-fixable Problems 手动触发一次。如果手动能修、保存不能修问题一定在保存动作的配置上editor.codeActionsOnSave如果手动也不修问题在扩展或项目侧。这个二分法非常好用能迅速缩小范围。我在一个 Vue 项目里遇到过保存不修复的情况手动命令却能修最后发现是项目的.vscode/settings.json里editor.codeActionsOnSave被另一个插件的默认值覆盖了写进去的source.fixAll.eslint没生效。后来把配置放到工作区设置里并重启窗口才恢复。这类被覆盖的情况不常见但用二分法能很快识别出来。7. 一些真正影响体验的细节与长期维护建议配置跑通只是第一步长期用下来还有几个细节会持续影响体验这里一并说说。7.1 让配置跟着仓库走把.vscode/settings.json提交到仓库意味着团队每个人拉下来就有一致的编辑器行为。但要注意不是所有 ESLint 配置都适合提交。涉及个人偏好的项比如是否开自动保存、是否显示内联提示可以放全局涉及项目规则一致性的项validate、workingDirectories、codeActionsOnSave.mode放工作区。这样既保证团队一致又不强制别人的个人习惯。提交之前确认.vscode不在.gitignore里。有些项目模板默认忽略了.vscode会导致你配好之后同事那边完全没效果。这算是个隐蔽坑值得检查一下。7.2 依赖版本对齐团队里 ESLint、各插件、dbaeumer.vscode-eslint扩展的版本尽量对齐。前三个通过package.json和锁文件能保证扩展版本只能靠约定或文档说明。当出现我这能修同事那不能修时第一步就是比扩展版本。这个动作很快但能省下大量无谓的配置对比。7.3 保存修复和自动保存的搭配如果你用自动保存files.autoSave配合explicit值行为是自动保存不修手动 CtrlS 才修。这对很多人来说反而是好事因为不会在你打字过程中反复改文件。如果你希望自动保存也修就得用true但要接受文件在你没主动保存时被改。两种都可以关键是明确自己要哪种别配了自动保存又抱怨代码自己变了。7.4 留意大文件与性能ESLint 在编辑器里是常驻运行的大项目里对性能有影响。如果感觉编辑时卡顿可以检查eslint.validate是否包含了太多语言或不必要的文件类型。精简validate到项目实际用的几种能减少不必要的检查。另外.eslintignore传统体系或配置里的ignores扁平体系把dist、node_modules、构建产物排除掉也能明显减负。这些排除项对编辑器同样生效别只以为它们影响命令行。7.5 一个实用的小配置组合最后给一个我实际在用的工作区配置片段它覆盖了单包项目最常见的场景你可以作为起点再按需调整{ eslint.enable: true, eslint.validate: [javascript, javascriptreact, typescript, typescriptreact, vue], eslint.workingDirectories: [{ mode: auto }], eslint.codeActionsOnSave.mode: all, editor.codeActionsOnSave: { source.fixAll.eslint: explicit }, eslint.run: onType }这里的eslint.run有两个取值onType打字时就检查和onSave保存时检查。onType反馈更即时配合自动修复用起来更顺手onSave更省性能适合大项目。这两个取值没有绝对优劣看你的项目规模和机器性能来定。我个人在中小项目里一直用onType加explicit保存修复的组合反馈快、改动可控。大项目里会切到onSave避免常驻检查拖慢编辑器。至于具体阈值我的经验是项目源文件超过几千个、或者编辑器明显卡顿时就该切了不必等到难以忍受才动手。