前言
无规矩不成方圆,无规范代码不成体系,遵循代码规范是工程化实践中不可或缺的一部分,它对于提升软项目质量和开发效率有着不可忽视的作用
ESLint代码规范
ESLint是一个用于识别和报告ECMAScript/JavaScript代码中发现的模式的工具,其目标是使代码更加一致并避免错误。
eslint的vscode插件
- 安装后,就会自动检测,这样
我们一边写代码的时候就能直接看到错误,然后就能直接随手改正错误
- vscode在
setting.json
文件配置自动保存
prettier的vscode插件
解析器
@typescript-eslint/parser
: 是专门为TypeScript
语法设计的解析器,能够解析 TypeScript 中的所有语法
扩展代码风格
eslint-config-airbnb
:基于 Airbnb 风格指南的一款规范化的配置文件,目前比较流行的风格eslint-config-airbnb-typescript
:通过TypeScript支持增强Airbnb的ESLint配置eslint-config-prettier
:格式化代码
插件
@typescript-eslint/eslint-plugin
:一个ESLint插件,为TypeScript代码库提供lint规则eslint-import-resolver-typescript
:为eslint插件导入添加了TypeScript支持eslint-plugin-jsx-a11y
:为JSX元素上可访问性规则的静态AST检查器。eslint-plugin-react
:用于React的ESLint规则eslint-plugin-import
:该插件目的在于支持ES6以上的导入/导出语法,并防止文件路径和导入名称拼写错误的问题eslint-plugin-react-hooks
:react hooks编写规范vite-plugin-eslint
:配置eslint自动验证eslint-plugin-prettier
:代码格式化插件eslint-plugin-promise
:promise使用规范
import/order常用规则
builtin
:内置模块,如path
,fs
等 Node.js内置模块。external
:外部模块,如lodash
,react
等第三方库。internal
:内部模块,如相对路径的模块、包名前缀为@
的模块。unknown
:未知模块,如模块名没有指定扩展名或模块路径缺失扩展名。parent
:父级目录的模块。sibling
:同级目录的模块。index
:当前目录的index
文件。object
:使用ES6 导入的模块。type
:使用import type
导入的模块。
"import/order": [
'error',
{
// 对导入模块进行分组
groups: [
'builtin',
'external',
['internal', 'parent', 'sibling', 'index', 'object', 'type'],
'unknown'
],
// 通过路径自定义分组
pathGroups: [
{
// pattern:当前组中模块的最短路径匹配
pattern: '../**', // 在规定的组中选其一,index、sibling、parent、internal、external、builtin、object、type、unknown
group: 'external',
// 定义组的位置,after、before
position: 'after'
}
],
pathGroupsExcludedImportTypes: ['builtin'],
// newlines-between 不同组之间是否进行换行
'newlines-between': 'always',
// alphabetize 根据字母顺序对每个组内的顺序进行排序
// alphabetize: {
// order: 'asc',
// caseInsensitive: true
// }
}
]
.eslintrc.cjs
/*
* @Author: vhen
* @Date: 2024-01-16 02:55:58
* @LastEditTime: 2024-01-18 16:03:29
* @Description: 现在的努力是为了小时候吹过的牛逼!
* @FilePath: \react-vhen-blog-admin\.eslintrc.cjs
*
*/
module.exports = {
// 指定了root为true,eslint只检查当前项目目录
root: true,
// 指定脚本运行的环境,可以是浏览器、Node.js或ES6等。这些环境会提供一组预定义的全局变量
env: { browser: true, es2020: true, node: true },
plugins: ["@typescript-eslint","react","jsx-a11y","react-hooks"],
extends: ['airbnb', 'airbnb-typescript', 'airbnb/hooks', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', 'plugin:storybook/recommended'],
ignorePatterns: ["dist", ".eslintrc.cjs"],
parser: "@typescript-eslint/parser",
parserOptions: {
parser:"@typescript-eslint/parser",
ecmaFeatures: {
jsx: true,
tsx: true
},
ecmaVersion: "latest",
sourceType: "module",
project: ["tsconfig.json", "tsconfig.node.json"],
// project: true,
tsconfigRootDir: __dirname,
},
// 定制化配置,例如React的版本和import配置
settings: {
react: {
version: "detect", // 自动检测React版本
},
},
// 配置规则,规则的格式为:'rule-name': [2, { options: [] }], 0是忽略,1是警告,2是报错
rules: {
"react/function-component-definition": 0,
"react/prop-types": 0,
'react/display-name': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-this-alias': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off',
"react/forbid-prop-types": "off",
"react/jsx-props-no-spreading": 0,
"react/jsx-filename-extension": [1, { extensions: [".tsx", ".jsx"] }],
"react/react-in-jsx-scope": 0, // React17后不需要在jsx中主动引入react
"import/prefer-default-export": 0,
"react-hooks/exhaustive-deps": 1,
"jsx-a11y/no-static-element-interactions": "off", // 关闭非交互元素加事件必须加 role
"jsx-a11y/click-events-have-key-events": "off", // 关闭click事件要求有对应键盘事件
"prettier/prettier": "off",
"import/extensions": 'off', // 关闭m没有后缀的告警
"@typescript-eslint/no-explicit-any":"off",
// eqeqeq: 2, // 必须使用 === 和 !==
// "no-unused-vars": 2, // 禁止出现未使用过的变量
// "no-var": 2, // 要求使用 let 或 const 而不是 var,
// "space-in-parens": 2, // 强制在圆括号内使用一致的空格
'import/no-unresolved': 'off',
'import/extensions': 'off',
'import/no-absolute-path': 'off',
'import/no-extraneous-dependencies': 'off',
"import/order": [
'error',
{
// 对导入模块进行分组
groups: [
'builtin',
'external',
['internal', 'parent', 'sibling', 'index', 'object', 'type'],
'unknown'
],
// 通过路径自定义分组
pathGroups: [
{
// pattern:当前组中模块的最短路径匹配
pattern: '../**', // 在规定的组中选其一,index、sibling、parent、internal、external、builtin、object、type、unknown
group: 'external',
// 定义组的位置,after、before
position: 'after'
}
],
pathGroupsExcludedImportTypes: ['builtin'],
// newlines-between 不同组之间是否进行换行
'newlines-between': 'always',
// alphabetize 根据字母顺序对每个组内的顺序进行排序
// alphabetize: {
// order: 'asc',
// caseInsensitive: true
// }
}
]
},
};
.eslintignore 忽略文件
dist
node_modules
.prettierrc.js
module.exports = {
printWidth: 100, // 换行字符串阈值
singleQuote: true, // 用单引号
trailingComma: "none", // 最后一个对象元素加逗号
proseWrap: "never",
overrides: [{ files: ".prettierrc", options: { parser: "json" } }],
};
.prettierignore 忽略文件
dist
node_modules
添加脚本
在 packjson.json
中 script
字段中添加俩行命令
"lint": "eslint --ext .js,.jsx,.ts,.tsx ./src --fix",
"prettier": "prettier --write "src/**/*.{html,ts,js,json,jsx,tsx}""
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import eslintPlugin from 'vite-plugin-eslint'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
eslintPlugin({
failOnError: false
})
]
})
.editorconfig
editorConfig
文件中的设置用于在代码库中维持一致的编码风格和设置,例如缩进样式、制表符宽度、行尾字符以及编码等,而无需考虑使用的编辑器或 IDE。
# http://editorconfig.org
# 表示是最顶层的配置文件,发现值为true时,才会停止查找.editorconfig文件
root = true
[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = space # 缩进风格(tab | space)
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行
[*.md] # 表示仅 md 文件适用以下规则
max_line_length = off
trim_trailing_whitespace = false
Stylelint
Stylelint 是一个强大、先进的 CSS 代码检查器(linter),可以帮助你规避 CSS 代码中的错误并保持一致的编码风格。
插件
stylelint
:可格式化 css 代码,检查 css 语法错误与不合理的写法,指定 css 书写顺序等stylelint-config-recess-order
:css自动排序stylelint-config-standard
:css样式规范stylelint-scss
:执行各种各样的 SCSS语法特性检测规则postcss-scss
: 执行各种各样的 SCSS语法特性检测规则
npm i -D stylelint stylelint-config-recess-order stylelint-config-standard stylelint-scss postcss-scss
.stylelintrc.js
/*
* @Author: vhen
* @Date: 2024-01-20 01:09:30
* @LastEditTime: 2024-01-20 01:09:53
* @Description: 现在的努力是为了小时候吹过的牛逼!
* @FilePath: \react-vhen-blog-admin\.stylelintrc.js
*
*/
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-recess-order', // 属性排序
'eslint-config-mature/stylelint/style', // 使用 eslint-config-mature 包的规则
'eslint-config-mature/stylelint/style-scss',
],
ignoreFiles: [
'**/*.js',
'**/*.cjs',
'**/*.jsx',
'**/*.tsx',
'**/*.ts',
"node_modules/",
"dist/",
"public/",
"docs/",
],
overrides: [
{
files: ["**/*.scss"],
customSyntax: "postcss-scss", // 处理.scss文件时使用postcss-scss语法解析器
},
],
rules: {
// 自定义覆盖规则
"indentation": "tab",
"number-leading-zero": null
},
};
.stylelintignore忽略文件
node_modules
dist
添加脚本
"lint:stylelint": "stylelint src/**/*.{html,css,scss} --fix --max-warnings 0",
Husky 与 Commitizen
git hooks
客户端钩子
githook | 调用时机 | 说明 |
---|---|---|
pre-commit | 在执行git commit 命令但在生成提交对象之前被触发。常用来检查即将提交的快照,比如运行lint工具检查代码格式 | 如果脚本以非零状态退出,Git会中断提交。 |
prepare-commit-msg | prepare-commit-msg钩子在提交信息编辑器显示之前,提交对象创建完毕之后被触发。常用于给提交信息编辑器提供默认的提交信息,如修复bug时引用bug号等。 | |
commit-msg | commit-msg钩子在提交信息编辑器关闭后、提交对象生成之前被触发。常用于检查提交信息是否符合格式要求 | 如果脚本以非零状态退出,Git将中断提交。 |
post-commi | post-commit钩子在整个提交过程完成后被触发,常用于通知其他工具提交已经完成。 | 此钩子不能影响提交过程的结果。 |
pre-rebase | pre-rebase钩子在git rebase 命令执行前被触发,常用于阻止对已经推送的提交进行rebase操作。 | 如果脚本以非零状态退出,Git将中断rebase。 |
post-checkout | post-checkout钩子在git checkout 或git switch 成功运行后被触发,常用于提醒用户工作目录已经改变。 | |
post-merge | post-merge钩子在git merge 成功运行后被触发,常用于通知用户有文件被合并。 | |
pre-push | pre-push钩子在git push 命令发送数据到远程仓库之前被触发,常用于确保不会推送错误的提交到远程仓库。 | 如果脚本以非零状态退出,Git将中断push。 |
服务器端钩子
githook | 调用时机 | 说明 |
---|---|---|
pre-receive | pre-receive钩子在远程仓库接收到git push 数据并开始更新处理之前被触发,常用于实现权限控制和引用(branch、tag等)的规则检查。 | |
update | update钩子在远程仓库接收到git push 数据,每个引用更新前被触发。与pre-receive类似,常用于实现权限控制和引用的规则检查。 | |
post-receive | post-receive钩子在远程仓库接收到git push 数据并完成所有更新后被触发,常用于触发持续集成、部署等后续任务,或者向外部系统发送有关新提交的通知。 |
husky
- 安装
npm i husky -D
package.json
中添加一个 script:
"prepare": "husky install",
执行 npm run husky
,会创建 .husky
文件夹,此时 git hook 已被启用。
- 安装 lint-staged
在代码提交之前,进行代码规则检查能够确保进入git库的代码都是符合代码规则的。但是整个项目上运行lint速度会很慢,lint-staged
能够让lint只检测暂存区的文件,效率大大提高。
npm i lint-staged -D
在package.json
中加入下面的代码,这样在命令行输入npx lint-staged
就可以进行代码检查和修复了
"lint-staged": {
"*.{vue,js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{css,less,scss,html,md}": [
"prettier --write"
],
"package.json": [
"prettier --write"
]
}
- 加入
pre-commit
的钩子,让它去执行npx lint-staged
指令,完成检查和修复功能。
npx husky add .husky/pre-commit 'npx lint-staged'
commitizen
commitize的作用就是代替git commit ,用来规范git提交说明;
- 安装
npm i -D commitizen cz-conventional-changelog
- 在
package.json
中指定scripts
与config
"commit": "git-cz" // 脚本命令
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
- 执行
npm run commit
自定义中文提交规范,
- 安装
npm i -D cz-customizable
- 在
package.json
中指定config
"config": {
"commitizen": {
"path": "cz-customizable"
},
"cz-customizable": {
"config": ".cz-config.cjs"
}
}
- 在项目根目录中创建
.cz-config.js
文件,如果package.json
中"type": "module"
文件名为.cz-config.cjs
module.exports = {
types: [
{
value: 'feat',
name: '✨ feat: 新功能'
},
{
value: 'fix',
name: '🐛 fix: Bug修复'
},
{
value: 'docs',
name: '📝 docs: 文档新增/变更'
},
{
value: 'style',
name: '🎨 style: 代码风格调整'
},
{
value: 'refactor',
name: '🔨 refactor: 代码重构'
},
{
value: 'perf',
name: '⚡️ perf: 性能提升'
},
{
value: 'test',
name: '🧪 test: 测试用例添加/更正'
},
{
value: 'revert',
name: '⏪ revert: 代码回滚'
},
{
value: 'build',
name: '📦 build: 构建编译过程变更'
},
{
value: 'chore',
name: '🚀 chore: 日常任务维护'
},
{
value: 'ci',
name: '👷 ci: 自动化集成流程'
}
],
usePreparedCommit: false, // to re-use commit from ./.git/COMMIT_EDITMSG
allowTicketNumber: false,
isTicketNumberRequired: false,
ticketNumberPrefix: 'TICKET-',
ticketNumberRegExp: '\\d{1,5}',
// 覆盖消息,默认如下
messages: {
type: '请选择提交类型 (必填)',
scope: '请选择文件修改范围 (可选)',
// 如果allowCustomScopes为true则使用 (官方存在bug, 暂未修复)
customScope: '请输入文件修改范围 (可选)',
subject: '请简要描述提交 (必填)',
body: '请输入详细描述 (可选)',
breaking: '列出任何重大变更 (可选)',
footer: '请输入要关闭的issue (可选)',
confirmCommit: '确定提交此说明吗?'
},
allowCustomScopes: true,
allowBreakingChanges: ['feat', 'fix'],
skipQuestions: ['scope', 'body', 'footer'], // 跳过您想要的任何问题
subjectLimit: 72 // 限制主题长度
}
- 执行
npm run commit
commitlint
commitlint能够在提交 git commit
时提交进行对所填写的描述格式进行规范化校验检查和错误提示处理
- 配置项的格式
# commitlint的规则由名称和`数组`组成,格式为:
"rule-name": [Level,Applicable,Value]
# Level可取值有`0,1,2`:0-禁用 1-警告 2-错误
# Applicable可取值有`always`和`never`:`always` - 应用 `never` - 应用其反面,类似"取反"
# Value:用于此规则的值,可以为`number/string/array`等类型
rule-name
属性:body-full-stop
- condition: 提交的
body
以value
结尾 - rule:
never
默认为never,提交信息不以value值
结尾 - value: 默认值
# 示例 "body-full-stop": [0,'never','.']
- condition: 提交的
body-leading-blank
- condition:
body
以空行开始 - rule:
always
- condition:
body-empty
- condition:
body
是否可为空 - rule:
never
- condition:
body-max-length
- condition:
body
的最大长度 - rule:
always
- value:
Infinity
默认无穷大
- condition:
body-max-line-length
- condition:
body
最大行数 - rule:
always
- value:
Infinity
默认无穷大
- condition:
- body-min-length
- condition:
body
最小长度 - rule:
always
- value:
0
默认为0
- condition:
- body-case
- condition:
body
的格式 - rule:
always
- value:
lower-case
默认是小写格式
[ 'lower-case', // default 'upper-case', // UPPERCASE 'camel-case', // camelCase 'kebab-case', // kebab-case 'pascal-case', // PascalCase 'sentence-case', // Sentence case 'snake-case', // snake_case 'start-case' // Start Case ]
- condition:
- footer-leading-blank
- condition:
footer
是否以空行开始 - rule:
always
- condition:
- footer-empty
- condition:
footer
是否可为空 - rule:
never
- condition:
- footer-max-length
- condition:
footer
最大长度 - rule:
always
- value:
Infinity
默认无穷大
- condition:
- footer-min-length
- condition:
footer
最小长度 - rule:
always
- value:
0
默认为0
- condition:
- header-case
- condition:
header
的格式 - rule:
always
- value:
lower-case
默认小写格式,可用列表同上
- condition:
- header-full-stop
- condition: 提交的
header
以value
结尾 - rule:
never
默认为never,提交信息不以.
结尾 - value: 默认值
.
- condition: 提交的
- header-max-length
- condition:
header
最大长度 - rule:
always
- value:
72
默认72个字符
- condition:
- header-min-length
- condition:
header
最小长度 - rule:
always
- value:
0
默认为0
- condition:
- references-empty
- condition:
references
是否必须有至少一个入口 - rule:
never
- condition:
- scope-enum
- condition: 影响范围
scope
的枚举,提交信息时只能从中选择 - rule:
always
- value:
[]
- condition: 影响范围
- scope-case
- condition:
scope
的格式 - rule:
always
- value:
lower-case
默认小写格式,可用列表同上
- condition:
- scope-empty
- condition:
scope
是否为空 - rule:
never
- condition:
- scope-max-length
- condition:
scope
最大长度 - rule:
always
- value:
Infinity
默认无穷大
- condition:
- scope-min-length
- condition:
scope
最小长度 - rule:
always
- value:
0
默认为0
- condition:
- subject-case
- condition: subject 的格式,默认其中之一:['sentence-case', 'start-case', 'pascal-case', 'upper-case']
- rule: always
- value: 默认[‘sentence-case’, ‘start-case’, ‘pascal-case’, ‘upper-case’],可用列表同上
- subject-empty
- condition:
subject
是否为空 - rule:
never
- condition:
- subject-full-stop
- condition:
subject
结尾符 - rule:
never
- value:
.
- condition:
- subject-max-length
- condition:
subject
最大长度 - rule:
always
- value:
Infinity
默认无穷大
- condition:
- subject-min-length
- condition:
subject
最小长度 - rule:
always
- value:
0
- condition:
- subject-exclamation-mark
- condition:
subject
在:
之前是否需要一个感叹号 - rule:
never
- condition:
- type-enum
- condition:
type
的类型列表 - rule:
always
- value: 默认值
['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'revert']
- condition:
- type-case
- description:
type
的输入格式 - rule:
always
- value:
'lower-case'
,默认为小写,可选列表同上
- description:
- type-empty
- condition:
type
是否可为空 - rule:
never
- condition:
- type-max-length
- condition:
type
最大长度 - rule:
always
- value:
Infinity
默认无穷大
- condition:
- type-min-length
- condition:
type
最小长度 - rule:
always
- value:
0
默认为0
- condition:
- signed-off-by
- condition:
message
是否包含value
- rule:
always
- value: 默认值
'Signed-off-by:'
- condition:
- trailer-exists
- condition:
message
是否有附加信息 - rule:
always
- value:
never
- condition:
- 安装
npm i @commitlint/config-conventional @commitlint/cli -D
- 在项目根目录创建
commitlint.config.js
或者.commitlintrc.js
配置文件
/*
* @Author: vhen
* @Date: 2024-01-20 03:56:05
* @LastEditTime: 2024-01-20 03:56:59
* @Description: 现在的努力是为了小时候吹过的牛逼!
* @FilePath: \react-vhen-blog-admin\commitlint.config.js
*
*/
module.exports = {
// ignores: [commit => commit.includes('init')],
extends: ['@commitlint/config-conventional'],
rules: {
'body-leading-blank': [2, 'always'], // 主体前有空行
'footer-leading-blank': [1, 'always'], // 末行前有空行
'header-max-length': [2, 'always', 108], // 首行最大长度
'subject-empty': [2, 'never'], // 标题不可为空
'scope-case': [0],
'subject-full-stop': [0],
'subject-case': [0],
'type-empty': [2, 'never'], // 类型不可为空
'type-enum': [ // 允许的类型
2,
'always',
[
'feat', // 新增功能
'update', // 更新功能
'ui', // 样式改动
'fix', // 修复功能bug
'merge', // 合并分支
'refactor', // 重构功能
'perf', // 性能优化
'revert', // 回退提交
'style', // 不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等)
'build', // 修改项目构建工具(例如 glup,webpack,rollup 的配置等)的提交
'docs', // 文档新增、改动
'test', // 增加测试、修改测试
'chore', // 不修改src或者test的其余修改,例如构建过程或辅助工具的变动
'release', // 版本发布
'types', // 类型声明
'ci', // 修改项目继续集成流程(Travis,Jenkins,GitLab CI,Circle等)
],
],
},
};
- 使用命令行生成一个
commit-msg
的钩子,运行指定命令,去检查提交的信息是否合法
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
- 执行
git commit -m'test'
,有效的检测出提交内容不符合规则
- 执行
git commit -m'feat: test'
,提交正确格式就通过了
release-it自动化版本管理
release-it
可以进行版本管理,并通过默认提供的配置文件、三方插件和Hooks等功能执行测试、构建、发布等项目内置的任何命令,并进行发布。它可以帮助您自动化执行以下任务:
- 增加版本号并提交
Git
- 生成变更日志(
Changelog
)并提交到Git
- 创建
Git
标签并推送到远程仓库 - 发布到
npm
等软件仓库 - 在
GitHub、GitLab
等平台创建发行版 - 支持使用
Hooks
执行测试或构建等命令 - 支持插件扩展功能
npm install release-it @release-it/conventional-changelog -D
- 在
package.json
添加命令
"scripts": {
"release": "release-it"
},
- 在项目根目录下创建一个名为
.release-it.json
的文件,
{
"plugins": {
"@release-it/conventional-changelog": {
"preset": "angular",
"infile": "CHANGELOG.md"
}
},
"github": {
"release": true
},
"git": {
"commitMessage": "release: v${version}"
},
"npm": {
"publish": false
},
"hooks": {
"after:bump": "echo 更新版本成功"
}
}
- 运行发布命令
npm run release
release-it
会自动执行配置的任务,更新版本号码和变更日志的描述。完成后,它会自动提交代码(Commit
)、打标签(Tag
)、推送(Push
)到仓库等等
注意: 运行
pnpm release
时, 工作目录必须是干净的, 也就是说你需要把修改了的文件提交, 或者使用git stash
放入缓存中, 运行完了, 别忘了在git stash pop
取出来
npm
版本号
major
:主版本,一般代表着Breaking Change,例如 vue 1.x 和vue 2.xminor
:次版本,一般代表着新feature的出现patch
:一般不包含新功能,只是bugfix或和功能关系不大的修改pre-release
:预发布版本,一般用于正式版发行前的验证、联调和测试。和正式版本号之间用 - 连接- alpha
- beta
- rc(release candidate)
github
项目地址:nest_vhen_blog