2. 从零搭建企业级 Monorepo 工程化模板:ESLint 10 (基础骨架)+ Prettier 配置与避坑指南

导读

本系列第二章来啦!在上一章中,我们完成了 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 提供基础推荐规则,属于全局基础

  • 安装命令

    bash 复制代码
    pnpm add -D -w eslint @eslint/js

    说明:-w 表示安装到 workspace 根目录

1.1.2 共享配置包安装:Vue/TS 插件与 globals

  • 安装什么globals@typescript-eslint/parser@typescript-eslint/eslint-plugineslint-plugin-vuevue-eslint-parsereslint-config-prettier

  • 为什么放在共享配置包 :这些包是配置文件的直接依赖,会被 base-eslint-config.jstypescript-eslint-config.jsvue-eslint-config.js 直接 import;子包通过 workspace:* 引用配置包时,pnpm 会自动传递这些依赖,无需子包重复安装。

  • 安装命令 :进入 packages/eslint-config 目录执行

    bash 复制代码
    pnpm 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 中引用
    private true 防止误发布到 npm,仅内部使用。
    type module 声明使用 ES Module 规范,配置文件使用 import
    exports 对象 导出映射,允许子包通过 @hrms/eslint-config/xxx 的方式导入对应的配置文件,同时限制未列出的文件不可被外部访问。
    dependencies 对象 声明配置包运行时所需的所有依赖。由于这些依赖会被 base-eslint-config.jstypescript-eslint-config.jsvue-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:全局忽略规则,替代旧版.eslintignoreignorePatterns字段。这里忽略了隐藏文件、构建产物、声明文件、公共目录和静态资源目录。
    • languageOptions.globals:定义代码中可用的全局变量,避免像 windowprocess这样的全局变量被误报为未定义。使用 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-varsno-undef,因为在 TS 文件中它们会误报类型导入、接口等。然后启用 @typescript-eslintstrict 规则集,提供更严格的类型安全推荐规则。
    • 注意 :这里没有添加任何关闭特定规则的 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-varsno-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.jsonexports 暴露给子包使用。接下来,你需要在具体的 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 主依赖包。

    bash 复制代码
    pnpm add -D -w prettier

    作用:安装 Prettier 到根目录,作为全仓库统一的代码格式化工具。

  • 安装 Prettier 与 ESLint 冲突解决包。

    bash 复制代码
    pnpm 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.jsonexports 导出三个分层配置:
    • base-eslint-config.js:纯基础规则,包含官方推荐规则、全局变量和忽略文件。
    • typescript-eslint-config.js:继承基础配置,添加 TypeScript 解析与严格规则。
    • vue-eslint-config.js:继承 TypeScript 配置,添加 Vue 单文件组件解析与推荐规则。
  • 在根目录安装 prettiereslint-config-prettier,实现代码格式化与 ESLint 的规则解耦。
  • 添加 .prettierrc.json.prettierignore 配置文件,统一全仓库代码风格。

通过这套配置,任何子包只需继承对应的共享配置(如 @hrms/eslint-config/vue-eslint-config),即可获得一致的代码检查和格式化能力。后续我们可以基于此继续集成 Husky 和 lint-staged,让规范在提交前自动执行,真正做到"代码即规范"。

如果本文对你有帮助,欢迎点赞、收藏、评论,也欢迎指出不足之处,一起交流进步。

相关推荐
Dawson Zhu16 分钟前
从虚拟内存到 Agent 记忆:把大模型的“脑补“变成“查表“
人工智能·语言模型·架构·aigc·agi
Raas10016 分钟前
MAI Gateway(魔芋企业级AI网关)详解:AI网关在架构中的位置,一文读懂企业AI流量治理
大数据·人工智能·架构·gateway·ai网关·mai gateway
光影少年17 分钟前
react navite实现全局弹窗、Toast 组件
前端·react native·react.js
WebInfra21 分钟前
Rslib 1.0 正式发布:面向多场景的 JavaScript 库开发工具
前端·javascript·github
陈珙39 分钟前
.NET AI 实战:用 MCP 把 Claude Code 变成数据库 DBA
架构·.net·技术
2601_9620745842 分钟前
大数据-260 实时数仓 - 项目背景与需求 实时数仓架构 需求分析 技术选型 逻辑架构
大数据·架构
Tongsr1 小时前
别只混淆代码:用 Kaleido 加固整个 Android Release AAB
前端·算法·github
AIOps打工人1 小时前
【AIOPS】当运维 Agent 开始自己学:证据补全才是自学习的真门槛
程序员·架构
郭邯1 小时前
从零到一:我用 AI 写了一个贷款计算器,顺便把等额本息公式彻底搞懂了
前端