前端代码工作流
提示
工欲善其事,必先利其器。对于写代码而言,也是需要有一套完善的工作流(工具和流程)。
ESLint
ESLint 是一款插件化的 JavaScript 代码静态检查工具,其核心是通过对代码解析得到的 AST(Abstract Syntax Tree,抽象语法树)进行模式匹配,来分析代码达到检查代码质量和风格问题的能力。
安装
安装并初始化 eslint:
# 全局安装
npm install -g eslint
# cd到项目根目录下
# 强制初始化package.json
npm init -force
# 初始化ESLint
eslint --init
使用方式
写注释
下面这行注释表示在当前文件中禁用 console 关键字
/* eslint no-console: "error" */
写文件
ESLint 支持 eslint.js , eslintrc.yaml , eslintrc.json 类型的配置文件。
如 eslint.js 配置文件:
module.exports = {
env: {
// 环境
browser: true,
es2021: true,
},
extends: [
// 拓展
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
],
parser: "@typescript-eslint/parser", // 解析器,本解析器支持Ts
parserOptions: {
// 解析器配置选项
ecmaVersion: 12, // 指定es版本
sourceType: "module", // 代码支持es6,使用module
},
plugins: [
// 插件
"@typescript-eslint",
],
rules: {
// 规则
},
};
const { defineConfig } = require("eslint-define-config");
module.exports = defineConfig({
root: true,
env: {
browser: true,
node: true,
jest: true,
es6: true,
},
plugins: ["vue"],
parser: "vue-eslint-parser",
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
allowImportExportEverywhere: true,
ecmaFeatures: {
jsx: true,
},
},
extends: [
"airbnb-base",
"eslint:recommended",
"plugin:vue/vue3-essential",
"plugin:vue/vue3-recommended",
"plugin:prettier/recommended",
],
rules: {
// 禁止使用多余的包
"import/no-extraneous-dependencies": 0,
// 确保在导入路径内一致使用文件扩展名
"import/extensions": 0,
// 确保导入指向可以解析的文件/模块
"import/no-unresolved": 0,
// 首选默认导出导入/首选默认导出
"import/prefer-default-export": 0,
// 要求使用 let 或 const 而不是 var
"no-var": "error",
// 禁止使用 new 以避免产生副作用
"no-new": 1,
// 禁止变量声明与外层作用域的变量同名
"no-shadow": 0,
// 禁用 console
"no-console": 0,
// 禁止标识符中有悬空下划线
"no-underscore-dangle": 0,
// 禁止在可能与比较操作符相混淆的地方使用箭头函数
"no-confusing-arrow": 0,
// 禁用一元操作符 ++ 和 --
"no-plusplus": 0,
// 禁止对 function 的参数进行重新赋值
"no-param-reassign": 0,
// 禁用特定的语法
"no-restricted-syntax": 0,
// 禁止在变量定义之前使用它们
"no-use-before-define": 0,
// 禁止直接调用 Object.prototypes 的内置属性
"no-prototype-builtins": 0,
// 禁止可以在有更简单的可替代的表达式时使用三元操作符
"no-unneeded-ternary": "error",
// 禁止重复模块导入
"no-duplicate-imports": "error",
// 禁止在对象中使用不必要的计算属性
"no-useless-computed-key": "error",
// 强制使用一致的缩进
indent: ["error", 2],
// 强制使用骆驼拼写法命名约定
camelcase: 0,
// 强制类方法使用 this
"class-methods-use-this": 0,
// 要求构造函数首字母大写
"new-cap": 0,
// 强制一致地使用 function 声明或表达式
"func-style": 0,
// 强制一行的最大长度
"max-len": 0,
// 要求 return 语句要么总是指定返回的值,要么不指定
"consistent-return": 0,
// 强制switch要有default分支
"default-case": 2,
// 强制剩余和扩展运算符及其表达式之间有空格
"rest-spread-spacing": "error",
// 要求使用 const 声明那些声明后不再被修改的变量
"prefer-const": "error",
// 强制箭头函数的箭头前后使用一致的空格
"arrow-spacing": "error",
},
overrides: [
{
files: ["*.vue"],
rules: {
// 要求组件名称总是多个单词
"vue/multi-word-component-names": 0,
},
},
],
});
配置项
- parser - 解析器
- parserOptions - 解析器选项
- env 和 globals - 环境和全局变量
- rules - 规则
- off 或 0,关闭规则
- warn 或 1,开启规则
- error 或 2,开启规则,并会出错阻止代码运行
- plugins - 插件
- extends - 拓展
配置优先级
规则是使用离要检测的文件最近的 .eslintrc 文件作为最高优先级。
- 行内配置
- 命令行选项
- 项目级配置
- IDE 环境配置
Stylelint
在项目根目录创建 .stylelintrc.js 文件,并填入以下内容:
module.exports = {
root: true,
defaultSeverity: "error",
extends: ["stylelint-config-standard", "stylelint-config-prettier"],
plugins: ["stylelint-order"],
rules: {
// 不允许未知函数
"function-no-unknown": null,
// 指定类选择器的模式
"selector-class-pattern": null,
// 禁止空源码
"no-empty-source": null,
// 指定字符串使用单引号
"string-quotes": "single",
// 禁止未知的@规则
"at-rule-no-unknown": [
true,
{
ignoreAtRules: [
"tailwind",
"apply",
"variants",
"responsive",
"screen",
"function",
"if",
"each",
"include",
"mixin",
],
},
],
// 指定@规则名的大小写
"at-rule-name-case": "lower",
// 指定缩进
indentation: [
2,
{
severity: "warning",
},
],
// 禁止未知的伪类选择器
"selector-pseudo-class-no-unknown": [
true,
{
ignorePseudoClasses: ["global"],
},
],
// 禁止未知的伪元素选择器
"selector-pseudo-element-no-unknown": [
true,
{
ignorePseudoElements: ["v-deep"],
},
],
"order/properties-order": [
"position",
"top",
"right",
"bottom",
"left",
"z-index",
"display",
"justify-content",
"align-items",
"float",
"clear",
"overflow",
"overflow-x",
"overflow-y",
"margin",
"margin-top",
"margin-right",
"margin-bottom",
"margin-left",
"padding",
"padding-top",
"padding-right",
"padding-bottom",
"padding-left",
"width",
"min-width",
"max-width",
"height",
"min-height",
"max-height",
"font-size",
"font-family",
"font-weight",
"border",
"border-style",
"border-width",
"border-color",
"border-top",
"border-top-style",
"border-top-width",
"border-top-color",
"border-right",
"border-right-style",
"border-right-width",
"border-right-color",
"border-bottom",
"border-bottom-style",
"border-bottom-width",
"border-bottom-color",
"border-left",
"border-left-style",
"border-left-width",
"border-left-color",
"border-radius",
"text-align",
"text-justify",
"text-indent",
"text-overflow",
"text-decoration",
"white-space",
"color",
"background",
"background-position",
"background-repeat",
"background-size",
"background-color",
"background-clip",
"opacity",
"filter",
"list-style",
"outline",
"visibility",
"box-shadow",
"text-shadow",
"resize",
"transition",
],
},
};
Prettier
Prettier 是一个代码格式化的工具。
安装使用
npm install --save-dev --save-exact prettier
# 格式化所有文件,npx命令是使用当前项目下的prettier
npx prettier --write .
配置文件
Prettier 支持 .prettierrc 为名称,以 .yaml .yml .json .js 为后缀的的配置文件,当然你也可以使用 package.json 文件中的 Prettier 属性来配置。
module.exports = {
printWidth: 80, //一行的字符数,如果超过会进行换行,默认为80
tabWidth: 2, //一个tab代表几个空格数,默认为80
useTabs: false, //是否使用tab进行缩进,默认为false,表示用空格进行缩减
singleQuote: false, //字符串是否使用单引号,默认为false,使用双引号
semi: true, //行位是否使用分号,默认为true
trailingComma: "none", //是否使用尾逗号,有三个可选值"
};
module.exports = {
// 一行最多 120 字符
printWidth: 120,
// 使用 2 个空格缩进
tabWidth: 2,
// 不使用缩进符,而使用空格
useTabs: false,
// 行尾需要有分号
semi: true,
// 使用单引号
singleQuote: true,
// 对象的 key 仅在必要时用引号
quoteProps: "as-needed",
// jsx 不使用单引号,而使用双引号
jsxSingleQuote: false,
// 末尾需要有逗号
trailingComma: "all",
// 大括号内的首尾需要空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 箭头函数,只有一个参数的时候,也需要括号
arrowParens: "always",
// 每个文件格式化的范围是文件的全部内容
rangeStart: 0,
rangeEnd: Infinity,
// 不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准
proseWrap: "preserve",
// 根据显示样式决定 html 要不要折行
htmlWhitespaceSensitivity: "css",
// vue 文件中的 script 和 style 内不用缩进
vueIndentScriptAndStyle: false,
// 换行符使用 lf
endOfLine: "lf",
// 格式化嵌入的内容
embeddedLanguageFormatting: "auto",
// html, vue, jsx 中每个属性占一行
singleAttributePerLine: false,
};
EditorConfig
EditorConfig 有助于维护跨多个编辑器和 IDE 从事同一项目的多个开发人员的一致编码风格,团队必备神器。
.editorconfig 文件
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file 表示是最顶层的配置文件,发现设为true时,才会停止查找.editorconfig文件
root = true
# Unix-style newlines with a newline ending every file 对于所有的文件 始终在文件末尾插入一个新行
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset 对于所有的js,py文件,设置文件字符集为utf-8
[*.{js,py}]
charset = utf-8
# 4 space indentation 控制py文件类型的缩进大小
[*.py]
indent_style = space
indent_size = 4
# Tab indentation (no size specified) 设置某中文件的缩进风格为tab Makefile未指明
[Makefile]
indent_style = tab
# Indentation override for all JS under lib directory 设置在lib目录下所有JS的缩进为
[lib/**.js]
indent_style = space
indent_size = 2
# Matches the exact files either package.json or .travis.yml 设置确切文件 package.json/.travis/.yml的缩进类型
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
# 表示是最顶层的 EditorConfig 配置文件
root = true
# 表示所有文件适用
[*]
# 缩进风格(tab | space)
indent_style = space
# 控制换行类型(lf | cr | crlf)
end_of_line = lf
# 设置文件字符集为 utf-8
charset = utf-8
# 去除行首的任意空白字符
trim_trailing_whitespace = true
# 始终在文件末尾插入一个新行
insert_final_newline = true
# 表示仅 md 文件适用以下规则
[*.md]
max_line_length = off
trim_trailing_whitespace = false
# 表示仅 ts、js、vue、css 文件适用以下规则
[*.{ts,js,vue,css}]
indent_size = 2
通配符
* 匹配除/之外的任意字符串
** 匹配任意字符串
? 匹配任意单个字符
[name] 匹配name中的任意一个单一字符
[!name] 匹配不存在name中的任意一个单一字符
{s1,s2,s3} 匹配给定的字符串中的任意一个(用逗号分隔)
{num1..num2} 匹配num1到num2之间的任意一个整数, 这里的num1和num2可以为正整数也可以为负整数
属性
indent_style 设置缩进风格(tab是硬缩进,space为软缩进)
indent_size 用一个整数定义的列数来设置缩进的宽度,如果indent_style为tab,则此属性默认为tab_width
tab_width 用一个整数来设置tab缩进的列数。默认是indent_size
end_of_line 设置换行符,值为lf、cr和crlf
charset 设置编码,值为latin1、utf-8、utf-8-bom、utf-16be和utf-16le,不建议使用utf-8-bom
trim_trailing_whitespace 设为true表示会去除换行行首的任意空白字符。
insert_final_newline 设为true表示使文件以一个空白行结尾
root 表示是最顶层的配置文件,发现设为true时,才会停止查找.editorconfig文件
VSCode 集成
我使用的是 VSCode ,来给它添加魔法,加 EditorConfig , Eslint , Prettier , Git 扩展。
配置全局工作区 setting.json 文件,在文件中加入下面配置:
// 设置全部语言在保存时自动格式化
"editor.formatOnSave": ture,
// 设置特定语言在保存时自动格式化
"[javascript]": {
"editor.formatOnSave": true
}
prettier 配置
{
// 设置全部语言的默认格式化程序为prettier
"editor.defaultFormatter": "esbenp.prettier-vscode",
// 设置特定语言的默认格式化程序为prettier
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
ESLint 配置
{
// 保存时自动修复
"editor.codeActionsOnSave": {
// For ESLint
"source.fixAll.eslint": true,
}
}
husky/lint-staged
在提交 git 之前,我们需要校验我们的代码是否符合规范,如果不符合,则不允许提交代码。
安装依赖
npm install -D husky
# lint-staged 可以让husky只检验git工作区的文件,不会导致你一下出现成百上千个错误
npm install -D lint-staged
然后修改 package.json,增加配置
"scripts": {
"precommit": "eslint src/**/*.js"
}
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,vue}": ["prettier --write", "eslint --cache --fix", "git add"]
}
在 git commit 之前会进入 工作区文件的扫描,执行 prettier 脚本,修改 eslint 问题,然后重要提交到工作区。
Commitizen
- 好处:
- 提供更多的历史信息,方便快速浏览
- 可以过滤某些 commit,便于筛选代码 review
- 可以追踪 commit 生成更新日志
- 可以关联 issues
安装
npm install -g commitizen
安装符合 AngularJS 规范的提交说明,初始化 cz-conventional-changelog 适配器:
commitizen init cz-conventional-changelog --save --save-exact
然后使用 git cz 命令 代替 git comit 来提交 git 说明:
git cz
定制化项目提交说明
上面的提交说明都是英文的,如果想自定义,可以试试 cz-customizable,先安装:
npm install cz-customizable --save-dev
修改 package.json 文件:
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
}
}
在项目根目录下创建 .cz.config.js 文件:
"use strict";
module.exports = {
types: [
{ value: "特性", name: "特性: 一个新的特性" },
{ value: "修复", name: "修复: 修复一个Bug" },
{ value: "文档", name: "文档: 变更的只有文档" },
{ value: "格式", name: "格式: 空格, 分号等格式修复" },
{ value: "重构", name: "重构: 代码重构,注意和特性、修复区分开" },
{ value: "性能", name: "性能: 提升性能" },
{ value: "测试", name: "测试: 添加一个测试" },
{ value: "工具", name: "工具: 开发工具变动(构建、脚手架工具等)" },
{ value: "回滚", name: "回滚: 代码回退" },
],
scopes: [
{ name: "模块1" },
{ name: "模块2" },
{ name: "模块3" },
{ name: "模块4" },
],
// it needs to match the value for field type. Eg.: 'fix'
/*
scopeOverrides: {
fix: [
{name: 'merge'},
{name: 'style'},
{name: 'e2eTest'},
{name: 'unitTest'}
]
},
*/
// override the messages, defaults are as follows
messages: {
type: "选择一种你的提交类型:",
scope: "选择一个scope (可选):",
// used if allowCustomScopes is true
customScope: "Denote the SCOPE of this change:",
subject: "短说明:\n",
body: '长说明,使用"|"换行(可选):\n',
breaking: "非兼容性说明 (可选):\n",
footer: "关联关闭的issue,例如:#31, #34(可选):\n",
confirmCommit: "确定提交说明?",
},
allowCustomScopes: true,
allowBreakingChanges: ["特性", "修复"],
// limit subject length
subjectLimit: 100,
};
然后运行
git cz
Commitizen 校验
检验提交的说明是否符合规范,不符合则不可以提交
npm install --save-dev @commitlint/cli
# 安装符合Angular风格的校验规则
npm install --save-dev @commitlint/config-conventional
在根目录下创建 commitlint.config.js 并配置检验:
module.exports = {
extends: ["@commitlint/config-conventional"],
};
然后在 package.json 中配置 husky ,之前我们已经安装过了,直接添加配置:
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
给 commit 加表情
安装:
npm i -g gitmoji-cli
使用: 你可以在这个 gitmoji 网站找到更多的表情来丰富你的提交记录,只需要在提交记录中加上类型 🐛 的代码就可以显示表情了。
如下示例
🎨 (调色板) :art: 改进代码结构/代码格式 ⚡️ (闪电) :zap: 提升性能 🔥 (火焰) :fire: 移除代码或文件 🐛 (bug) :bug: 修复 bug 🚑 (急救车) :ambulance: 重要补丁 ✨ (火花) :sparkles: 引入新功能 📝 (备忘录) :memo: 撰写文档 🚀 (火箭) :rocket: 部署功能 💄 (口红) :lipstick: 更新 UI 和样式文件 🎉 (庆祝) :tada: 初次提交 ✅ (复选框) :white_check_mark: 增加测试 🔒 (锁) :lock: 修复安全问题 🍎 (苹果) :apple: 修复 macOS 下的问题 🐧 (企鹅) :penguin: 修复 Linux 下的问题 🏁 (旗帜) :checkered_flag: 修复 Windows 下的问题 🤖 (机器人) :robot: 修复 Android 下的问题 🍏 (苹果) :green_apple: 修复 IOS下的问题 🔖 (书签) :bookmark: 发行/版本标签 🚨 (警车灯) :rotating_light: 移除 linter 警告 🚧 (施工) :construction: 工作进行中 💚 (绿心) :green_heart: 修复 CI 构建问题 ⬇️ (下降箭头) :arrow_down: 降级依赖 ⬆️ (上升箭头) :arrow_up: 升级依赖 📌 (图钉) :pushpin: 依赖固定到特定版本 👷 (工人) :construction_worker: 添加 CI 构建系统 📈 (上升趋势图) :chart_with_upwards_trend: 添加分析或跟踪代码 ♻️ (回收) :recycle: 重构代码 🐳 (鲸鱼) :whale: Docker 相关工作 🔨 (锤子) :hammer: 重大重构 ➕ (加号) :heavy_plus_sign: 增加一个依赖 ➖ (减号) :heavy_minus_sign: 减少一个依赖 🔧 (扳手) :wrench: 修改配置文件 🌐 (地球) :globe_with_meridians: 国际化与本地化 ✏️ (铅笔) :pencil2: 修复错别字 💩 (粑粑) :poop: 编写需要改进的错误代码 ⏪ (后退) :rewind: 还原更改 🔀 :twisted_rightwards_arrows: Merge 分支 📦 (包裹) :package: 更新编译文件或Package 👽 (外星人) :alien: 由于外部API的更改而更新了代码 🚚 (卡车) :truck: 移动或重命名文件 📄 (文件) :page_facing_up: 添加或更新 Licence 💥 (隆隆声) :boom: 引入重大变化 🍱 (便当) :bento: 添加或更新 Assets 👌(OK) :ok_hand: 由于代码评审更改而更新代码 ♿️ (轮椅) :wheelchair: 提高可访问性 💡 (电灯泡) :bulb: 记录源代码 🍻 (啤酒) :beers: 醉醺醺地编写代码 💬 (发言) :speech_balloon: 更新文本和文字 🗃 (文件盒) :card_file_box: 执行与数据库相关的更改 🔊 (巨大声响) :loud_sound: 添加日志 🔇 (静音) :mute: 移除日志 👥 (轮廓半身像) :busts_in_silhouette: 添加贡献者 🚸 (儿童通过) :children_crossing: 提高用户体验/可用性 🏗 (房屋) :building_construction: 使建筑变化 📱 (苹果手机) :iphone: 致力于响应式设计 🤡 (小丑) :clown_face: Mock 相关 🥚 (彩蛋) :egg: 加入一个复活节彩蛋 🙈 (非礼勿视) :see_no_evil: 添加或更新 .gitignore 文件 📸 (相机) :camera_flash: 添加或更新快照 ⚗️ (蒸馏器) :alembic: 尝试新事物 🔍 (放大镜) :mag: SEO 提升 ☸️ (达摩车轮) :wheel_of_dharma: Kubernetes 相关工作 🏷 (标签) :label: 添加或更新 types (Flow, TypeScript) 🌱 (种子) :seedling: 添加或更新种子文件 🚩 (旗帜) :triangular_flag_on_post: 添加、更新或删除功能标志 💫 (头昏眼花) :dizzy: 添加或更新动画和转换