github 代码仓库: https://github.com/lbbbboom/react-code-standardization
环境准备
- Node v20.18.0
- Pnpm v9.12.3
- Vite v6.0.3
- VS Code 插件下载安装
- ESLint
- Stylelint
- Prettier - Code formatter
Vite
vite 版本:6.0.3
使用 Vite 脚手架搭建项目
pnpm create vite react-code-lint --template react-ts
- 根目录下创建
.vscode
文件夹extensions.json
- 用于放vscode扩展插件settings.json
- 用于设置vscode的基本配置(项目配置会覆盖本地)
- 删除
.gitignore
里的.vscode/*
和!.vscode/extensions.json
- 目的:做到同一项目相同配置,保证风格统一
添加.vscode 文件夹内容
extensions.json
在.vscode 文件夹下创建extensions.json 文件,添加以下代码
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"stylelint.vscode-stylelint"
]
}
settings.json
在.vscode 文件夹下创建 settings.json 文件,添加以下代码
{
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit"
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
// 配置stylelint检查的文件类型范围
"stylelint.validate": ["css", "scss", "sass"],
"stylelint.enable": true,
"css.validate": false,
"scss.validate": false,
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
Eslint
版本:9.16.0 ➡️
Tip:v9 版本后使用的 eslint 文件命名为
eslint.config.js
,文件配置项也与之前有所不同
// ...
"scripts": {
// ...
"lint": "eslint .", // 检测eslint
"lint:fix": "eslint . --fix" // 根据eslint规则修复
}
// ...
尝试输入命令:
pnpm lint
检查规则pnpm lint:fix
修复规则
(一)新增排序插件
- 安装依赖
pnpm add eslint-plugin-import eslint-import-resolver-alias -D
eslint-plugin-import:此插件旨在支持 ES2015+ (ES6+) 导入/导出语法的 linting,并防止文件路径和导入名称拼写错误的问题。ES2015+ 静态模块语法旨在提供的所有优点均已在编辑器中标记出来。
- 在
eslint.config.js
文件中写入(eslint-plugin-import)
// ...
rules: {
// ...
"import/order": [
"error",
{
// 对导入模块进行分组,分组排序规则如下
groups: [
"builtin", // 内置模块
"external", // 外部模块
"parent", // 父节点依赖
"sibling", // 兄弟依赖
"internal", // 内部引用
"index", // index文件
"type", //类型文件
"unknown", // 未知依赖
],
//通过路径自定义分组
pathGroups: [
{
pattern: "@/**", // 把@开头的应用放在external分组后面
group: "external",
position: "after", // 定义组的位置,after、before
},
{
pattern: "react*", // 在规定的组中选其一,index、sibling、parent、internal、external、builtin、object、type、unknown
group: "builtin",
position: "before",
},
],
// 是否开启独特组,用于区分自定义规则分组和其他规则分组
distinctGroup: true,
// 每个分组之间换行
"newlines-between": "always",
// 相同分组排列规则 按字母升序排序
alphabetize: { order: "asc",caseInsensitive: true },
},
],
},
eslint-import-resolver-alias:这是一个简单的 Node.js 模块导入解析插件eslint-plugin-import,支持原生 Node.js 模块解析、模块别名/映射和自定义文件扩展名。
- 在
eslint.config.js
文件中写入(eslint-import-resolver-alias)
// ...
settings: {
"import/resolver": {
// eslint-import-resolver-alias 可以解决绝对路径的问题
alias: {
map: [
["", "./public"], // <-- this line
["@", "./src"], // <-- this line
],
extensions: [".js", ".jsx", ".ts", ".tsx", ".svg"],
},
},
},
// ...
Prettier
版本:3.4.2 ➡️
Prettier:是一个代码格式化工具,支持多种编程语言。它可以自动格式化代码,使其符合一致的风格标准
- 安装依赖
pnpm add prettier eslint-config-prettier eslint-plugin-prettier -D
- 添加
.prettierrc.cjs
文件,输入以下代码配置
/** .prettierrc.js
* 在VSCode中安装prettier插件 打开插件配置填写`.prettierrc.js` 将本文件作为其代码格式化规范
* 在本文件中修改格式化规则,不会同时触发改变ESLint代码检查,所以每次修改本文件需要重启VSCode,ESLint检查才能同步代码格式化
* 需要相应的代码格式化规范请自行查阅配置,下面为默认项目配置
*/
module.exports = {
// plugins: ["prettier-plugin-tailwindcss"],
// 一行最多多少个字符
printWidth: 90,
// 指定每个缩进级别的空格数
tabWidth: 2,
// 使用制表符而不是空格缩进行
useTabs: false,
// 在语句末尾是否需要分号
semi: true,
// 是否使用单引号
singleQuote: false,
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
quoteProps: "as-needed",
// 在JSX中使用单引号而不是双引号
jsxSingleQuote: false,
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
trailingComma: "es5",
// 在对象文字中的括号之间打印空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
arrowParens: "always",
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
rangeStart: 0,
rangeEnd: Infinity,
// 指定要使用的解析器,不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准 always\never\preserve
proseWrap: "preserve",
// 指定HTML文件的全局空格敏感度 css\strict\ignore
htmlWhitespaceSensitivity: "css",
// Vue文件脚本和样式标签缩进
vueIndentScriptAndStyle: false,
//在 windows 操作系统中换行符通常是回车 (CR) 加换行分隔符 (LF),也就是回车换行(CRLF),
//然而在 Linux 和 Unix 中只使用简单的换行分隔符 (LF)。
//对应的控制字符为 "\n" (LF) 和 "\r\n"(CRLF)。auto意为保持现有的行尾
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
endOfLine: "auto",
};
Tip:
.prettierrc.cjs
修改了相关格式化配置规则,ESLint代码不会立即去检查报红,Ctrl+Shift+P 打开命令面板,输入Restart Extension Host
重启扩展宿主,等待加载一会儿,就能同步更新了。也可以暴力直接重启打开vscode软件。eslint-config-prettier:这个配置是为了让 ESLint 和 Prettier 更好地协作。它关闭了所有可能与 Prettier 冲突的 ESLint 规则。使用这个配置可以确保 Prettier 的格式化规则优先于 ESLint 的风格规则,从而避免两者之间的冲突。
这个插件将 Prettier 作为一个 ESLint 规则来运行。这样,你可以在 ESLint 的输出中看到 Prettier 的格式化问题。通过这种方式,你可以在使用 ESLint 时同时检查代码的格式化问题,并在开发过程中及时修复。
添加eslint-plugin-prettier 配置
在eslint.config.js
文件下添加以下代码,这样就会将prettier 与 eslint 融合在一起了
import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
export default tseslint.config(
{ ignores: ["dist"] },
{
// ...
}
eslintPluginPrettierRecommended
);
- 这时候使用
eslint
修复的时候会读取prettier
的配置进行修复代码
Stylelint
版本:16.11.0 ➡️
- 安装相关依赖(使用Scss样式预处理器)
pnpm add stylelint stylelint-scss stylelint-config-recommended-scss stylelint-config-standard stylelint-config-standard-scss stylelint-order -D
- stylelint(16.11.0):
Stylelint 是一个强大的现代 CSS 样式检查工具。它可以帮助你检测和修复 CSS、SCSS 和其他样式语言中的错误和不一致。
它提供了丰富的规则集,可以自定义以满足项目的特定需求。- stylelint-scss(6.10.0):
这个插件为 Stylelint 提供了对 SCSS 语法的支持。它增加了许多专门用于 SCSS 的规则,帮助你保持 SCSS 代码的质量和一致性。- stylelint-config-recommended-scss(14.1.0):
这是一个 Stylelint 的配置包,提供了一组推荐的 SCSS 规则。它是一个基础配置,帮助你快速开始使用 Stylelint 检查 SCSS 代码。- stylelint-config-standard(36.0.1):
这个配置包提供了一组标准的 CSS 规则,适用于大多数项目。它帮助你确保 CSS 代码符合行业标准的最佳实践。- stylelint-config-standard-scss(14.0.0):
这是 stylelint-config-standard 的扩展,专门为 SCSS 提供标准规则。它结合了标准 CSS 和 SCSS 的最佳实践。- stylelint-order(6.0.4):
这个插件为 Stylelint 提供了 CSS 属性排序的功能。它允许你定义属性的排序规则,帮助你保持样式代码的可读性和一致性。
- 在根目录新增文件
.stylelintignore
# .stylelintignore
# 旧的不需打包的样式库
*.min.css
# 其他类型文件
*.js
*.jpg
*.png
*.eot
*.ttf
*.woff
*.json
# 测试和打包目录
/test/
/dist/
/node_modules/
/lib/
- 在根目录新增文件
.stylelintrc.cjs
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-standard-scss',
'stylelint-config-recommended-scss',
],
plugins: ['stylelint-scss', 'stylelint-order'],
rules: {
'no-irregular-whitespace': true,
// 指定样式的排序
'order/properties-order': [
[
'content',
'position',
'top',
'right',
'bottom',
'left',
'z-index',
'display',
'vertical-align',
'flex',
'flex-grow',
'flex-shrink',
'flex-basis',
'flex-direction',
'flex-flow',
'flex-wrap',
'grid',
'grid-area',
'grid-template',
'grid-template-areas',
'grid-template-rows',
'grid-template-columns',
'grid-row',
'grid-row-start',
'grid-row-end',
'grid-column',
'grid-column-start',
'grid-column-end',
'grid-auto-rows',
'grid-auto-columns',
'grid-auto-flow',
'grid-gap',
'grid-row-gap',
'grid-column-gap',
'gap',
'row-gap',
'column-gap',
'align-content',
'align-items',
'align-self',
'justify-content',
'justify-items',
'justify-self',
'order',
'float',
'clear',
'object-fit',
'overflow',
'overflow-x',
'overflow-y',
'overflow-scrolling',
'clip',
//
'box-sizing',
'width',
'min-width',
'max-width',
'height',
'min-height',
'max-height',
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'padding',
'padding-top',
'padding-right',
'padding-bottom',
'padding-left',
'border',
'border-spacing',
'border-collapse',
'border-width',
'border-style',
'border-color',
'border-top',
'border-top-width',
'border-top-style',
'border-top-color',
'border-right',
'border-right-width',
'border-right-style',
'border-right-color',
'border-bottom',
'border-bottom-width',
'border-bottom-style',
'border-bottom-color',
'border-left',
'border-left-width',
'border-left-style',
'border-left-color',
'border-radius',
'border-top-left-radius',
'border-top-right-radius',
'border-bottom-right-radius',
'border-bottom-left-radius',
'border-image',
'border-image-source',
'border-image-slice',
'border-image-width',
'border-image-outset',
'border-image-repeat',
'border-top-image',
'border-right-image',
'border-bottom-image',
'border-left-image',
'border-corner-image',
'border-top-left-image',
'border-top-right-image',
'border-bottom-right-image',
'border-bottom-left-image',
//
'background',
'background-color',
'background-image',
'background-attachment',
'background-position',
'background-position-x',
'background-position-y',
'background-clip',
'background-origin',
'background-size',
'background-repeat',
'color',
'box-decoration-break',
'box-shadow',
'outline',
'outline-width',
'outline-style',
'outline-color',
'outline-offset',
'table-layout',
'caption-side',
'empty-cells',
'list-style',
'list-style-position',
'list-style-type',
'list-style-image',
//
'font',
'font-weight',
'font-style',
'font-variant',
'font-size-adjust',
'font-stretch',
'font-size',
'font-family',
'src',
'line-height',
'letter-spacing',
'quotes',
'counter-increment',
'counter-reset',
'-ms-writing-mode',
'text-align',
'text-align-last',
'text-decoration',
'text-emphasis',
'text-emphasis-position',
'text-emphasis-style',
'text-emphasis-color',
'text-indent',
'text-justify',
'text-outline',
'text-transform',
'text-wrap',
'text-overflow',
'text-overflow-ellipsis',
'text-overflow-mode',
'text-shadow',
'white-space',
'word-spacing',
'word-wrap',
'word-break',
'overflow-wrap',
'tab-size',
'hyphens',
'interpolation-mode',
//
'opacity',
'visibility',
'filter',
'resize',
'cursor',
'pointer-events',
'user-select',
//
'unicode-bidi',
'direction',
'columns',
'column-span',
'column-width',
'column-count',
'column-fill',
'column-gap',
'column-rule',
'column-rule-width',
'column-rule-style',
'column-rule-color',
'break-before',
'break-inside',
'break-after',
'page-break-before',
'page-break-inside',
'page-break-after',
'orphans',
'widows',
'zoom',
'max-zoom',
'min-zoom',
'user-zoom',
'orientation',
'fill',
'stroke',
//
'transition',
'transition-delay',
'transition-timing-function',
'transition-duration',
'transition-property',
'transform',
'transform-origin',
'animation',
'animation-name',
'animation-duration',
'animation-play-state',
'animation-timing-function',
'animation-delay',
'animation-iteration-count',
'animation-direction',
'animation-fill-mode',
],
{
unspecified: 'bottom',
severity: 'error',
},
],
},
}
- 打开命令面板重启一下扩展宿主,可以看到
App.css
文件报红 - 添加脚本命令行
// ...
"scripts": {
// ...
"stylelint": "stylelint ./**/*.{css,scss}",
"stylelint:fix": "stylelint ./**/*.{css,scss} --fix",
},
// ...
Husky
版本:9.1.7 ➡️
Husky 是一个用于管理 Git 钩子的工具。它可以帮助你在特定的 Git 操作(如提交、推送等)之前或之后自动运行脚本,从而确保代码质量和一致性
- 安装依赖
pnpm add husky -D
- 在
package.json
添加脚本命令
// ...
"scripts": {
// ...
"prepare": "husky install"
},
// ...
- 生成 husky
pnpm exec husky init
- 更新修改 pre-commit 文件
pnpm run lint:fix && pnpm run stylelint:fix
- 执行 Git 提交命令
git add .
git commit -m 'feat: init'
- 可以看到提交的时候帮我们检查并修复不规范的代码
Commitlint
@commitlint/cli(19.6.0):
Commitlint 是一个用于检查 Git 提交信息的工具。@commitlint/cli 是其命令行接口,允许你在命令行中运行 Commitlint。
@commitlint/config-conventional(19.6.0):
这是 Commitlint 的一个配置包,提供了一组基于 Angular 提交信息规范的规则。
cz-git(1.11.0):
cz-git 是一个交互式的提交信息生成工具,基于 Commitizen 适配器。它提供了一个命令行界面,帮助开发者按照预定义的格式生成提交信息。
czg(1.11.0):
czg 是 cz-git 的一个命令行工具,提供了更友好的用户界面和功能,帮助开发者生成符合规范的提交信息。
- 安装依赖
pnpm add @commitlint/cli @commitlint/config-conventional cz-git czg -D
- 在 package.json 文件中添加
"commitizen": {
"path": "node_modules/cz-git"
}
- 项目根目录添加
commitlint.config.cjs
文件夹
/** @type {import('cz-git').UserConfig} */
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"],
"type-empty": [2, "never"],
"subject-case": [0],
"type-enum": [
2,
"always",
[
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"build",
"ci",
"chore",
"revert",
"wip",
"workflow",
"types",
"release",
],
],
},
prompt: {
messages: {
type: "选择你要提交的类型 :",
scope: "选择一个提交范围[可选]:",
customScope: "请输入自定义的提交范围 :",
subject: "请简要描述提交 :\n",
body: '填写更加详细的变更描述[可选]。使用 "|" 换行 :\n',
breaking: '列举非兼容性重大的变更[可选]。使用 "|" 换行 :\n',
footerPrefixsSelect: "选择关联issue前缀[可选]:",
customFooterPrefixs: "输入自定义issue前缀 :",
footer: "列举关联issue [可选] 例如: #31, #I3244 :\n",
confirmCommit: "是否提交或修改commit ?",
},
types: [
{ value: "feat", name: "feat: ✨ 新增功能", emoji: "✨" },
{ value: "fix", name: "fix: 🐛 修复缺陷", emoji: "🐛" },
{ value: "docs", name: "docs: 📝 文档变更", emoji: "📝" },
{
value: "style",
name: "style: 💄 代码格式",
emoji: "💄",
},
{
value: "refactor",
name: "refactor: 🔨 代码重构",
emoji: "🔨",
},
{ value: "perf", name: "perf: ⚡️ 性能优化", emoji: "⚡️" },
{
value: "test",
name: "test: ✅ 测试",
emoji: "✅",
},
{
value: "build",
name: "build: 📦️ 打包构建",
emoji: "📦️",
},
{ value: "ci", name: "ci: 👷 CI 配置变更", emoji: "👷" },
{ value: "revert", name: "revert: ⏪️ 代码回退", emoji: "⏪️" },
{
value: "chore",
name: "chore: 🚀 构建/工程依赖/工具",
emoji: "🚀",
},
{ value: "wip", name: "wip: 🚧 正在开发中", emoji: "🚧" },
{ value: "workflow", name: "workflow: 🎯 工作流程改进", emoji: "🎯" },
],
useEmoji: true,
scopes: [],
customScopesAlign: "bottom",
emptyScopesAlias: "empty",
customScopesAlias: "custom",
allowBreakingChanges: ["feat", "fix"],
skipQuestions: ["scope", "body", "breaking", "footerPrefix", "footer"], // 自定义选择指定的问题不显示
},
};
package.json
中添加脚本
"scripts": {
// ...
"commit": "czg"
},
- .husky 中新增 commit-msg 文件
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no -- commitlint --edit $1
- 输入命令
pnpm commit
lint-staged
15.2.10
lint-staged 是一个工具,用于在 Git 暂存文件上运行 linters(代码检查工具)。它的主要作用是提高代码质量和开发效率。以下是 lint-staged 的一些关键功能和作用:
- 安装依赖
pnpm add lint-staged -D
- 修改
pre-commit
文件
npx lint-staged
执行
git add .
pnpm commit
- 完成