首页 / Node.js 教程 / Lint 与格式化

Node.js 教程

Lint 与格式化

本教程共 76 篇 · 第 63 篇 · 更新于 2026-07-25 · 约 6 分钟阅读

Node.jsESLintPrettierhusky代码规范

63. Lint 与格式化

本节目标:- ESLint 9 的 flat config 怎么写,常用规则有哪些 - Prettier 负责格式化,如何和 ESLint 配合不打架 - 用 husky + lint-staged 在 git 提交前自动检查

代码能跑只是第一步。一旦项目变大、人变多,「风格各异」比 bug 还让人头疼——有人用双引号有人用单引号,有人加分号有人不加分号,diff 里一半是无关紧要的格式改动。Lint(静态检查)和格式化(Formatter)就是来解决这个问题的:前者帮你揪出潜在错误和坏味道,后者把代码刷成统一样子。这一章讲 ESLint 9、Prettier,以及用 husky 在提交前自动跑它们。

ESLint:代码的质检员

ESLint 是最主流的 JavaScript / TypeScript 静态检查工具。它不运行你的代码,而是读 AST(抽象语法树),按规则(rule)一条条核对:有没有未使用的变量、有没有用 == 而不是 ===、有没有可能出错的 await 漏掉……

安装与初始化

npm install --save-dev eslint
npx eslint --init

ESLint 9 起默认采用「扁平配置」(flat config),配置文件是项目根目录的 eslint.config.js(ESM)。它终于告别了过去层层覆盖的 .eslintrc 时代,配置写起来更直白:

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

export default [
  js.configs.recommended,
  {
    files: ['**/*.js', '**/*.mjs'],
    languageOptions: {
      ecmaVersion: 2024,
      sourceType: 'module',
    },
    rules: {
      'no-unused-vars': 'warn',
      'no-console': 'off',
      'prefer-const': 'error',
    },
  },
];

js.configs.recommended 是官方推荐规则集,开箱就能拦下一大批常见错误。后面那个对象是你想自定义的部分:files 指定作用范围,rules'error' 会直接让检查失败,'warn' 只警告不阻断,'off' 则关闭。

Tip

规则三种档位记牢:'error' 让 lint 命令以非零状态退出(CI 会挂)、'warn' 提示但不阻断、'off' 关闭。本地开发建议把关键项设成 error,格式类交给 Prettier 而非 ESLint 去管。

常用规则举例

  • no-unused-vars:定义了却没用的变量,八成是手误或忘了删。
  • prefer-const:不会被重新赋值的变量应该用 const
  • eqeqeq:强制 === / !==,避免隐式类型转换的坑。
  • no-undef:用了没声明的变量(配合 globals 配置浏览器/Node 全局)。

跑检查:

npx eslint .
# 自动修复能修的问题(比如缩进、引号)
npx eslint . --fix

--fix 能自动修掉绝大多数格式类问题,省得你手动改。

Prettier:格式化交给它

ESLint 偏「找错」,Prettier 偏「排版」。它的哲学是「几乎零配置、不跟你商量」——给你一套合理的默认,你别调了,统一就行。这样团队里再也不会有人为「该不该换行」吵起来。

npm install --save-dev prettier

建一个 .prettierrc

{
  "semi": true,
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 80
}

格式化整个项目:

npx prettier --write .

和 ESLint 怎么不打架

早期 ESLint 自己也有一批格式化规则(比如 quotesindent),会和 Prettier 冲突:ESLint 说要双引号,Prettier 改成单引号,下次 ESLint 又改回来,来回拉锯。解决办法是关掉 ESLint 里所有格式相关的规则,让 Prettier 全权负责排版,ESLint 专心找错。

ESLint 9 可以用官方的 eslint-config-prettier 一键关掉冲突规则:

npm install --save-dev eslint-config-prettier
// eslint.config.js
import js from '@eslint/js';
import prettier from 'eslint-config-prettier';

export default [
  js.configs.recommended,
  prettier, // 放在数组末尾,关掉所有和格式冲突的规则
  {
    files: ['**/*.js'],
    rules: {
      'prefer-const': 'error',
    },
  },
];
Note

分工一句话:Prettier 管「长什么样」,ESLint 管「对不对」。两者配合,代码既整齐又少 bug。如果还想让 ESLint 在保存时自动调用 Prettier 格式化,可以加 eslint-plugin-prettier,但多数编辑器直接配 Prettier 的保存时格式化就够了。

husky:把检查卡在提交前

配置都写好了,但人总会忘。有没有办法「只要一提交代码,就自动跑 lint,不过就别想提交」?有,靠 git 钩子(hook)。husky 是管理 git 钩子的工具,让你不用手写那些藏在 .git/hooks 里的脚本。

npm install --save-dev husky
npx husky init

husky init 会在 package.json 里加个 prepare 脚本,并生成 .husky/ 目录。然后加一个 pre-commit 钩子:

npx husky add .husky/pre-commit "npx lint-staged"

这里引出了 lint-staged:它只对你这次提交改动的那些文件跑 lint 和格式化,而不是全项目扫一遍——大项目全扫太慢,提交时只查改动文件才合理。

npm install --save-dev lint-staged

package.json 里配:

{
  "lint-staged": {
    "*.js": ["eslint --fix", "prettier --write"],
    "*.{js,json,md}": ["prettier --write"]
  }
}

现在你每次 git commit,husky 触发 pre-commitlint-staged 取出暂存区里的 .js 文件,先 eslint --fixprettier --write,都过了才允许提交。哪条 ESLint 规则是 error 且修不了,提交就被挡下来。

Warning

钩子挡提交有时挺烦,尤其是赶时间的时候。但别轻易加 --no-verify 跳过(git commit --no-verify)。这个开关是给「紧急情况临时提交」留的后门,常用它等于把门焊死了,等于没装 husky。真要临时跳过,事后记得补跑 lint。

一个完整的 package.json 片段

把前面提到的串起来,你的 package.json 大致是这样:

{
  "scripts": {
    "lint": "eslint .",
    "format": "prettier --write .",
    "prepare": "husky"
  },
  "devDependencies": {
    "eslint": "^9.0.0",
    "eslint-config-prettier": "^9.0.0",
    "prettier": "^3.0.0",
    "husky": "^9.0.0",
    "lint-staged": "^15.0.0"
  }
}
Tip

第一次搭这套环境,建议按顺序来:先 ESLint 能跑 → 再接 Prettier 关冲突 → 最后上 husky + lint-staged。一步到位容易分不清是哪一层在报错。遇到规则不生效,先确认 eslint.config.js 是 flat config 格式(ESLint 9 默认),老项目的 .eslintrc 在新版本里已经不认了。

编辑器配合

这层工具链最大的价值在「即时反馈」。VS Code 装上 ESLint 和 Prettier 插件后,开启「保存时自动格式化」,你写着写着,格式就刷好了,有错的地方编辑器里直接画红线。等到真去提交时,husky 只是最后一道保险,而不是第一次发现问题的地方。这样开发体验才顺。