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

目录

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

这样就配置完成了, 当执行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 许可协议。转载请注明出处!