使用husky + lint-staged助力团队编码规范

写在前面

husky 是一个为 git 客户端增加 hook 的工具。安装后,它会自动在仓库中的 .git/ 目录下增加相应的钩子;比如 pre-commit 钩子就会在你执行 git commit 的触发。

那么我们可以在 pre-commit 中实现一些比如 lint 检查、单元测试、代码美化等操作。当然,pre-commit 阶段执行的命令当然要保证其速度不要太慢,每次 commit 都等很久也不是什么好的体验。

lint-staged,一个仅仅过滤出 Git 代码暂存区文件(被 git add 的文件)的工具;这个很实用,因为我们如果对整个项目的代码做一个检查,可能耗时很长,如果是老项目,要对之前的代码做一个代码规范检查并修改的话,这可能就麻烦了呀,可能导致项目改动很大。

所以这个 lint-staged,对团队项目和开源项目来说,是一个很好的工具,它是对个人要提交的代码的一个规范和约束。

了解 githooks

Git Hooks 就是在 Git 执行特定事件(如commit、push、receive等)时触发运行的脚本,类似于“钩子函数”,没有设置可执行的钩子将被忽略。

在项目的 .git/hooks 目录中,有一些 .sample 结尾的钩子示例脚本,如果想启用对应的钩子,只需手动删除后缀,即可。(删除某一个 hook 的后缀 .sample 即可启用该 hook 脚本,默认是不启用的。)

【但是,我们一般不去改动 .git/hooks 里面的文件,因为我们使用 husky 】

husky

  • husky 的安装
npm i husky -D --registry=https://registry.npm.taobao.org

husky 在安装过程中会在 .git/hooks 文件夹中生成一系列的 git hook 脚本。

需要注意的是:你要留意 husky 的安装信息,是否为你安装了 git 钩子。

如果安装正确的话,可以看到 husky 会打印出如下消息:

> node husky install
husky > setting up git hooks  
husky > done

在这里插入图片描述

但也有可能:
在这里插入图片描述

这个就是由于电脑 node 版本的原因,跳过了 Git 钩子安装,相当于是没有安装成功哦~

OK,假设你的 husky 安装是正常的,那么 husky 为你安装的 hooks 将会生效。这样我们在 git commit 的时候会触发 pre-commit 钩子从而触发到 huksy。

我们在 package.json 文件中配置 husky 的钩子需要执行的 命令 或 操作。

"husky": {
  "hooks": {
    "pre-commit": "echo \"git commit trigger husky pre-commit hook\" "
  }
}

这样,在 git commit 的时候就会看到 pre-commit 执行了。
在这里插入图片描述

从 1.0.0 开始,husky 的配置可以使用 .huskyrc.huskyrc.json.huskyrc.jshusky.config.js 文件

钩子中执行多个命令

  • 根据 npm script 的规则,使用 &&
"husky": {
  "hooks": {
    "pre-commit": "echo \"git commit trigger husky pre-commit hook\" && npm run test"
  }
}
  • 如果您更喜欢使用数组,建议的方法是在 .huskyrc.js 中定义它们
const tasks = arr => arr.join(' && ')

module.exports = {
  'hooks': {
    'pre-commit': tasks([
      'npm run lint',
      'npm run test'
    ])
  }
}

hook 拦截

为了阻止提交,pre-commit 脚本必须以非零的退出代码退出。

如果您的提交未被阻止,请检查脚本退出代码。

当然 husky 不止能验证 commit ,也可以进行 push 等其他操作验证,这里就不一一举例了,具体可以参照 npm husky


lint-staged

lint-staged 是一个在 git 暂存文件上(也就是被 git add 的文件)运行已配置的 linter(或其他)任务。lint-staged 总是将所有暂存文件的列表传递给任务。

// package.json

"lint-staged": {
  "src/**/*.{js,vue}": [
    "prettier --write",
    "eslint --cache --fix",
    "git add"
  ]
}

这里 lint-staged 的配置是:在 git 的待提交的文件中,在 src 目录下的所有 .js .vue 都要执行三条命令。前两条一会儿说,后一条是将处理过的代码重新 add 到 git 中。

结合我们前面介绍的 husky,配合 husky 的 pre-commit 钩子,将会形成一个自动化工具链。

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "src/**/*.{js,vue}": ["prettier --write", "eslint --cache --fix", "git add"]
}

在 commit 之前,将暂存区的内容做一次 代码检查 和 代码美化,然后再添加到暂存区;然后再 commit,完美!!

从 v3.1 开始,您现在可以使用不同的方式进行 lint-staged 配置:

  • lint-staged 在你的对象 package.json
  • .lintstagedrc JSON或YML格式的文件
  • lint-staged.config.js JS格式的文件
  • 使用 --config 或 -c 标志传递配置文件

mrm

mrm 是一个自动化工具。推荐

它将根据 package.json 依赖项中的代码质量工具来安装和配置 husky 和 lint-staged,因此请确保在此之前安装并配置所有代码质量工具,如 Prettier 和 ESlint

安装 mrm 并执行 lint-staged 任务:

npm i mrm -D --registry=https://registry.npm.taobao.org
npx mrm lint-staged

此时,将会自动给你安装相关依赖工具,以及相关配置文件。

mrm 文档、mrm api doc

关于 prettier 的问题

prettier 是一个很好的格式化代码的插件,但对已经有一定迭代完成度的代码不推荐使用。使用该插件后,它会将原有的代码也进行格式化,造成很多不可知的问题,我就是前车之鉴,使用 prettier 后,原本已经没有 eslint 问题的代码,又多出了更多的不知道什么原因的报错,只能将代码回退处理。

所以,这也就是我们为什么在 lint-staged 中,执行 prettier 的原因。

-----------------(正文完)------------------

前端学习交流群,想进来面基的,可以加群:
Vue学习交流 React学习交流
或者手动search群号:685486827832485817


写在最后: 约定优于配置 —— 软件开发的简约原则
-------------------------------- (完)--------------------------------------

我的:
个人网站: https://neveryu.github.io/neveryu/
Github: https://github.com/Neveryu
新浪微博: https://weibo.com/Neveryu

更多学习资源请关注我的新浪微博…

<think>我们有一个明确的目标:在Git提交前,使用huskylint-staged来触发一个自定义脚本,该脚本能够检查代码并删除特定的注释(例如,不希望上传的注释,如调试信息或临时注释)。 步骤概述: 1. 安装必要的包:husky, lint-staged 2. 配置husky:设置pre-commit钩子 3. 配置lint-staged:指定对哪些文件运行自定义脚本 4. 编写自定义脚本:这个脚本将负责检查并删除特定的注释 假设我们想要删除的注释是类似以下格式的: // DEV-ONLY: 这是只在开发中出现的注释,提交前应该被删除 或者可能是一个多行注释,但我们这里以单行为例。 我们可以编写一个Node.js脚本来处理文件,删除包含特定标记的注释行。 具体步骤: 第一步:安装依赖 在项目根目录下执行: pnpm add husky lint-staged -D 第二步:初始化husky npx husky install 第三步:添加pre-commit钩子,这个钩子将运行lint-staged npx husky add .husky/pre-commit "npx lint-staged" 第四步:在package.json中配置lint-staged,让它针对特定文件运行我们的自定义脚本 例如,我们想要对所有.js和.ts文件运行一个名为remove-dev-comments.js的脚本。 第五步:编写自定义脚本(remove-dev-comments.js) 这个脚本的功能: - 读取传递给它的文件(通过命令行参数) - 删除文件中包含特定字符串(例如"DEV-ONLY:")的整行 - 将修改写回文件 注意:这个操作会直接修改源文件,所以请确保在版本控制中,这些修改可以被提交(即这些注释确实是不需要提交的)。 第六步:在package.json中配置lint-staged,指向这个脚本 详细配置如下: 1. 创建自定义脚本文件 在项目根目录下创建脚本文件:scripts/remove-dev-comments.js 脚本内容示例(使用Node.js): ```javascript const fs = require('fs'); const path = require('path'); // 要删除的注释标记 const MARKER = 'DEV-ONLY:'; // 获取命令行参数(lint-staged会传递文件列表) const files = process.argv.slice(2); if (files && files.length) { files.forEach(file => { const filePath = path.resolve(process.cwd(), file); try { let content = fs.readFileSync(filePath, 'utf8'); // 使用正则表达式删除包含标记的行(包括空行处理?这里简单按行分割) const lines = content.split('\n'); const filteredLines = lines.filter(line => !line.includes(MARKER)); const newContent = filteredLines.join('\n'); // 如果内容有变化,则写入文件 if (content !== newContent) { fs.writeFileSync(filePath, newContent, 'utf8'); console.log(`Removed DEV-ONLY comments from: ${file}`); } } catch (err) { console.error(`Error processing file ${file}:`, err); // 如果出错,退出并返回非0,这样lint-staged会知道有错误,提交会终止 process.exit(1); } }); } ``` 2. 配置package.json 在package.json中添加lint-staged配置,例如: ```json { "lint-staged": { "*.{js,ts}": [ "node scripts/remove-dev-comments.js", "eslint --fix", // 如果还需要运行其他检查,比如eslint "prettier --write" ], // 其他文件类型的配置... } } ``` 注意:自定义脚本应该放在lint-staged数组的第一个,因为我们要先删除注释,然后再进行代码格式化和lint检查。 3. 确保脚本可执行(在Unix-like系统中可能需要设置权限,但Node.js脚本通过node运行,一般不需要) 4. 测试 - 在代码中添加一个包含"DEV-ONLY:"的注释行 - 执行git add . 然后 git commit,观察该注释是否被删除,并且其他lint-staged步骤是否正常执行。 注意事项: - 这个脚本会直接修改文件,所以在使用前请确保你的工作已经保存,并且了解风险。 - 如果脚本执行出错(比如文件不存在),我们会捕获错误并退出,这样提交会被终止。 - 可以根据需要调整要删除的注释标记和文件类型。 另外,根据引用[3]和[4]中的经验,配置过程中可能会遇到路径问题或者命令执行问题,请确保脚本路径正确。 如果希望更灵活,也可以考虑使用现成的工具,比如通过sed命令(在Unix-like系统中)来实现,但这里使用Node.js脚本以保证跨平台。 对于Windows用户,如果遇到路径问题,可以使用path模块来解析路径。 根据引用[4],lint-staged的配置中,我们还可以对不同文件类型执行不同的命令。因此,我们只对js和ts文件执行这个删除注释的脚本。 最后,在package.json的scripts中,我们不需要为这个自定义脚本单独添加脚本命令,因为lint-staged会直接调用node运行它。 但是,如果自定义脚本比较复杂,也可以将其封装成一个可执行的npm script,然后在lint-staged中调用这个npm script。不过这里直接使用node命令执行脚本即可。 总结配置步骤: 1. 安装依赖:`pnpm add husky lint-staged -D` 2. 初始化husky:`npx husky install` 3. 添加pre-commit钩子:`npx husky add .husky/pre-commit "npx lint-staged"` 4. 创建自定义脚本文件:`scripts/remove-dev-comments.js`(内容如上) 5. 在package.json中配置lint-staged,添加对js和ts文件执行自定义脚本的命令 6. 测试 注意:如果项目中还没有配置eslint和prettier,那么lint-staged中关于eslint和prettier的命令可能会报错,可以暂时去掉,或者先配置好它们。 这样,在每次提交前,lint-staged都会对暂存区的js和ts文件运行我们的脚本,删除包含特定标记的注释行,然后再进行后续的代码检查和格式化。 相关问题: 1. 如何避免在删除注释时误删其他代码? 2. 除了删除注释,是否还可以在提交前自动替换代码中的其他内容? 3. 如果自定义脚本执行时间较长,如何优化? 4. 如何配置huskylint-staged以支持多项目(monorepo)?</think>### 配置 Husky + Lint-staged 实现提交前自动清理注释 以下是完整配置方案,通过自定义脚本在 Git 提交前自动检测并删除特定注释(如 `// DEV-ONLY:` 等调试注释): --- #### 第一步:安装依赖 ```bash pnpm add husky lint-staged -D ``` #### 第二步:初始化 Husky ```bash npx husky install npx husky add .husky/pre-commit "npx lint-staged" ``` #### 第三步:创建自定义清理脚本 在项目根目录创建 `scripts/clean-comments.js`: ```javascript const fs = require('fs'); const path = require('path'); // 需要删除的注释标记(可自定义) const COMMENT_MARKERS = [ 'DEV-ONLY:', 'DEBUG:', 'TEMPORARY:' ]; const files = process.argv.slice(2); // 获取 lint-staged 传递的文件列表 files.forEach(file => { const filePath = path.resolve(file); let content = fs.readFileSync(filePath, 'utf8'); // 删除单行注释 COMMENT_MARKERS.forEach(marker => { const regex = new RegExp(`//\\s*${marker}.*\\n`, 'g'); content = content.replace(regex, ''); }); // 删除多行注释(可选) // content = content.replace(/\/\* TEMPORARY:[\s\S]*?\*\//g, ''); fs.writeFileSync(filePath, content); console.log(`Cleaned comments in: ${file}`); }); ``` #### 第四步:配置 lint-staged 在 `package.json` 中添加: ```json { "lint-staged": { "*.{js,ts,jsx,tsx,vue}": [ "node scripts/clean-comments.js", // 先执行注释清理 "eslint --fix", // 后续可接其他检查 "prettier --write" ] } } ``` #### 第五步:验证配置 1. 在代码中添加测试注释: ```javascript // DEV-ONLY: 这段代码不应提交 console.log("测试"); ``` 2. 执行提交命令: ```bash git add . git commit -m "测试注释清理功能" ``` 3. 观察控制台输出和文件变更,确认注释已被自动删除 --- ### 关键配置说明 1. **自定义脚本逻辑**: - 通过正则表达式匹配特定注释标记 - 支持单行注释(`// DEV-ONLY:`)和多行注释 - 可扩展标记列表(修改 `COMMENT_MARKERS`) 2. **执行顺序**: ```mermaid graph LR A[git commit] --> B[Husky pre-commit hook] B --> C[lint-staged] C --> D[清理脚本] D --> E[ESLint/Prettier] ``` 3. **安全机制**: - 只处理暂存区文件(`lint-staged` 特性) - 原始文件修改前可通过 `git stash` 备份 - 建议搭配版本控制使用 > 注意:该方案会**直接修改源代码**,建议在 CI 环境添加二次验证[^4] --- ### 常见问题解决 1. **脚本执行权限问题**(Linux/Mac): ```bash chmod +x scripts/clean-comments.js ``` 2. **Windows 路径错误**: 在脚本中使用 `path.resolve()` 处理路径分隔符 3. **恢复误删内容**: ```bash git restore --staged <file> # 取消暂存 git checkout -- <file> # 恢复文件 ``` 4. **性能优化**: 添加文件过滤规则(如忽略 `node_modules`): ```json "lint-staged": { "src/**/*.{js,ts}": [ ... ] } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值