背景
必要性
代码风格统一很重要,要是没有统一代码风格我们在提交代码的时候,diff会比较多,我们在多人协作的时候,解决的冲突会骤然变大,带来了业务之外的负担。而且当新人进入的时候,不利于了解代码,降低了开发的效率。
- diff 导致的问题会变多,代码风险,不利于查看新提交的内容
- 新人加入需要投入较大的精力来熟悉代码,不利于提高开发效率
如何统一代码风格
使用人工验证工作量太大了,所以我们经常借助工具来完成这类工作,前端主要使用的工具为ESLint、StyleLint,提供了比较全面的配置文件,可以对我们项目的代码风格进行配置。可以有效的提高我们的代码质量和开发效率。
工具枚举
-
VSCode插件:安装编辑器插件,使用插件提高我们的开发效率
- ESLint
- StyleLint
- Prettier
-
VSCode的配置:配置文件,用来存放用户的一些常见配置
- 工作区的
setting.json - 用户区的
setting.json
- 工作区的
-
CSS 格式化
- StyleLint
-
Git流程规范
- Husky
- CommitLint
- Lint-Stage
使用
ESlint
ESLint 是一款插件化的JavaScript代码静态检查工具,核心理念是通过AST树对进行模式匹配,来进行分析和检查代码安全。
脚手架安装
可以在用脚手架创建项目的时候,默认创建选上ESLint,项目创建完成后会在跟路径下默认创建一个.eslintrc.js文件。
手动安装
下载eslint,在项目中进行配置。
npm install eslint --save-dev
对eslint 进行初始化,根据下面的选项选择我们当前的项目的风格。
eslint --init
我们执行过后发现在该路径下生成了一个新的文件:
文件内的内容如下:
// eslint.config.mjs文件
// 导入了 `globals`全局变量的库模块,该模块提供了一组预定义的全局变量(如 window、document 等),这些变量通常在不同的环境(如浏览器、Node.js)中可用。
// 在 ESLint 配置中,你可以使用这个模块来指定代码所运行的环境,从而定义全局变量。
import globals from 'globals'
//针对 JavaScript 的 ESLint 配置和规则。保持 JavaScript 代码的一致性和质量
import pluginJs from '@eslint/js'
// 导入 `eslint-plugin-vue` 插件,提供了 Vue.js 特有 ESLint 规则。确保 Vue 文件(`.vue` 文件)中的代码符合 Vue.js 的最佳实践和代码风格指南
import pluginVue from 'eslint-plugin-vue'
/** @type {import('eslint').Linter.Config[]} */
export default [
// 配置ignore文件,过滤dist的文件
{ ignores: ['**/dist/*'] },
//**文件匹配**:`files` 属性指定了哪些文件类型(JavaScript、Vue 文件等)将应用这些规则
{ files: ['**/*.{js,mjs,cjs,vue}'] },
//1. **全局变量**:`languageOptions` 配置了浏览器环境下的全局变量。
{ languageOptions: { globals: globals.browser } },
// **插件和规则**:
pluginJs.configs.recommended,
// 引入`eslint-plugin-vue` 插件的基础规则
...pluginVue.configs['flat/essential'],
{
rules: {
indent: ['error', 2], // 缩进使用 2 个空格
'linebreak-style': ['error', 'unix'], // 使用 Unix 风格的换行符
quotes: ['error', 'single'], // 使用单引号
semi: ['error', 'never'], // 语句末尾不加分号
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境中警告 console 使用,开发环境中关闭规则
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境中警告 debugger 使用,开发环境中关闭规则
},
},
]
手动配置
相关的依赖包的版本如下:
ps:node 的版本要求较高,我当前只用的node版本为:v20.15.1
对于package.json中配置相关的脚本
"scripts": {
"lint": "eslint ",
"lint:fix": "eslint --fix"
},
prettier
概念
是VSCode的一种插件,它让人又爱又恨,因为他和ESlint 之间是有冲突的,那我们应该如何解决这种冲突呢。
解决冲突
最新版本的eslit和preitter不再是冲突的,所以我们可以使用不用做额外的处理,但是我们可以对我们当下的风格进行定义。
// prettier.config.js
/**
* @type {import('prettier').Config}
* @see https://www.prettier.cn/docs/options.html
*/
export default {
trailingComma: "all",
singleQuote: true,
semi: false,
printWidth: 80,
arrowParens: "always",
proseWrap: "always",
endOfLine: "lf",
experimentalTernaries: false,
tabWidth: 2,
useTabs: false,
quoteProps: "consistent",
jsxSingleQuote: false,
bracketSpacing: true,
bracketSameLine: false,
jsxBracketSameLine: false,
vueIndentScriptAndStyle: false,
singleAttributePerLine: false,
};
同时需要依赖插件进行相关的配置:
// .vscode/settings.json
{
"eslint.validate": [
"javascript",
"vue",
"vue-html",
"typescript",
"typescriptreact",
"html",
"css",
"scss",
"less",
"json",
"jsonc",
"json5",
"markdown"
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
最终配置
// 导入了 `globals`全局变量的库模块,该模块提供了一组预定义的全局变量(如 window、document 等),这些变量通常在不同的环境(如浏览器、Node.js)中可用。
// 在 ESLint 配置中,你可以使用这个模块来指定代码所运行的环境,从而定义全局变量。
import globals from 'globals'
//针对 JavaScript 的 ESLint 配置和规则。保持 JavaScript 代码的一致性和质量
import pluginJs from '@eslint/js'
// 导入 `eslint-plugin-vue` 插件,提供了 Vue.js 特有 ESLint 规则。确保 Vue 文件(`.vue` 文件)中的代码符合 Vue.js 的最佳实践和代码风格指南
import pluginVue from 'eslint-plugin-vue'
// import eslintConfigPrettier from "eslint-plugin-prettier/recommended";
export default [
{ ignores: ['**/dist/*','./eslint.config.mjs','./vue.config.js'] },
//**文件匹配**:`files` 属性指定了哪些文件类型(JavaScript、Vue 文件等)将应用这些规则
{ files: ['**/*.{js,mjs,cjs,vue}'] },
//1. **全局变量**:`languageOptions` 配置了浏览器环境下的全局变量。
{ languageOptions: { globals: { ...globals.browser, ...globals.node } } }, // 解决node 相关的udf报错
// **插件和规则**:
pluginJs.configs.recommended,
// 引入`eslint-plugin-vue` 插件的基础规则
...pluginVue.configs['flat/essential'],
{
rules: {
indent: ['error', 2], // 缩进使用 2 个空格
'vue/multi-word-component-names':'off',
// 'linebreak-style': ['error', 'unix'], // 使用 Unix 风格的换行符
quotes: ['error', 'single'], // 使用单引号
semi: ['error', 'never'], // 语句末尾不加分号
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境中警告 console 使用,开发环境中关闭规则
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境中警告 debugger 使用,开发环境中关闭规则
},
},
]
styleLint
主要针对我们写的一些样式文件,进行统一的格式化,但是当前的项目样式变化比较多,所以经过取舍,不再在项目中引入styleLint,后续有时间再研究这里
git
husky
husky: 用来管理git 的生命周期,commitlint用来管理提交代码相关的规范
npm install -D husky
我们需要初始化一个个husky的文件,执行如下的命令:
npx husky-init
初始化husky 文件,然后我们会生成如下目录:
我们的预期是在提交代码执行一遍eslint,我们进行操作的package.json文件内容如下:
"scripts": {
"lint": "eslint ",
"lint:fix": "eslint --fix"
},
我们在.husky/pre-commit的文件内容如下:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint
Commitlint
Commitlint 检查您的提交消息是否符合 Conventional commit format。-- Commitlint 官网 我们先安装一个相关的依赖,安装的内容如下:
npm install -D @commitlint/cli @commitlint/config-conventional
根目录创建 commitlint.config.cjs 配置文件,我们在配置文件,写入相关的配置:
module.exports = {
// 继承的规则
extends: ["@commitlint/config-conventional"],
// @see: https://commitlint.js.org/#/reference-rules
rules: {
"subject-case": [0], // subject大小写不做校验
// 类型枚举,git提交type必须是以下类型
"type-enum": [
2,
"always",
[
'feat', // 新增功能
'fix', // 修复缺陷
'docs', // 文档变更
'style', // 代码格式(不影响功能,例如空格、分号等格式修正)
'refactor', // 代码重构(不包括 bug 修复、功能新增)
'perf', // 性能优化
'test', // 添加疏漏测试或已有测试改动
'build', // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)
'ci', // 修改 CI 配置、脚本
'revert', // 回滚 commit
'chore', // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
],
],
},
};
添加提交信息校验钩子
执行下面命令生成 commint-msg 钩子用于 git 提交信息校验
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"
文件变成上面的样子:
文件内容如下:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no -- commitlint --edit
Commitizen & cz-git
- commitizen: 基于Node.js的
git commit命令行工具,辅助生成标准化规范化的 commit message。--官方文档 - cz-git: 一款工程性更强,轻量级,高度自定义,标准输出格式的 commitizen 适配器
Commitizen & cz-git 安装
npm install -D commitizen cz-git
修改 package.json 指定使用的适配器
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
},
cz-git 与 commitlint 进行联动给予校验信息,所以可以编写于 commitlint 配置文件之中
module.exports = {
// 继承的规则
extends: ['@commitlint/config-conventional'],
// @see: https://commitlint.js.org/#/reference-rules
rules: {
'subject-case': [0], // subject大小写不做校验
// 类型枚举,git提交type必须是以下类型
'type-enum': [
2,
'always',
[
'feat', // 新增功能
'fix', // 修复缺陷
'docs', // 文档变更
'style', // 代码格式(不影响功能,例如空格、分号等格式修正)
'refactor', // 代码重构(不包括 bug 修复、功能新增)
'perf', // 性能优化
'test', // 添加疏漏测试或已有测试改动
'build', // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)
'ci', // 修改 CI 配置、脚本
'revert', // 回滚 commit
'chore', // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
],
],
},
prompt: {
messages: {
type: '选择你要提交的类型 :',
scope: '选择一个提交范围(可选):',
customScope: '请输入自定义的提交范围 :',
subject: '填写简短精炼的变更描述 :\n',
body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
footerPrefixesSelect: '选择关联issue前缀(可选):',
customFooterPrefix: '输入自定义issue前缀 :',
footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
generatingByAI: '正在通过 AI 生成你的提交简短描述...',
generatedSelectByAI: '选择一个 AI 生成的简短描述:',
confirmCommit: '是否提交或修改commit ?',
},
// prettier-ignore
types: [
{ value: 'feat', name: '特性: ✨ 新增功能', emoji: ':sparkles:' },
{ value: 'fix', name: '修复: 🐛 修复缺陷', emoji: ':bug:' },
{ value: 'docs', name: '文档: 📝 文档变更', emoji: ':memo:' },
{ value: 'style', name: '格式: 💄 代码格式(不影响功能,例如空格、分号等格式修正)', emoji: ':lipstick:' },
{ value: 'refactor', name: '重构: ♻️ 代码重构(不包括 bug 修复、功能新增)', emoji: ':recycle:' },
{ value: 'perf', name: '性能: ⚡️ 性能优化', emoji: ':zap:' },
{ value: 'test', name: '测试: ✅ 添加疏漏测试或已有测试改动', emoji: ':white_check_mark:'},
{ value: 'build', name: '构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)', emoji: ':package:'},
{ value: 'ci', name: '集成: 🎡 修改 CI 配置、脚本', emoji: ':ferris_wheel:'},
{ value: 'revert', name: '回退: ⏪️ 回滚 commit',emoji: ':rewind:'},
{ value: 'chore', name: '其他: 🔨 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)', emoji: ':hammer:'},
],
useEmoji: true,
emojiAlign: 'center',
useAI: false,
aiNumber: 1,
themeColorCode: '',
scopes: [],
allowCustomScopes: true,
allowEmptyScopes: true,
customScopesAlign: 'bottom',
customScopesAlias: 'custom',
emptyScopesAlias: 'empty',
upperCaseSubject: false,
markBreakingChangeMode: false,
allowBreakingChanges: ['feat', 'fix'],
breaklineNumber: 100,
breaklineChar: '|',
skipQuestions: [],
issuePrefixes: [{ value: 'closed', name: 'closed: ISSUES has been processed' }],
customIssuePrefixAlign: 'top',
emptyIssuePrefixAlias: 'skip',
customIssuePrefixAlias: 'custom',
allowCustomIssuePrefix: true,
allowEmptyIssuePrefix: true,
confirmColorize: true,
maxHeaderLength: Infinity,
maxSubjectLength: Infinity,
minSubjectLength: 0,
scopeOverrides: undefined,
defaultBody: '',
defaultIssues: '',
defaultScope: '',
defaultSubject: '',
}
}
添加提交指令
package.json 添加 commit 指令
"scripts": { "commit": "git-cz" }
提交代码的时候我们执行的顺序如下
git add .
npm run commit
我们执行了如下的命令会出现下面的交互,我们按照交互进行执行:
后记
由于elint9版本过高,对于Vue的兼容性还是不是很好,很多问题在社区上没有很好的节点,综上所述,决定将eslint的版本降低到8.57.0,下面详细说一下降低版本后的操作
降低eslint的版本
"eslint": "^8.57.0",
额外安装进行内容的转译
"@babel/eslint-parser": "^7.25.9",
elint 的配置文件修改成.eslintrc.js,文档的内容如下:
module.exports = {
parser: 'vue-eslint-parser',
'env': {
'browser': true,
'es6': true,
'node': true
},
'extends': ['eslint:recommended','plugin:vue/vue3-essential', 'plugin:vue/vue3-essential'],
'parserOptions': {
'ecmaVersion': 2020,
'sourceType': 'module'
},
'rules': {
// 缩进
'indent': [
'error',
2 //我的是编辑器自动格式化,不是使用tabs,而是四个空格
],
// 引号
'quotes': [
1,
'single'
],
'vue/multi-word-component-names':'off',
'no-unused-vars': [2, {
// 允许声明未使用变量
'vars': 'local',
// 参数不检查
'args': 'none'
}],
// 最大空行100
'no-multiple-empty-lines': [0, { 'max': 100 }],
'no-mixed-spaces-and-tabs': [0],
// vue/multi-word-component-names
'no-console': 'off',
//未定义变量不能使用
'no-undef': 0,
//一行结束后面不要有空格
'no-trailing-spaces': 1,
//this别名
'consistent-this': [2, 'that'],
}
};