在团队协作的项目中,代码风格不统一、提交信息混乱、低质量代码被合入主干,这些看似琐碎的问题会不断侵蚀项目的可维护性。代码质量保障就是在这些细节上建立自动化防线,让“正确的代码习惯”成为默认选项,而不是依赖每个人的自觉。本节介绍一套已经在前端和 Node.js 项目中广泛使用的组合方案:ESLint + Prettier 统一代码风格,Husky + lint-staged + commitlint 守住提交质量。
17.3.1 ESLint + Prettier:代码质量的双层防线
ESLint 负责代码的逻辑质量:发现未使用的变量、禁止 console.log 遗留在生产代码、强制使用严格相等、限制回调嵌套深度等。Prettier 则专注于格式一致性:缩进是 2 空格还是 4 空格、单引号还是双引号、行末是否加分号等。两者分工明确,配合使用可以避免在代码评审中因格式问题浪费精力。
安装与基础配置
在一个典型的 Node.js 项目中,首先安装相关依赖:
npm install --save-dev eslint prettier
为了减少 ESLint 与 Prettier 之间的规则冲突,需要安装 eslint-config-prettier,它会关闭 ESLint 中所有与格式相关的规则,让 Prettier 全权负责格式。
npm install --save-dev eslint-config-prettier
ESLint 配置文件 .eslintrc.json 的一个实用示例如下:
{
"root": true,
"env": {
"node": true,
"es2022": true
},
"extends": [
"eslint:recommended",
"prettier"
],
"parserOptions": {
"ecmaVersion": "latest"
},
"rules": {
"no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
"no-console": "warn",
"eqeqeq": ["error", "always"]
}
}
这里 "extends": ["eslint:recommended", "prettier"] 表示先继承 ESLint 推荐的规则集,再用 Prettier 覆盖掉可能冲突的格式规则。"no-unused-vars" 允许以 _ 开头的未使用参数(常用于 middleware 的函数签名),"no-console" 给出警告而不强制报错。
Prettier 的配置文件 .prettierrc 则更简洁:
{
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 100,
"tabWidth": 2
}
这些选项决定了项目中代码的外观。"trailingComma": "es5" 在 ES5 支持的地方(数组、对象)加尾逗号,既方便增删行,又避免语法错误。
TypeScript 项目的额外配置
如果项目使用 TypeScript,需要将 ESLint 的解析器和规则替换为 TypeScript 版本:
npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin
修改 .eslintrc.json:
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"parserOptions": {
"project": "./tsconfig.json"
}
}
这样 ESLint 就能理解 TypeScript 语法,并应用对应的规则。
脚本集成与编辑器配合
在 package.json 中添加脚本:
{
"scripts": {
"lint": "eslint . --ext .js,.ts",
"lint:fix": "eslint . --ext .js,.ts --fix",
"format": "prettier --write ."
}
}
日常开发中,通过 VS Code 安装 ESLint 和 Prettier 插件,并设置保存时自动格式化,可以让开发者几乎感受不到这些工具的存在。大部分格式问题在保存的一瞬间就被修正,而明显的逻辑错误也会在编辑器中直接标红提示。
17.3.2 Husky + lint-staged:提交前自动检查
ESLint 和 Prettier 配置好了,但如果没有强制执行的机制,团队成员可能会忘记运行 lint 命令而将不符合规范的代码推到仓库。Husky 可以在特定的 Git 钩子(如 pre-commit)上自动执行脚本,而 lint-staged 则确保只检查本次提交中修改过的文件,避免全量扫描带来的性能浪费。
安装与配置
npm install --save-dev husky lint-staged
npx husky init
执行 npx husky init 会创建 .husky/ 目录并在其中生成一个 pre-commit 钩子文件。编辑这个文件:
# .husky/pre-commit
npx lint-staged
然后在 package.json 中配置 lint-staged:
{
"lint-staged": {
"*.{js,ts}": [
"eslint --fix",
"prettier --write"
],
"*.{json,md,yaml}": [
"prettier --write"
]
}
}
这段配置的意思是:对于所有被暂存的 JavaScript/TypeScript 文件,先运行 ESLint 自动修复,再用 Prettier 格式化;对于 JSON、Markdown、YAML 等文件则只用 Prettier 格式化。整个检查在提交时自动触发,如果 ESLint 发现无法自动修复的错误,提交会被中断,并在控制台输出具体错误信息,要求开发者手动修复后再提交。
这样一来,格式和基础逻辑问题在 git commit 阶段就被拦截下来,不会流入代码仓库。
17.3.3 commitlint:规范提交信息
提交信息混乱(如 fix bug、update、wip)会让后期查阅 Git 历史、生成 Changelog 变得困难。commitlint 可以校验提交信息是否符合约定的格式,流行的规范是 Conventional Commits,其要求提交信息形如:
<type>(<scope>): <subject>
[optional body]
[optional footer]
类型(type)必须为 feat、fix、docs、style、refactor、test、chore 等之一。
安装与配置
npm install --save-dev @commitlint/cli @commitlint/config-conventional
在项目根目录创建 commitlint.config.js:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [
'feat', // 新功能
'fix', // 修复 Bug
'docs', // 文档变更
'style', // 格式调整,不影响逻辑
'refactor', // 重构
'perf', // 性能优化
'test', // 测试相关
'chore', // 构建过程或辅助工具变更
'ci', // CI 配置变更
'revert' // 回滚提交
]],
'subject-case': [0] // 不强制标题大小写
}
};
然后通过 Husky 将 commitlint 挂载到 commit-msg 钩子上:
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg
配置完成后,如果尝试提交类似 git commit -m "fix something" 的信息,commitlint 会报错并给出规范提示,强制开发者按照约定格式书写,例如 git commit -m "fix(api): 修复用户登录接口的异常返回"。
17.3.4 统一团队开发环境的可选补充
除了上述核心工具外,还有一些细节可以进一步提升保障力度:
.editorconfig:提供编辑器的基本缩进、换行符设置,让不同编辑器的开发者打开项目时默认风格一致。engines字段:在package.json中声明"engines": { "node": ">=18" },可以配合.npmrc或 CI 检查来确保团队使用一致的 Node.js 版本。- VSCode 工作区设置:可在
.vscode/settings.json中统一设置保存时自动格式化、默认使用项目的 ESLint/Prettier 等,配合共享extensions.json推荐插件,让新加入的开发者快速进入状态。
17.3.5 真实项目中的落地效果
这套组合方案在初期配置大约需要 10-15 分钟,但它能够持续节省团队大量时间,实际效果表现在:
- 代码评审聚焦逻辑:不再有“请在这里加分号”“缩进不对”等机械性评论,评审者可以专注于架构设计、性能隐患和业务边界。
- 提交历史清晰可读:通过规范化提交信息,结合
standard-version等工具可以自动生成 CHANGELOG 并管理版本号。 - 新人降低犯错概率:自动检查机制让新加入的成员在一次失败的提交后立即了解项目规范,学习成本比阅读文档更直接。
代码质量保障不是约束,而是建立共识。当整个团队都依赖同一套自动化规则,代码风格就不再是个人偏好的博弈,而成为团队文化的一部分。这一节的内容,为后续测试体系、CI/CD 自动化部署等工程化实践奠定了坚实的基础。