ESLint 是怎样工作的?husky、lint-staged、commitlint 如何组成提交前检查?

先理解原理和示例,再练习完整口述与追问。

ESLint 用解析器把代码转成 AST,规则在遍历 AST 时订阅节点类型并报告问题,可附带自动修复。ESLint 9 默认使用扁平配置 eslint.config.js。husky 管理 Git 钩子,lint-staged 只检查暂存的文件,commitlint 校验提交信息格式;本地钩子可被绕过,CI 必须再次检查。

默认解析器 espree 生成 ESTree 格式的 AST,TypeScript 需要 typescript-eslint 的解析器,Vue 单文件组件需要 vue-eslint-parser。每条规则导出 create(context),返回 { Identifier(node) {}, CallExpression(node) {} } 这类访问器,发现问题调用 context.report,可提供 fix 函数。Prettier 负责格式,ESLint 负责代码质量,用 eslint-config-prettier 关闭冲突的格式规则。

pre-commit 钩子运行 lint-staged,对暂存文件执行 eslint --fix 与 prettier --write,修复结果会被重新加入暂存区;commit-msg 钩子运行 commitlint,校验 feat(scope): 描述 这类 Conventional Commits 格式,便于自动生成变更日志和语义化版本。

js
export default {
  meta: { type: 'problem', messages: { noConsole: '提交前请移除 console.{{name}}' } },
  create(context) {
    return {
      'CallExpression[callee.object.name="console"]'(node) {
        context.report({ node, messageId: 'noConsole', data: { name: node.callee.property.name } })
      }
    }
  }
}

git commit --no-verify 会跳过本地钩子,所以规范必须在 CI 中强制;对整个仓库执行 lint 会让每次提交都很慢,应只检查变更文件。启用新规则时,存量问题先降级为警告再逐步修复。

ESLint 先用解析器把代码转成 AST,规则通过订阅节点类型在遍历时检查并 report,能提供自动修复,TS 和 Vue 要换对应的解析器,ESLint 9 默认是扁平配置。提交流程上,husky 注册 Git 钩子,pre-commit 中 lint-staged 只对暂存文件跑 ESLint 和 Prettier,commit-msg 中 commitlint 校验提交信息格式。本地钩子可以被 --no-verify 跳过,所以 CI 一定要再检查一次。