文章内容太多,分为上下两部分,这里是下半部分。上半部分在《从零搭建前端工程(上)》,此篇的内容有:
4. 使用 eslint + prettier 让代码健壮和优雅
5. 使用 husky + lint-staged 强制增量各类检查
6. 使用 @commitlint/cli 规范提交信息
7. 使用 埋点(性能 + 错误) 让项目运行更好
四、使用 eslint + prettier 让代码健壮和优雅
到 eslint 了,是不是让人又爱又恨。刚接的时候应该很不爽吧,动辄就来个错,这也错那也错。满屏尽是红 error。其实都是没有配好,也有处理好。eslint 是非常必要的,可以尽早发现一些错误及不合理,也可以统一一些写法,减少冲突等。比如,vue template 的属性顺序,import 的顺序等等。
循例先上代码示例,在项目根目录创建一份 .eslintrc.js
,记得前面有个点的,上书代码:
module.exports = {
env: {
// 关键字指定你想启用的环境
browser: true,
es2021: true,
},
extends: [
// 一个配置文件可以被基础配置中的已启用的规则继承
'plugin:vue/essential',
'plugin:vue/recommended',
'standard',
'plugin:prettier/recommended',
],
parserOptions: {
// 允许你指定你想要支持的 JavaScript 语言选项
ecmaVersion: 12,
sourceType: 'module',
},
plugins: [
// 支持使用第三方插件,检查自定义的语法
'vue', // 省略了 eslint-plugin- 前缀,插件全称为 eslint-plugin-vue
'prettier',
],
rules: {
// 直接声明的 eslint 规则
semi: ['error', 'always'], // 规则为:需要结束分号,优先级为 error,即抛错
// 当最后一个元素或属性与闭括号 ] 或 } 在 不同的行时,要求使用拖尾逗号
// 当在 同一行时,禁止使用拖尾逗号。https://eslint.bootcss.com/docs/rules/comma-dangle
'comma-dangle': ['error', 'always-multiline'],
'no-console': ['error', { allow: ['info', 'warn', 'error'] }],
'no-unused-vars': ['error', { args: 'after-used' }],
// "plugin1/rule1": "error" 配置定义在插件中的一个规则的时候,必须使用 插件名/规则ID 的形式
'prettier/prettier': 'error',
},
globals: {
var1: 'writable', // 对 var1 这个全局变量允许重写
var2: 'readonly', // 对 var2 这个全局变量只允许读取
var3: 'off', // 不支持 var3 这个全局变量
},
};
说一下可能配置较多的。
1、extends
基础一些封装好的规则库,就会引入配置好的规则。比如示例里的 vue 规则,standard 规则。
2、plugins
封装好的规则还不够,对于项目还有特定检测的,自己写插件去拓展,通过对传递来的 ast 对象处理,自己想要什么检测就写什么,灵活又强大。
注意:
有时会遇到 definition for rule ‘xxxx’ was not found 这种报错,可能是相关插件没安装,找不到相应的 rule。检查一下。比如报错:definition for rule 'import/no-unresolved' was not found
,就是 eslint-plugin-import 没使用上,配置上即可。
3、rules
自己的规则只有一两条和引用的规则库不太一样,直接这里配置就行了。有点像 extends 是 class,这个是写行内 style 覆盖样式。
4、globals
前面提到我们会注入一些全局的环境变量。但是这个语法检测不知道啊,所以得告诉它,这是全局对象,合理的。
5、eslint cli 命令
# 问答式新增配置文件
eslint --init
# 检测文件
eslint file1.js file2.js
# 检测文件夹
eslint lib/**
# 检测文件夹里的后缀匹配的文件
eslint --ext .jsx,.js lib/
# 加上会自动修复,一些简单的语法问题。比如单双引号,结尾分号
--fix
另外,可以建一份 .eslintignore 文件来声明不需要检查 lint 的文件。 如果检测命令与 .eslintignore 上的文件有交集,此时会提醒加多个 --no-ignore
参数: File ignored because of a matching ignore pattern. Use “–no-ignore” to override。
6、加上 prettier
prettier 其实是单独的工具,也是对代码美化处理,难免和 eslint 有些重叠。官网的说法是:Prettier vs. Linters。
我的理解吧,就是:eslint 为了代码合理,prettier 为了代码好看。
官网也介绍了如何给 eslint 加上 prettier 的配置。就是给 eslint 配置继承 prettier 的规则库,用上 prettier 的插件,也挺简单。
当然 prettier 也有自己的配置文件,循例项目根目录创建一份 .prettierrc.js
:
module.exports = {
trailingComma: 'es5',
tabWidth: 2,
semi: true,
singleQuote: true,
};
7、prettier cli 命令
# 格式化文件夹
npx prettier --write src
# 只检查不格式化
npx prettier --check src
8、vscode 配置保存自动格式化
进入 vscode 设置,在搜索栏输入关键字 settings
,随便找个 Edit in settings.json
点击进入配置文件,加上配置:
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.formatOnSave": true
}
五、使用 husky + lint-staged 强制增量各类检查
在实际开发中,我们肯定是希望上面说的各种检查是自动,不用每次提醒自己要执行一下,以免不小心提交到仓库。那么,就在提交代码前给它默认做一次检查,而且是增量的,因为对于没有改动到的文件,就没必要再检查了。
1、用 husky 给 git 加上 commit 触发事件
安装并初始化 husky:
npm install --save-dev husky
在 package.json 里添加脚 scripts,"postinstall": "husky install"
。 这样可以在安装完依赖之后,初始化一下 husky。
当然在本项目刚用上 husky 的时候,要主动初始化一下:
npx husky install
然后执行
npx husky add .husky/pre-commit "npm test"
这样就会在项目根目录创建一个 .husky
的文件夹,里面有一份 pre-commit
文件,里面运行着 npm test
的命令。也就是接着把 npm test 改为 lint 操作就行。但是一般我们没有直接这样做,会加以下面的工具打配合。
2、用 lint-staged 对改动文件做检测
我们知道 eslint 或者 prettier 其实是可以指定哪些文件做处理的。用 lint-staged 就可以帮我们做到只针对 git add 的文件进行检查,不需要全量检查。
npm install --save-dev lint-staged
在 package.json 里加上这么个字段:
{
"lint-staged": {
"*.{js,vue}": [
"prettier --write",
"eslint"
]
}
}
然后就有这个功能,执行:git add file1.ext file2.ext
,
就会接着执行: your-cmd(prettier或eslint) file1.ext file2.ext
这样就可以只检测新增的文件,不需要每次都全量。
注意:在上述生成的 pre-commit
钩子里,把默认生成的 npm test
改成 npx lint-staged
。这才是它原本的触发命令,会去获取在 git 暂存区的文件作为处理。
3、针对 monorepo 的处理
如果是 monorepo 这种多子项目的,可以参考官网《how-to-use-lint-staged-in-a-multi-package-monorepo》。就是可以在子项目也就是 packages
的各个目录下,配置各自的检测规则,因为项目可能不一,web 应用或者 node 工具的检测内容都有可能不一样。所以配置各自的是最好的。配置了各子项目的 lint-staged
规则后,好像根路径的设置就没效了。也可以理解,毕竟内容都在 packages 里。
4、针对 typescript 的语法检查
官网《example-run-tsc-on-changes-to-typescript-files-but-do-not-pass-any-filename-arguments》。
typescript 的设定,指定了检测文件就用默认的 tsconfig,指定了自定义的 tsconfig.json,是针对整个项目的,后面跟着指定文件就会报错。所以出了在 package.json 配上 lint-staged 规则。也可以在项目根路径写一份 lint-staged.config.js
:
export default {
'**/*.ts?(x)': (filenames) => [
'tsc -p tsconfig.json --noEmit',
`eslint ${filenames.join(' ')}`, // 注意 join 有空格
],
}
如官网所示,变成自定义函数返回要执行的命令,就可以去除默认带上的文件参数。
其它使用例子请查看官网。
六、使用 @commitlint/cli 规范提交信息
提交信息也是个技术活,和代码风格一样,最好也是有统一格式,这里使用 @commitlint/cli 来约束。
npm install --save-dev @commitlint/config-conventional @commitlint/cli
生成配置,指定规则:
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
接着还是搭配 husky:
npx husky add .husky/commit-msg "npx --no -- commitlint --edit ${1}"
这样就会在项目根目录创建一个 .husky
的文件夹,里面有一份 commit-msg
文件,里面运行着 npx --no -- commitlint --edit ${1}
的命令。根据实际需要,可以自行添加命令行参数。
这里记录下基础的提交类型(网上抄的):
- feat: 修改/增加新功能
- fix: 修改 bug 的变更
- docs: 文档相关变更
- style: 不影响代码含义的变更(空白、格式、缺少符号等)
- refactor: 代码重构变更
- perf: 改进性能的变更
- test: 添加/修改现有的测试
- chore: Build, .gitignore 或辅助工具、库(如文档生成)等变更
七、使用 埋点(性能 + 错误) 让项目运行更好
要想一个项目长治久安,需要我们长期去治理。要让我们的服务问题少,体验好。我们就必须要迅速主动地解决问题,等用户反馈再去修改修复就太慢了,可能人家直接弃坑了。
所以我们需要做一些埋点数据,一般用途有:
1、错误监控
可以在 window.onerror
监听全局错误。或者再觉得可能会出错的地方 try catch
一下,然后上报错误。当然一般这种我们都知道可能会有问题主动去 catch 了,一般也是用来优化流程。减少可能的 catch 事件。这里简单提一下,不展开说了。
2、性能监控
然后就是老生常谈的性能问题啦,收集页面的各项性能数据,然后分析优化,等等。具体指标可以看看这篇文章《前端性能监控》。当然根据实际需求,还会有各式各样的指标,这里就不展开说了。
3、业务监控
然后就是 pv/pu 啊,日活多少啊这种。或者一些场景分析,比如进入一个页面停留多久啊,完成一个功能事项点了多少下啊。这些比较针对性的,一般都是核心场景,定向地分析了模块功能才埋的点。
至于埋点工具,公司如果有封装的话,就用公司的。如果没有的话,错误监控可以看看 Sentry。业务分析可以看看 Google Analytics。一般这种都是成套,要搭配有可配置的可视化界面 Grafana、kibana 之类的,是个大工程,一般都有专人负责这块事项。我们只需要埋好点,然后懂得分析数据进而改进系统就行。
到此大致列了一个项目从无到运行所需要的一些工程化工作。每个点再细化其实还是有不少东西可挖。这些就是具体应用场景再去配置啦。这里记录一下整体框架的活,方便日后再使用。
以下内容请移步《从零搭建前端工程(上)》阅读
1. 使用 webpack 打包(编译)vue
2. 使用 babel 处理 js
3. 使用 webpack-dev-sever 做热调试开发