前端工程化
前端工程化是前端的一个重要领域,简单的从代码规范开始,复杂的到团队脚手架搭建。在小团队中大多由开发兼任,在大团队中则可能有专门的基建团队负责。可见工程化的普及度是非常高的,只是不同团队的水平或复杂度参差不齐。
工程化对于前端开发是个必备技能。不说要学的多深多厉害,起码能 hold 住一个普通项目。我们先从 Git 的 hooks 学起,这是很多自动化的关键。
Git hooks
以前可能还会时常遇到使用 SVN 管理的代码仓库,而现在已经很少见到了,绝大多数项目应该都使用或切换到 Git 管理了。其中两个最重要的原因就是 Git 的分布式及便捷的分支管理。关于 Git 的使用就不细说了,而 Git hooks 顾名思义就是 Git 提供的一些钩子,我们可以利用其做一些自动化的事情。
Git 提供的钩子可以在仓库的 .git 文件中可以看到,在 .git/hooks
下有这么一些文件
. ├── applypatch-msg.sample ├── commit-msg.sample ├── fsmonitor-watchman.sample ├── post-update.sample ├── pre-applypatch.sample ├── pre-commit.sample ├── pre-merge-commit.sample ├── pre-push.sample ├── pre-rebase.sample ├── pre-receive.sample ├── prepare-commit-msg.sample ├── push-to-checkout.sample └── update.sample 复制代码
他们都是以 .sample 结尾的 bash 文件,其实就是钩子的示例文件了,我们把 .sample 去掉便可让 bash 生效,在特定的时期就会执行这些钩子文件代码,例如 pre-commit 会在我们执行 git commit
的时候执行,如果 pre-commit
的执行结果状态为 0,则 commit
成功,否则 commit
会失败。所以说,通过 Git 提供的各类钩子,我们可以在流程中加入各类校验,或者自动化相关的能力,各种工具包实际也产生于此。
其中最简单常用的应该是 pre-commit
及 commit-msg
钩子了。pre-commit
多用于规范校验、自动修复,commit-msg
多用于 commit message 规范校验、提示。
看到这里,我想大家可以联想到团队项目在使用 Git 命令时候的一些自动化的原理了吧,很酷但原理实际很简单。
husky
上面说了原理很简单,但是操作起来还是有一些需要思考的点的。例如
- .git/hooks 的内容是不会被 push 到远程的,pull 的时候自然也无法同步,那团队间该如何同步呢
- .git 一般在编辑器上默认也是隐藏文件,想要修改其内容需要先设置为显示,修改完再隐藏吗
所以 husky 就来了,其作用在于帮助开发者创建修改 hooks 并同步。husky 在很多文章都有介绍,并且会对比其新旧版本。我们这边仅仅学习下新版本的使用就好了。
新版本的新在于利用了 Git 的新能力,在 .git/config 下可以通过 hooksPath 自定义 hooks 目录
[core] hooksPath = xxx 复制代码
简单介绍下使用
安装
npm install husky --save-dev 复制代码
命令式配置 package.json,作用是以后每次执行完 install 都会执行 husky install
,实际就是自动帮你修改 .git 配置文件,修改 hooks 目录,解决一致性问题
npm set-script prepare "husky install" npm run prepare 复制代码
添加 hooks
npx husky add .husky/pre-commit "npm run lint" 复制代码
这时候在项目根目录下会创建 .husky 目录,好奇的你可以看看 ./git/config 的配置中多了 hooksPath = .husky
我们来看看新建的 ./husky/pre-commit 的内容,实际就是个执行 npm run lint
的 bash。当然,其中是通过 husky.sh 执行的,细节不再展开。
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" npm run lint 复制代码
我们继续配置 lint
,在 package.json 的 script 中添加
{ "lint": "eslint --ext .js src/" } 复制代码
当然安装 eslint 及配置规则必不可少
npm i eslint -D 复制代码
.eslintrc
module.exports = { "env": { "browser": true, "es2021": true }, "extends": "eslint:recommended", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "rules": { "semi": [2, "never"] } } 复制代码
好了,现在每次执行 git commit
都会先执行 npm run lint
,只有通过 eslint 的检查,才能继续填写 commit message
,否则将提交失败。
commitlint
前面了解了常见的 pre-commit 用于配置 lint 的情况。我们再来看看另一常见的钩子 commit-msg
。当执行 git commit
提交时,如果 pre-commit 执行通过,则继续触发 commit-msg。如果自己写 bash 研究如何校验 message 格式会比较麻烦,而 commitlint 正是用于提供统一的校验规则并支持自定义配置。即通过配置的方式来校验 message,避免大家陷入不会 bash 的窘局。
我们看看其使用
安装
npm install @commitlint/cli @commitlint/config-conventional -D 复制代码
生成配置
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js 复制代码
通过 husky 添加 commit-msg
npx husky add .husky/commit-msg "npx commitlint --edit $1" 复制代码
现在再提交 commit 就会验证提交格式了,正确的 message 格式形如
git commit -m 'fix: 修复配置' 复制代码
当然,具体格式是支持自定义配置的,感兴趣可以查看其文档。
lint-staged
上面我们执行 eslint 检查的时候是对整个项目进行检查的,有没有办法对增量代码进行检查呢?在单测领域,增量检查,增量覆盖率是个很常见的需求。
借助 lint-staged
可以做到,lint-staged 仅仅作用于通过 git add
提交到暂存区的文件。
我们来看看其使用
安装
npm install --save-dev lint-staged 复制代码
添加 .lintstagedrc 配置,数组的形式意味着可以添加更多不同的命令,例如单元测试
{ "src/**/*.js": ["npx eslint --fix", "git add"] } 复制代码
顾名思义,对 JS 执行 eslint 检查并自动修复,再执行 git add 添加代码。这边的 git add
只会添加在前面命令中的自动修改的代码,不会提交你原本工作区的修改,实际上是通过 git stash
先缓存了工作区。
总结
本文介绍了 Git hooks 及常见的一些和 hooks 配合使用的 npm 插件 husky、commitlint、lint-staged。提供了自动化校验,提交信息校验的简单思路。