导读
本系列第二章来啦!在上一章中,我们完成了 Monorepo 基础结构初始化、第一个 Vue3 应用(hrms-admin)的创建,以及共享 TypeScript 配置包的设计。本章我们将正式进入工程化规范的核心环节:集成 ESLint 10 与 Prettier。你将学到如何创建共享 ESLint 配置包、使用 ESLint 10 的 flat config 新格式、处理与 TypeScript 和 Vue 的集成,以及如何避免配置过程中常见的坑。学完本章,你的项目将拥有统一的代码质量检查和自动格式化能力,为后续接入 Husky 和 lint-staged 打下坚实基础。
第一步:ESLint 10 安装与配置
ESLint 是一个代码质量检查工具 ,它通过解析代码为 AST(抽象语法树),根据预设规则发现潜在错误、风格问题和最佳实践违背。与 Prettier 不同,ESLint 关注的是代码是否正确、是否遵循最佳实践,例如未使用的变量、类型不安全的操作、不推荐的语法等。
在 Monorepo 中,为了让所有子包拥有统一的代码规范,通常将 ESLint 配置抽离为共享配置包,方式与共享 TypeScript 配置类似。但 ESLint 10 使用 flat config 格式(eslint.config.js),不再使用旧的 .eslintrc 文件。我们同样可以创建一个 packages/eslint-config 包,导出 flat config 数组供子包继承。
核心要点:
- ESLint 10 默认使用 flat config,配置文件名为
eslint.config.js(或.mjs) - 共享配置包通过
exports导出配置数组。 - 子包可以继承共享配置,并覆盖自己的规则。
1.1 ESLint 10 安装依赖包
1.1.1 根目录安装:eslint 与 @eslint/js
-
安装什么 :
eslint、@eslint/js -
为什么放在根目录 :
eslint是命令工具,所有子包共用;@eslint/js提供基础推荐规则,属于全局基础 -
安装命令:
bashpnpm add -D -w eslint @eslint/js说明:
-w表示安装到 workspace 根目录
1.1.2 共享配置包安装:Vue/TS 插件与 globals
-
安装什么 :
globals、@typescript-eslint/parser、@typescript-eslint/eslint-plugin、eslint-plugin-vue、vue-eslint-parser、eslint-config-prettier -
为什么放在共享配置包 :这些包是配置文件的直接依赖,会被
base-eslint-config.js、typescript-eslint-config.js、vue-eslint-config.js直接import;子包通过workspace:*引用配置包时,pnpm 会自动传递这些依赖,无需子包重复安装。 -
安装命令 :进入
packages/eslint-config目录执行bashpnpm add globals @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-vue vue-eslint-parser eslint-config-prettier -
提示:不需要在子包重新安装这些插件
1.2 搭建 Monorepo 项目的 ESLint 基础骨架(不包含项目具体规则配置)
1.2.1 配置 package.json 文件
-
操作 :在
packages/eslint-config目录下创建package.json文件。 -
作用 :将 ESLint 共享配置声明为一个独立的 workspace 包,对外导出多个配置文件入口,并集中管理该包运行所有的依赖,使其他子包通过
workspace:*引用。 -
代码块:
json{ "name": "@hrms/eslint-config", "version": "0.0.1", "private": true, "type": "module", "exports": { "./base-eslint-config": "./base-eslint-config.js", "./typescript-eslint-config": "./typescript-eslint-config.js", "./vue-eslint-config": "./vue-eslint-config.js" }, "dependencies": { "globals": "^17.0.0", "@typescript-eslint/parser": "^8.0.0", "@typescript-eslint/eslint-plugin": "^8.0.0", "eslint-plugin-vue": "^10.0.0", "vue-eslint-parser": "^10.0.0", "eslint-config-prettier": "^9.0.0" } } -
字段解析:
字段 值 作用 name@hrms/eslint-config共享配置包的名称,使用 @hrms作用域,便于在 monorepo 中引用privatetrue防止误发布到 npm,仅内部使用。 typemodule声明使用 ES Module 规范,配置文件使用 importexports对象 导出映射,允许子包通过 @hrms/eslint-config/xxx的方式导入对应的配置文件,同时限制未列出的文件不可被外部访问。dependencies对象 声明配置包运行时所需的所有依赖。由于这些依赖会被 base-eslint-config.js、typescript-eslint-config.js、vue-eslint-config.js直接import,所以放在dependencies中,子包通过workspace:*引用本包时,pnpm 会自动处理这些传递依赖,无需在子包重复安装。
1.2.2 配置 base-eslint-config.js 文件
-
操作 :在
packages/eslint-config目录下创建base-eslint-config.js文件。 -
作用:提供最基础、所有项目通用的 ESLint 规则,包括官方推荐规则、忽略文件列表和全局变量定义。不包含任何特定框架(如 Vue)或业务规则,保证纯净可复用。
-
代码块:
javascript// ESLint base 配置文件,使用 ESM 语法 import eslint from "@eslint/js"; import globals from "globals"; export default [ // 继承 ESLint 官方推荐的规则 eslint.configs.recommended, { // 忽略不需要检查的文件 ignores: ["**/.*", "**/dist/*", "*.d.ts", "public", "**/assets/*"], }, { // 配置全局变量,避免在代码中使用未定义的全局变量时报错 languageOptions: { globals: { ...globals.browser, // 浏览器环境 ...globals.node, // Node.js 环境 ...globals.es2020, // ES2020 环境 }, }, }, ]; -
字段解析:
eslint.configs.recommended:ESLint 官方提供的推荐规则集,包含了绝大多数基本的代码质量检查规则,是 flat Config 中常见的起点。ignores:全局忽略规则,替代旧版.eslintignore或ignorePatterns字段。这里忽略了隐藏文件、构建产物、声明文件、公共目录和静态资源目录。languageOptions.globals:定义代码中可用的全局变量,避免像window、process这样的全局变量被误报为未定义。使用globals包提供的预设,按环境合并。注意:这里故意没有写任何rules自定义规则。因为这些规则往往带有项目偏好(比如是否允许console、是否强制使用const等),应放在具体的子包或更高层的预设中,保持基础配置的通用性。
1.2.3 配置 typescript-eslint-config.js 文件
-
操作 :在
packages/eslint-config目录下创建typescript-eslint-config.js文件 -
作用:在基础配置之上,为所有 TypeSript 项目提供解析器、插件和推荐规则。它不包含任何具体项目的偏好关闭项,只做通用能力增强,供纯 TS 包或 Vue 配置继承。
-
代码块 :
javascript// TypeScript 项目的共享 ESLint 配置 // 继承基础规则,添加 TypeScript 解析与推荐规则 import baseConfig from "./base-eslint-config.js"; import tsParser from "@typescript-eslint/parser"; import tsPlugin from "@typescript-eslint/eslint-plugin"; export default [ ...baseConfig, { files: ["**/*.{ts,tsx,cts,mts}"], languageOptions: { parser: tsParser, parserOptions: { ecmaVersion: "latest", sourceType: "module", projectService: true, warnOnUnsupportedTypeScriptVersion: false, }, }, plugins: { "@typescript-eslint": tsPlugin, }, rules: { // 关闭原生规则,启用 TS 版本,避免误报 "no-unused-vars": "off", "no-undef": "off", // 启用 TypeScript 严格推荐规则 ...tsPlugin.configs.strict.rules, }, }, ]; -
字段解析 :
files:限制此配置块仅对 TypeScript 文件生效,包括.ts、.tsx、.cts、.mts。languageOptions.parser:使用@typescript-eslint/parser作为解析器,使 ESLint 能理解 TypeScript 语法。languageOptions.parserOptions.projectService: true:启用 TypeScript 项目服务,自动处理项目引用、多 tsconfig 等情况,避免手动指定project路径的麻烦和常见错误(如 vite.config.mts 解析失败)。plugins:注册@typescript-eslint插件,使该插件提供的规则可被使用。rules:首先关闭原生no-unused-vars和no-undef,因为在 TS 文件中它们会误报类型导入、接口等。然后启用@typescript-eslint的strict规则集,提供更严格的类型安全推荐规则。- 注意 :这里没有添加任何关闭特定规则的
off,保持共享配置纯净。如果项目需要放宽某些规则(例如允许any),应在子包配置中覆盖。
1.2.4 配置 vue-eslint-config.js 文件
-
操作 :在
packages/eslint-config目录下创建vue-eslint-config.js文件。 -
作用 :为 Vue 3 + TypeScript 项目提供完整的 ESLint 规则,继承 TypeScript 配置,并添加 Vue 单文件组件(.vue)的解析和官方推荐规则,最后通过
eslint-config-prettier关闭与 Prettier 冲突的格式规则。 -
代码块:
javascript// Vue + TypeScript 项目的共享 ESLint 配置 // 继承 TypeScript 配置,并添加 Vue 单文件组件支持 import vueParser from "vue-eslint-parser"; import tsConfig from "./typescript-eslint-config.js"; import pluginVue from "eslint-plugin-vue"; import tsParser from "@typescript-eslint/parser"; import tsPlugin from "@typescript-eslint/eslint-plugin"; import prettierConfig from "eslint-config-prettier"; export default [ // 1. 继承 TypeScript 配置(已包含基础规则和 TS 规则) ...tsConfig, // 2. Vue 官方推荐的 flat 规则集 ...pluginVue.configs["flat/recommended"], // 3. Vue 单文件组件特殊解析器配置 { files: ["**/*.vue"], languageOptions: { parser: vueParser, parserOptions: { parser: tsParser, parserOptions: { ecmaVersion: "latest", sourceType: "module", projectService: true, }, extraFileExtensions: [".vue"], }, }, plugins: { "@typescript-eslint": tsPlugin, }, rules: { // 关闭原生规则,启用 TS 版本 "no-unused-vars": "off", "no-undef": "off", // 对 <script> 部分启用 TS 推荐规则 ...tsPlugin.configs.recommended.rules, }, }, // 4. 关闭所有与 Prettier 冲突的格式规则 prettierConfig, ]; -
字段解析:
vueParser:从vue-eslint-parser包导入,作为.vue文件的主解析器,能够解析<template>、<script>、<style>等区块。...tsConfig:继承 TypeScript 配置,使 .ts 文件继续使用 TS 规则。...pluginVue.configs["flat/recommended"]:引入 Vue 官方推荐规则,包含模板和基础脚本规则。files: ["**/*.vue"]:对.vue文件单独配置解析器。parserOptions.parser: tsParser:指定内部使用 TypeScript 解析器解析<script lang="ts">部分。parserOptions.parserOptions:传递给内部 TypeScript 解析器的选项,这里同样开启projectService以正确识别 Vue 文件所在的 tsconfig 项目。extraFileExtensions: [".vue"]:允许 TS 解析器识别.vue扩展名。rules:关闭原生no-unused-vars和no-undef,启用@typescript-eslint/recommended规则(Vue 场景下通常使用 recommended 而非 strict,以避免过度限制模板相关代码)。prettierConfig:放在数组最后,利用eslint-config-prettier关闭所有与 Prettier 冲突的格式规则,确保 ESLint 只负责代码质量,格式化交给 Prettier。
1.2.5 TS 配置与 Vue 配置的规则集不一致
- typescript-eslint-config.js 中使用了
...tsPlugin.config.strict.rules(严格规则集) - vue-eslint-config.js 中使用了
...tsPlugin.config.recommended.rules(推荐规则集)
这里使用 strict 而不是 recommended 是为了给纯 TypeScript 项目提供更严格的类型安全约束。Vue 项目由于模板与脚本交互的特殊性,在 Vue 配置中会降级为 recommended,避免误报。
1.3 小结
至此,共享配置包 @hrms/eslint-config 的三个核心文件已经完成:
base-eslint-config.js:纯基础规则typescript-eslint-config.js:TS 通用规则vue-eslint-config.js:Vue + TS 通用规则
它们通过 package.json 的 exports 暴露给子包使用。接下来,你需要在具体的 Vue 应用(如 hrms-admin)中创建 eslint.config.mjs 并继承 vue-eslint-config,然后按需添加项目特定规则覆盖。这样整个 ESLint 体系就完整落地了。
第二步:Prettier 安装与配置
Prettier 是一个代码格式化工具 ,它能够自动统一代码的风格,比如缩进、空格、引号、换行、分号等。与 ESLint 不同,Prettier 不关注代码逻辑是否正确,只关注代码的外观是否一致 。它支持多种语言(JavaScript、TypeScript、Vue、CSS、JSON 等),并且配置简单,可以大幅减少团队中因代码风格不同而产生的冲突。在工程化实践中,通常将 Prettier 与 ESLint 配合使用:ESLint 负责检查代码质量和潜在错误,Prettier 负责自动格式化,两者通过 eslint-config-prettier 关闭冲突规则,实现各司其职。
2.1 安装 Prettier 与 eslint-config-prettier
Prettier 属于 开发依赖 所以它应该被安装到根目录的 devDependencies 中。
-
安装 Prettier 主依赖包。
bashpnpm add -D -w prettier作用:安装 Prettier 到根目录,作为全仓库统一的代码格式化工具。
-
安装 Prettier 与 ESLint 冲突解决包。
bashpnpm add -D -w eslint-config-prettier作用:关闭 ESLint 中与 Prettier 格式规则冲突的选项,让 ESLint 专注于代码质量,Prettier 专注于代码格式,两者互不干扰。该包在 ESLint 配置中作为最后一个 extends 引入。
2.2 配置 .prettierrc.json 格式化配置文件与 .prettierignore 忽略文件
2.2.1 .prettierrc.json 配置文件
-
在项目根目录下创建
.prettierrc.json并录入以下内容:json{ "printWidth": 120, "semi": true, "singleQuote": false, "useTabs": false, "trailingComma": "es5", "arrowParens": "avoid", "bracketSpacing": true, "proseWrap": "preserve", "endOfLine": "auto", "jsxSingleQuote": false, "htmlWhitespaceSensitivity": "ignore" } -
字段解析:
| 字段 | 值 | 说明 |
|---|---|---|
printWidth |
120 |
每行最大字符数,超过会换行,120 是常见的宽松选择 |
semi |
true |
语句末尾强制加分号 |
singleQuote |
false |
使用双引号而非单引号 |
useTabs |
false |
使用空格缩进,而不是 Tab |
trailingComma |
"es5" |
在 ES5 支持的地方(对象、数组等)添加尾逗号 |
arrowParens |
"avoid" |
箭头函数参数只有一个时省略括号(如 x => x) |
bracketSpacing |
true |
对象字面量的花括号内加空格({ foo: bar }) |
proseWrap |
"preserve" |
保持 Markdown 等文本的换行原样 |
endOfLine |
"auto" |
自动检测文件行尾符(LF/CRLF),避免跨平台冲突 |
jsxSingleQuote |
false |
JSX 属性使用双引号 |
htmlWhitespaceSensitivity |
"ignore" |
忽略 HTML(含 Vue 模板)中的空白敏感度 |
-
注意事项:
-
trailingComma: "es5"是 Prettier 3.x 的合法值,但若想在所有可能位置都加尾逗号(包括函数参数),可改为"all",看团队习惯。 -
htmlWhitespaceSensitivity: "ignore"可能让 Vue 模板中的空白被随意处理,某些情况下会影响渲染(尤其是pre标签或依赖空白的布局),建议根据实际项目决定是否保留。 -
这个配置没有写在
.prettierrc还是package.json中?通常放在根目录的.prettierrc或.prettierrc.json,确保全仓库统一。
2.2.2 .prettierignore 忽略文件
- 在项目根目录下创建
.prettierignore并录入以下内容:
json
node_modules
dist
coverage
.turbo
.vscode
pnpm-lock.yaml
写在最后
本章我们完成了 ESLint 10 与 Prettier 的集成,为 Monorepo 项目搭建了统一的代码质量检查和自动格式化体系,主要包括:
- 在根目录安装
eslint与@eslint/js,作为全仓库的 ESLint 命令工具和基础规则来源。 - 创建共享配置包
packages/eslint-config,通过package.json的exports导出三个分层配置:base-eslint-config.js:纯基础规则,包含官方推荐规则、全局变量和忽略文件。typescript-eslint-config.js:继承基础配置,添加 TypeScript 解析与严格规则。vue-eslint-config.js:继承 TypeScript 配置,添加 Vue 单文件组件解析与推荐规则。
- 在根目录安装
prettier和eslint-config-prettier,实现代码格式化与 ESLint 的规则解耦。 - 添加
.prettierrc.json和.prettierignore配置文件,统一全仓库代码风格。
通过这套配置,任何子包只需继承对应的共享配置(如 @hrms/eslint-config/vue-eslint-config),即可获得一致的代码检查和格式化能力。后续我们可以基于此继续集成 Husky 和 lint-staged,让规范在提交前自动执行,真正做到"代码即规范"。
如果本文对你有帮助,欢迎点赞、收藏、评论,也欢迎指出不足之处,一起交流进步。