2023-09-24
前端工程化
00
请注意,本文编写于 240 天前,最后修改于 161 天前,其中某些信息可能已经过时。

目录

glob模式匹配
基本用法
类比正则表达式
.gitignore 扩充的规则
EditorConfig
Prettier
Prettier规则
配置VSCode插件
类比eslint,看看它的功能
Eslint
ESLint 是否可替代 Prettier
ESlint和Pretter的综合案例
Stylelint
StyleLint基本功能
VSCode编辑器配置
融合Prettier
Git Hook背景
husky
commitlint
lint-staged仅校验本次提交
综合案例
VSCode推荐插件

本文系统梳理前端代码规范,包含以下内容

  1. glob语法(它在前端工程化领域用途很广)
  2. prettier格式化工具
  3. stylelint样式检查工具
  4. eslintJS检查工具
  5. prettier + stylelint + eslint 的融合使用及VSCode配置
  6. husky + lint-staged commit前对按需检查,commitlint对注释检查
  7. 一个综合案例, 集成了CICD

glob模式匹配

为什么要说 glob模式匹配 呢,因为本文涉及的代码规范工具如EditorConfigEslintPrettier的配置有它的身影。实际上应该是所有工具只要涉及文件匹配的都是使用它,比如.gitignorewebpack.config.jsgulpfile.jstsconfig.json等。

它与正则表达式用途有本质区别,正则表达式适用更广泛,它只处理文件匹配。因为它的规则更少。

背景:

  1. 它最初是贝尔实验室 Unix 系统上的一个名叫 glob 的命令(globglobal 的缩写),用于展开命令行中的通配符。
  2. 后来系统提供了该功能的 C 语言库函数glob(),知名的 shell 解释器就使用了该接口,shell 脚本和命令行中使用的 glob 模式匹配功能便源自于此。

基本用法

规则 示例 匹配 不匹配
?匹配单个字符
匹配多个字符用多个?
ls ?.txt a.txtb.txt aa.txt.txt
*表示任意数量的字符 ls a*.txt a.txtab.txt b.txtbb.txt
[...]匹配方括号之中的任意一个字符 ls [ab].txt a.txtb.txt c.txt
[start-end]表示一个连续的范围 ls [a-c].txt a.txtb.txtc.txt d.txt
[^...]不在方括号里面的字符
[!...][^...]作用完全一样
ls [^a].txt b.txtc.txt a.txt
ls [^a-c].txt d.txt a.txtb.txtc.txt
{...}表示匹配大括号里面的所有模式,模式之间使用逗号分隔。 echo d{a,e}g dagdeg dog
它可以用于多字符的模式。
echo {cat,dog}
catdog dag
{start..end}会匹配连续范围的字符。 echo d{a..c}g dagdbgdcg ddg
匹配a文件夹下任意txt文件 ls a/*.txt a/b.txta/cc.txt -
深度匹配当前文件夹下任意文件 ls **/* f1/f1.txtf1/f2.txtf2/b.sf2/txtf1/ff/ff1.txt -
{start..end}会匹配连续范围的字符。 echo d{a..c}g dagdbgdcg ddg

更多{...}模式

image.png

更多{start..end}模式

image.png

那么在前端工程化中如何使用glob模式匹配呢?

可使用 node-glob ,它基于 minimatchNode 实现 glob 模式遍历文件的 API。

类比正则表达式

  • glob 模式主要用于匹配文件路径
  • 当然也可以用于匹配字符串,不过在匹配字符串的能力上比 regexp 要弱很多。

image.png

.gitignore 扩充的规则

  • 所有空行或者以 # 开头的行都会被 Git 忽略
  • 匹配模式可以以 / 开头防止递归
  • 匹配模式可以以 / 结尾指定目录
  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号 ! 取反

参考资料:

EditorConfig

官网

  • EditorConfig是用于多人协作使用同编辑器和IDE时,能够保持统一的代码风格
  • 它作用于代码书写和预览阶段
  • 它可以作用于任何文件(通过配置文件制定哪些文件使用哪些规则)
  • 一些重量级工具如webstorm内置了EditorConfig, 一些轻量级工具如VSCodeSubline 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模式匹配
  • 后面介绍的PrettierEslint等工具的配置文件也是 glob模式匹配 ,后续不在强调

Prettier

  • Prettier是一个固执己见的代码格式化工具,固执己见是指它只有少量选择,它内置了一些规则(无需在代码审查中讨论风格,节省您的时间和精力)
  • 它默认支持 js/ts/css/yml/html/md 文件, 其他文件想要支持的话要使用插件
  • 它只关注代码风格, 不关注代码质量(一些低级错误,如使用未定义的变量)问题。
  • 它作用于输入和预览阶段

Prettier规则

看一下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的配置文件有有很多种方式

image.png

关于每个配置项的作用建议前往官网查看(虽然是英文文档,但是有图示一看便懂)

它和EditorConfig有一些功能重叠,但是EditorConfig配置极少, 只要保证endOfLineuseTabstabWidth两者一致即可。

还有一点区别是EditorConfig可以作用域所有类型的文件,Prettier作用的文件类型有限

配置VSCode插件

  1. VSCode中使用Prettier需要安装插件, --略
  2. 配置VSCode支持使用Prettier为格式化

image.png

image.png

这时候会在你的项目文件夹下生成.vscode/settings.json文件

image.png

这样Command + S 保存就可以使用Prettier自动格式化代码了。

默认只是CSS/JS/HTML/TS文件会使用Prettier格式化, 如果是JSX/TSX/vue文件还需要一步额外操作

image.png

image.png

image.png

类比eslint,看看它的功能

-Prettiereslint
功能只关注代码风格关注代码风格和代码质量
作用时机作用于输入和预览阶段关注代码风格和代码质量
CLInpx 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深入浅出》

ESLint 是否可替代 Prettier

由于Eslint功能包含代码风格和代码质量,而Prettier仅关注代码风格,那么 ESLint 是否可替代 Prettier ?

有以下两点无法取代Prettier

  1. ESLint中的Formatting rules并非都提供了fixer
  2. ESLint着重于 JS/TS 无法兼容CSS/Markdown/Html 术业有专攻,代码规范方面得交给Prettier

既然不能替代,那么两者之间怎么解决冲突?

eslint-plugin-prettier插件增加了prettier/prettier规则,该规则执行prettier并将错误信息上报eslint。简言之,把prettier融合到eslint中,担负起代码检查的功能,同时需要配合搭配eslint-config-prettier关闭调ESLint中代码风格相关的规则。

ESlint和Pretter的综合案例

我尝试写了一个支持前端各种类型(JS/CSS/SCSS/HTML/TS/JSX/TSX)的文件编辑器提示和格式化的脚手架Demo

  • .editorconfig配置不变,见前面的模板
  • .prettierrc.json 配置不变,见前面的模版
  • ..eslintrc.js 内容如下
js
module.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', }, }

该配置做了以下事情

  1. 支持了TS/JSX/TSX/Vue格式的文件
  2. Prettier融入Eslint,代码风格交给Prettier处理

有些项目不一定使用Prettier,所以还需要研究了下VSCode中使用Eslint自动格式化, 配置方法与前面Prettier格式化类似

image.png

总结

  1. Eslint只能格式化 JS/TS/JSX/TSX 文件
  2. 其他类型文见CSS/SCSS/HTML/Vue等还是需要使用Prettier进行格式化
  3. VSCode需要安装PrettierESlintVolar插件(Volar是vue3语法的插件)

再次注意: 上述案例有个坑,你会发现使用eslint格式化快捷键,Prettier的规则没有生效。
但是如果使用npx eslint --fixnpx prettier --write格式化同一个文件发现结果一样,说明项目配置没问题。
格式化的文件发现eslint的提示并不对,这说明是 VSCode的ESlint插件问题,翻了很多文档,坑了我几个小时, 终于找到答案, 调整配置如下

image.png

这样就可以愉快的玩耍了(其实还有点小问题,由于CommonJS模块的缓存行, 修改Prettier配置需要重新使用VSCode打开项目,但是规范制定好,只要不去改规范就没不会遇到问题)。

本段落完整代码点这里

Stylelint

stylelint 可以类比 eslintJS中的作用,它不仅管代码风格还管代码质量

先贴出 官网 官方在线demo 以下内容来自官方介绍

它将帮助您避免错误,例如:

  • 无效的东西,例如定义了grid-area的无效值
  • 有疑问的东西,例如重复选择器
  • 有问题的东西,例如属性名称拼写错误

并强制执行约定,例如:

  • 禁止某些规则,例如具体某个单位
  • 强制命名模式,例如对于自定义属性采用短横线kebab-case规范
  • 设定限制,例如ID选择器的数量
  • 指定符号,例如现代色彩函数

我们建议使用像 PrettierStylelintLintersPrettier是互补的工具,它们一起工作可以帮助您编写一致且无错误的代码。

贴一张图解释前面的描述

image.png

StyleLint基本功能

这里先简单总结一下它的功能,有大致的了解。

  1. 配置文件
    配置文件有多种形式,按以下优先级顺序
  • package.json中的stylelint
  • .stylelintrc文件 JSON格式
  • .stylelintrc.{cjs,js,json,yaml,yml} file
  • stylelint.config.{cjs,mjs,js} file
  1. rules规则
json
{ "rules": { "color-no-invalid-hex": true } }

值类型有以下几种

  • null 关闭规则
  • 单个值 主要选项
  • 数组形式 [主要选项, 次要选项]
  • 许多规则提供了用于进一步定制的辅助选项。要设置辅助选项,请使用双成员数组。例如
json
{ "rules": { "selector-pseudo-class-no-unknown": [ true, { "ignorePseudoClasses": ["global"] } ] } }
  1. 命令行使用

前面的案例执行效果如下图 image.png

  1. 特殊处理
  • 默认屏蔽文件 .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; } /* ...... */
  1. 支持手动编程 参考官网 Node.js API

  2. 支持插件、支持PostCSS插件

VSCode编辑器配置

插件安装不用说了,

按照官方文档写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 } }

完整代码点这里

融合Prettier

stylelint从15版本起(目前最新版本15.0.3)废弃了 所有与代码风格(Prettier干的事情)的配置,专注于CSS的代码质量

这里是官方的解释

已弃用的风格规则
我们已经废弃了 76 条强制执行风格约定的规则,例如缩进。

当我们创建这些规则时,Prettier还不存在。他们现在提供了一种更好的方法来一致地格式化代码,尤其是空格。 LintersPrettier是互补的工具,它们一起工作可以帮助您编写一致且无错误的代码。

通过弃用这些规则,我们可以:

  • 专注于编写和维护规则,帮助您避免错误并强制执行(非风格)约定,这两者都是 stylelint 所独有的
  • 使我们的代码库现代化,例如迁移到 ESM,以便我们可以更新依赖项并确保 stylelint 的安全

如果你用的stylelint< 14 可以参考这篇文章的配置。

这里 我写了一个案例 stylelint + scss + prettier

Git Hook背景

首先Git支持 自定义钩子 自定义钩子文档.git/hooks/这个目录下面

image.png 移除sample就可以使用

但实际上并没有这样用的,我推测有以下几点原因

  1. .git文件夹存在于本地,不会提交到远程仓库,你需要写脚本,脚本是使用shell和Perl语言编写,此外shell脚本在window电脑和mac电脑又一些区别。
  2. 如果格式化失败需要恢复之前的代码
  3. 每次commit做全量检查不友好,需要增量检查 (关于脚本示例,参考这

husky

官网

husky 是一个 Git Hook 工具。husky 其实就是一个为 git 客户端增加 hook 的工具。

husky 有一个快捷命令npx husky-init,一键安装并配置pre-commit hook,它会自动完成以下操作

  1. npm pkg set scripts.prepare="husky install"
    • 这里在package.json文件中增加了一个script脚本
  2. npm run prepare
    • prepare是一个钩子,会在npm installnpm publishnpm pack命令前执行 ,详见官网介绍
    • 其他小伙伴在开发前肯定要执行npm install命令, 触发 npm run prepare, 再触发 husky install
    • husky 会设置.hasky/git hooks目录
  3. 为了方便,提供了一个pre-commit的默认脚本

你也可以通过node_modules/husky/README.md查看 husky的使用

commitlint

官网

commitlint 是约束git提交代码时注释的规范。

官方的一张图胜过千言万语 commitlint.svg

使用步骤

  1. 安装依赖 pnpm install --save-dev @commitlint/cli @commitlint/config-conventional
  2. 创建配置文件,写入内容 echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
  3. 使用 npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'

这样就配置完成了, 当执行git commit -m 'XXX'时就会拦截校验你的XXX内容。

如果你提交没有通过, 会提示你怎么写注释, 这里是文档

你还可以自定义规则

lint-staged仅校验本次提交

使用步骤

  1. 安装 pnpm install -D lint-staged
  2. 修改 husky pre-commit 钩子执行脚本
  • .husky/pre-commit
sh
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" npx lint-staged # 校验
  1. 修改 package.json
json
"lint-staged": { "src/**/*.{js,ts,vue}": "npx eslint", "src/**/*.{css,scss,html,vue}": "npx stylelint --allow-empty-input" }

本段落完整代码案例点这里

参考资料

综合案例

我写了一个综合案例 github仓库CICD-demo

  • webpack + ts 开发的脚手架
  • 集成jest单元测试
  • 代码规范方案 prettier + stylelint + eslint
  • VScode编辑器支持 prettier + stylelint + eslint
  • husky + lint-staged 提交前对代码按需进行eslint+stylelint校验,对注释进行校验commitlint
  • CICD集成

我们先从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" ] } }
  1. pre-commit是入口,它是git hooks的钩子,在代码提交前检查代码是否符合规范,不符合规范将不可被提交 这里配置了lint 意思是执行 npm run lint
  2. 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
  3. lint-staged 配置了3条规则
    • 使用prettier对项目中所有后缀为.css.scss.md.html的文件进行格式化
    • 使用jest对项目中所有后缀为.spec.js.spec.ts的文件进行单元测试
      • --bail 执行过程中只要遇到一次错误就退出
      • --passWithNoTests 因为jest默认将没有一个测试用例执行视为错误, 这里告诉jest是正常情况
      • --findRelatedTests 只对有改动的文件进行单元测试

网上也有方案将 eslint格式化配置到 lint-staged里面,这样会遇到一个问题 image.png 所以把eslint放到了外部

VSCode推荐插件

最后推荐一些比较实用的vscode插件

  1. es6-string-html

注: 右边为安装插件后的效果

  1. JavaScript (ES6) code snippets 提供了一些快捷输入的方式比如
  • clg回车 => console.log(object);
  • imp回车 => import moduleName from 'module'
  • edf回车 => export default function test(params) {}
  • 更多请看插件文档
  1. live-server 会本地启动一个服务,选中html文件右击在浏览器打开

  2. Vue Language Features (Volar) vue3语法插件, vue2使用的是Vetur

  3. Compare Folders 文件夹比较

  4. Color Picker 展示颜色

  5. GitLens

本文作者:郭敬文

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!