本文系统梳理前端代码规范,包含以下内容
glob
语法(它在前端工程化领域用途很广)prettier
格式化工具stylelint
样式检查工具eslint
JS检查工具prettier
+ stylelint
+ eslint
的融合使用及VSCode
配置husky
+ lint-staged
commit前对按需检查,commitlint
对注释检查CICD
。为什么要说 glob模式匹配 呢,因为本文涉及的代码规范工具如EditorConfig
、Eslint
、Prettier
的配置有它的身影。实际上应该是所有工具只要涉及文件匹配的都是使用它,比如.gitignore
、webpack.config.js
、 gulpfile.js
、 tsconfig.json
等。
它与正则表达式用途有本质区别,正则表达式适用更广泛,它只处理文件匹配。因为它的规则更少。
背景:
Unix
系统上的一个名叫 glob
的命令(glob
是 global
的缩写),用于展开命令行中的通配符。C
语言库函数glob()
,知名的 shell
解释器就使用了该接口,shell
脚本和命令行中使用的 glob
模式匹配功能便源自于此。规则 | 示例 | 匹配 | 不匹配 |
---|---|---|---|
? 匹配单个字符匹配多个字符用多个 ? |
ls ?.txt |
a.txt 、b.txt |
aa.txt 、.txt |
* 表示任意数量的字符 |
ls a*.txt |
a.txt 、ab.txt |
b.txt 、bb.txt |
[...] 匹配方括号之中的任意一个字符 |
ls [ab].txt |
a.txt 、b.txt |
c.txt |
[start-end] 表示一个连续的范围 |
ls [a-c].txt |
a.txt 、b.txt 、c.txt |
d.txt |
[^...] 不在方括号里面的字符[!...] 与[^...] 作用完全一样 |
ls [^a].txt |
b.txt 、c.txt |
a.txt |
ls [^a-c].txt |
d.txt |
a.txt 、b.txt 、c.txt |
|
{...} 表示匹配大括号里面的所有模式,模式之间使用逗号分隔。 |
echo d{a,e}g |
dag 、deg |
dog |
它可以用于多字符的模式。echo {cat,dog} |
cat 、dog |
dag |
|
{start..end} 会匹配连续范围的字符。 |
echo d{a..c}g |
dag 、dbg dcg |
ddg |
匹配a文件夹下任意txt文件 | ls a/*.txt |
a/b.txt 、a/cc.txt |
- |
深度匹配当前文件夹下任意文件 | ls **/* |
f1/f1.txt 、f1/f2.txt 、f2/b.s 、f2/txt 、f1/ff/ff1.txt |
- |
{start..end} 会匹配连续范围的字符。 |
echo d{a..c}g |
dag 、dbg dcg |
ddg |
更多{...}
模式
更多{start..end}
模式
那么在前端工程化中如何使用glob
模式匹配呢?
可使用 node-glob ,它基于 minimatch 和 Node
实现 glob
模式遍历文件的 API。
glob
模式主要用于匹配文件路径regexp
要弱很多。#
开头的行都会被 Git
忽略/
开头防止递归/
结尾指定目录!
取反参考资料:
EditorConfig
是用于多人协作使用同编辑器和IDE
时,能够保持统一的代码风格webstorm
内置了EditorConfig
, 一些轻量级工具如VSCode
、Subline Text
需要安装插件EditorConfig的匹配非常少,以下是个人推荐的配置示例
ini# 已经是顶层配置文件,不必继续向上搜索
root = true
# 所有文件都必须遵守的规则
[*]
# 编码字符集
charset = utf-8
# 缩进风格是空格
indent_style = space
# 一个缩进占用两个空格,因没有设置tab_with,一个Tab占用2列
indent_size = 2
# 换行符 lf
end_of_line = lf
# 文件以一个空白行结尾
insert_final_newline = true
# 去除行首的任意空白字符
trim_trailing_whitespace = false
# md文件要准守的规则
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
注意
glob
模式匹配Prettier
和 Eslint
等工具的配置文件也是 glob
模式匹配 ,后续不在强调Prettier
是一个固执己见的代码格式化工具,固执己见是指它只有少量选择,它内置了一些规则(无需在代码审查中讨论风格,节省您的时间和精力)js
/ts
/css
/yml
/html
/md
文件, 其他文件想要支持的话要使用插件看一下Prettier
的配置示例
.prettierrc.json
json{
"printWidth": "100",
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"jsxSingleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"arrowParens": "always",
"insertPragma": true,
"proseWrap": "preserve",
"vueIndentScriptAndStyle": false,
"endOfLine": "lf",
"embeddedLanguageFormatting": "auto",
"singleAttributePerLine": false
}
Prettier
的配置文件有有很多种方式
关于每个配置项的作用建议前往官网查看(虽然是英文文档,但是有图示一看便懂)
它和EditorConfig
有一些功能重叠,但是EditorConfig
配置极少, 只要保证endOfLine
、useTabs
、tabWidth
两者一致即可。
还有一点区别是EditorConfig
可以作用域所有类型的文件,Prettier
作用的文件类型有限
VSCode
中使用Prettier
需要安装插件, --略VSCode
支持使用Prettier
为格式化这时候会在你的项目文件夹下生成.vscode/settings.json
文件
这样Command + S
保存就可以使用Prettier
自动格式化代码了。
默认只是CSS
/JS
/HTML
/TS
文件会使用Prettier
格式化, 如果是JSX
/TSX
/vue
文件还需要一步额外操作
eslint
,看看它的功能- | Prettier | eslint |
---|---|---|
功能 | 只关注代码风格 | 关注代码风格和代码质量 |
作用时机 | 作用于输入和预览阶段 | 关注代码风格和代码质量 |
CLI | npx prettier --write . prettier . "!**/*.{js,jsx,vue}" --write | npx eslint --fix . |
配置文件 | 支持JSON /JS 格式 | 支持JSON /JS /YAML 格式 |
API方式使用 | 支持 | 支持 |
忽略文件 | .prettierignore | .eslintignore |
禁止区块 | <!-- prettier-ignore-start --> <!-- prettier-ignore-end --> | /*eslint-disable*/ /*eslint-enable*/ |
禁止单行 | // prettier-ignore <!-- prettier-ignore --> | // eslint disable // eslint-disable-line no-var /* eslint-disable no-var,space-before-function-paren */ |
关于eslint
之前单独写过一篇文章《Eslint深入浅出》
由于Eslint
功能包含代码风格和代码质量,而Prettier
仅关注代码风格,那么 ESLint
是否可替代 Prettier
?
有以下两点无法取代Prettier
ESLint
中的Formatting rules
并非都提供了fixer
ESLint
着重于 JS/TS
无法兼容CSS
/Markdown
/Html
术业有专攻,代码规范方面得交给Prettier
既然不能替代,那么两者之间怎么解决冲突?
eslint-plugin-prettier
插件增加了prettier
/prettier
规则,该规则执行prettier
并将错误信息上报eslint
。简言之,把prettier
融合到eslint
中,担负起代码检查的功能,同时需要配合搭配eslint-config-prettier
关闭调ESLint
中代码风格相关的规则。
我尝试写了一个支持前端各种类型(JS
/CSS
/SCSS
/HTML
/TS
/JSX
/TSX
)的文件编辑器提示和格式化的脚手架Demo
.editorconfig
配置不变,见前面的模板.prettierrc.json
配置不变,见前面的模版..eslintrc.js
内容如下jsmodule.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-essential",
"prettier",
],
overrides: [
{
env: {
node: true,
},
files: [".eslintrc.{js,cjs}"],
parserOptions: {
sourceType: "script",
},
},
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
plugins: ["vue", "prettier"],
rules: {
'prettier/prettier': 'error',
},
}
该配置做了以下事情
TS
/JSX
/TSX
/Vue
格式的文件Prettier
融入Eslint
,代码风格交给Prettier
处理有些项目不一定使用Prettier
,所以还需要研究了下VSCode
中使用Eslint
自动格式化, 配置方法与前面Prettier
格式化类似
总结
Eslint
只能格式化 JS
/TS
/JSX
/TSX
文件CSS
/SCSS
/HTML
/Vue
等还是需要使用Prettier
进行格式化VSCode
需要安装Prettier
、ESlint
、Volar
插件(Volar
是vue3语法的插件)再次注意: 上述案例有个坑,你会发现使用eslint
格式化快捷键,Prettier
的规则没有生效。
但是如果使用npx eslint --fix
和npx prettier --write
格式化同一个文件发现结果一样,说明项目配置没问题。
格式化的文件发现eslint
的提示并不对,这说明是 VSCode的ESlint插件问题,翻了很多文档,坑了我几个小时, 终于找到答案, 调整配置如下
这样就可以愉快的玩耍了(其实还有点小问题,由于CommonJS模块的缓存行, 修改Prettier
配置需要重新使用VSCode
打开项目,但是规范制定好,只要不去改规范就没不会遇到问题)。
stylelint
可以类比 eslint
在JS
中的作用,它不仅管代码风格还管代码质量
它将帮助您避免错误,例如:
- 无效的东西,例如定义了
grid-area
的无效值- 有疑问的东西,例如重复选择器
- 有问题的东西,例如属性名称拼写错误
并强制执行约定,例如:
- 禁止某些规则,例如具体某个单位
- 强制命名模式,例如对于自定义属性采用短横线
kebab-case
规范- 设定限制,例如ID选择器的数量
- 指定符号,例如现代色彩函数
我们建议使用像
Prettier
和Stylelint
。Linters
和Prettier
是互补的工具,它们一起工作可以帮助您编写一致且无错误的代码。
贴一张图解释前面的描述
这里先简单总结一下它的功能,有大致的了解。
package.json
中的stylelint
.stylelintrc
文件 JSON格式.stylelintrc.{cjs,js,json,yaml,yml}
filestylelint.config.{cjs,mjs,js}
filejson{
"rules": {
"color-no-invalid-hex": true
}
}
值类型有以下几种
null
关闭规则[主要选项, 次要选项]
json{
"rules": {
"selector-pseudo-class-no-unknown": [
true,
{
"ignorePseudoClasses": ["global"]
}
]
}
}
npx stylelint "**/*.css"
前面的案例执行效果如下图
.stylelintignore
这里也是glob
语法eslint
非常像css/* stylelint-disable */
区块屏蔽
/* stylelint-enable */
/* stylelint-disable declaration-no-important */
区块屏蔽
/* stylelint-enable declaration-no-important */
#id {
/* stylelint-disable-line */
color: pink !important;
}
/* ...... */
支持手动编程 参考官网 Node.js API
支持插件、支持PostCSS插件
插件安装不用说了,
按照官方文档写demo,但是没有效果, 坑!折腾了会回找到原因
stylelint-wont-mark-errors-in-vscode
这里贴一下我的配置
.vscode/setting.json
json{
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
// 文件保存时开启stylelint自动修复程序
"source.fixAll.stylelint": true
},
// 防止编辑器内置linter与插件冲突设置
"css.validate": false,
"less.validate": false,
"scss.validate": false,
// 启用stylelint插件
"stylelint.enable": true,
"stylelint.config": null,
}
.stylelintrc.json
json{
"extends": [
"stylelint-config-standard"
],
"rules": {
"declaration-empty-line-before": "never",
"unit-allowed-list": [
"em",
"rem"
],
"selector-max-id": 1
}
}
stylelint
从15版本起(目前最新版本15.0.3)废弃了 所有与代码风格(Prettier干的事情)的配置,专注于CSS的代码质量。
已弃用的风格规则
我们已经废弃了 76 条强制执行风格约定的规则,例如缩进。当我们创建这些规则时,
Prettier
还不存在。他们现在提供了一种更好的方法来一致地格式化代码,尤其是空格。Linters
和Prettier
是互补的工具,它们一起工作可以帮助您编写一致且无错误的代码。通过弃用这些规则,我们可以:
- 专注于编写和维护规则,帮助您避免错误并强制执行(非风格)约定,这两者都是
stylelint
所独有的- 使我们的代码库现代化,例如迁移到
ESM
,以便我们可以更新依赖项并确保stylelint
的安全
如果你用的stylelint
< 14 可以参考这篇文章的配置。
这里 我写了一个案例 stylelint
+ scss
+ prettier
首先Git
支持 自定义钩子 自定义钩子文档
在.git/hooks/
这个目录下面
移除sample就可以使用
但实际上并没有这样用的,我推测有以下几点原因
Git Hook
感兴趣,可与读一下这篇文章 《git-pre-commit钩子使用》。commit
做全量检查不友好,需要增量检查 (关于脚本示例,参考这husky
是一个 Git Hook
工具。husky
其实就是一个为 git
客户端增加 hook
的工具。
husky
有一个快捷命令npx husky-init
,一键安装并配置pre-commit hook
,它会自动完成以下操作
npm pkg set scripts.prepare="husky install"
package.json
文件中增加了一个script
脚本npm run prepare
prepare
是一个钩子,会在npm install
、npm publish
、npm pack
命令前执行 ,详见官网介绍npm install
命令, 触发 npm run prepare
, 再触发 husky install
,husky
会设置.hasky/
为git hooks
目录pre-commit
的默认脚本你也可以通过node_modules/husky/README.md
查看 husky
的使用
commitlint 是约束git提交代码时注释的规范。
官方的一张图胜过千言万语
使用步骤
pnpm install --save-dev @commitlint/cli @commitlint/config-conventional
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
这样就配置完成了, 当执行git commit -m 'XXX'
时就会拦截校验你的XXX
内容。
如果你提交没有通过, 会提示你怎么写注释, 这里是文档
你还可以自定义规则
使用步骤
pnpm install -D lint-staged
husky pre-commit
钩子执行脚本.husky/pre-commit
sh#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged # 校验
package.json
json"lint-staged": {
"src/**/*.{js,ts,vue}": "npx eslint",
"src/**/*.{css,scss,html,vue}": "npx stylelint --allow-empty-input"
}
本段落完整代码案例点这里
参考资料
我写了一个综合案例 github仓库CICD-demo
我们先从package.json
梳理流程
json{
"script": {
"lint": "eslint --ext .js,.ts --quiet src --fix && npx lint-staged",
},
"pre-commit": [
"lint"
],
"lint-staged": {
"*.{css,scss,html,md, vue}": [
"prettier --write"
],
"*.{css,scss}": [
"stylelint \"**/*.{css,scss}\""
],
"*.{js,ts}": [
"jest --bail --passWithNoTests --findRelatedTests"
]
}
}
pre-commit
是入口,它是git hooks
的钩子,在代码提交前检查代码是否符合规范,不符合规范将不可被提交 这里配置了lint
意思是执行 npm run lint
npm run lint
找到 pkg.script.lint
对应的命令eslint --ext .js,.ts --quiet src --fix && npx lint-staged
eslint --ext .js,.ts --quiet src --fix
使用eslint
格式化src
文件夹下面所有后缀为.js
、.ts
的文件,
--quiet
仅报告错误,--fix
自动修复, 当然有些错误如运行时错误是无法自动修复的,失败就退出了, 成功继续执行npx lint-staged
会读取配置即pkg.lint-staged
lint-staged
配置了3条规则
prettier
对项目中所有后缀为.css
、.scss
、.md
、.html
的文件进行格式化jest
对项目中所有后缀为.spec.js
、.spec.ts
的文件进行单元测试
--bail
执行过程中只要遇到一次错误就退出--passWithNoTests
因为jest
默认将没有一个测试用例执行视为错误, 这里告诉jest
是正常情况--findRelatedTests
只对有改动的文件进行单元测试网上也有方案将 eslint
格式化配置到 lint-staged
里面,这样会遇到一个问题
所以把eslint
放到了外部
最后推荐一些比较实用的vscode插件
注: 右边为安装插件后的效果
clg
回车 => console.log(object);
imp
回车 => import moduleName from 'module'
edf
回车 => export default function test(params) {}
live-server
会本地启动一个服务,选中html
文件右击在浏览器打开
Vue Language Features (Volar) vue3语法插件, vue2使用的是Vetur
Compare Folders 文件夹比较
Color Picker 展示颜色
GitLens
本文作者:郭敬文
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!