网上有很多教程是有关搭建react项目工程化代码规范的文章,自己跟着敲一遍会出现各种问题,大部分是依赖包版本问题,深受其扰,所以抽空整理出自己总结的一份模板搭建教程
node版本:18.20.0
1.项目初始化
- vite快速搭建react
npm create vite
- 目录结构
- 删除eslint.config.js
2.代码规范
prettier
- vscode安装
- 安装
npm i -D prettier@2.6.2
- 根目录新建文件 .prettierrc.cjs 并复制以下内容
// @see: https://www.prettier.cn
module.exports = {
// 超过最大值换行
printWidth: 130,
// 缩进字节数
tabWidth: 2,
// 使用制表符而不是空格缩进行
useTabs: true,
// 结尾不用分号(true有,false没有)
semi: true,
// 使用单引号(true单双引号,false双引号)
singleQuote: false,
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
quoteProps: 'as-needed',
// 在对象,数组括号与文字之间加空格 "{ foo: bar }"
bracketSpacing: true,
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
trailingComma: 'none',
// 在JSX中使用单引号而不是双引号
jsxSingleQuote: false,
// (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号 ,always:不省略括号
arrowParens: 'avoid',
// 如果文件顶部已经有一个 doclock,这个选项将新建一行注释,并打上@format标记。
insertPragma: false,
// 指定要使用的解析器,不需要写文件开头的 @prettier
requirePragma: false,
// 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
proseWrap: 'preserve',
// 在html中空格是否是敏感的 "css" - 遵守CSS显示属性的默认值, "strict" - 空格被认为是敏感的 ,"ignore" - 空格被认为是不敏感的
htmlWhitespaceSensitivity: 'css',
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
endOfLine: 'auto',
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
rangeStart: 0,
rangeEnd: Infinity,
// Vue文件脚本和样式标签缩进
vueIndentScriptAndStyle: false
}
- 为了不让本地的配置文件影响prettier和eslint,在根目录下新建 .vscode 文件夹,并且创建settings.json,复制内容
{
"search.exclude": {
"/node_modules": true,
"dist": true,
"pnpm-lock.sh": true
},
"editor.formatOnSave": true,
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
}
- 现在一保存代码就自动格式化
- 根目录新建文件 .prettierignore 忽略格式化的文件,一般内容是
/dist/*
.local
/node_modules/**
**/*.svg
**/*.sh
/public/*
eslint
eslint是用来检查代码中的语法错误、代码风格问题以及可能的逻辑错误。
- vscode安装
- 安装
npm i eslint@8.17.0 -D
- 安装插件
npm i @typescript-eslint/eslint-plugin@8.15.0 @typescript-eslint/parser@8.15.0 -D
- 根目录新建 .eslintrc.js 复制内容
module.exports = {
root: true, // 指定这是根配置文件,用于定义javascript或者Typescript项目中的代码质量和风格的规则。
env: { browser: true, es2020: true, node: true }, // 指定代码的运行环境
extends: [
// 这里是越靠后的插件配置优先级越高
"eslint:recommended", // eslint默认规则
"plugin:@typescript-eslint/recommended", // Typescript推荐规范
"plugin:react-hooks/recommended", // React Hooks推荐规范
],
ignorePatterns: ["dist", ".eslintrc.cjs"], // 忽略文件
parser: "@typescript-eslint/parser", // 指定的解析器
plugins: ["react-refresh"], // 支持React的热刷新
rules: {
"no-var": "error", // 要求使用 let 或 const 而不是 var
"no-multiple-empty-lines": ["error", { max: 1 }], // 不允许多个空行
"no-use-before-define": "off", // 禁止在 函数/类/变量 定义之前使用它们
"prefer-const": "off", // 此规则旨在标记使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const
"no-irregular-whitespace": "off", // 禁止不规则的空白
// typeScript (https://typescript-eslint.io/rules)
"@typescript-eslint/no-unused-vars": "error", // 禁止定义未使用的变量
"@typescript-eslint/no-inferrable-types": "off", // 可以轻松推断的显式类型可能会增加不必要的冗长
"@typescript-eslint/no-namespace": "off", // 禁止使用自定义 TypeScript 模块和命名空间。
"@typescript-eslint/no-explicit-any": "off", // 禁止使用 any 类型
"@typescript-eslint/ban-ts-ignore": "off", // 禁止使用 @ts-ignore
"@typescript-eslint/ban-types": "off", // 禁止使用特定类型
"@typescript-eslint/explicit-function-return-type": "off", // 不允许对初始化为数字、字符串或布尔值的变量或参数进行显式类型声明
"@typescript-eslint/no-var-requires": "off", // 不允许在 import 语句中使用 require 语句
"@typescript-eslint/no-empty-function": "off", // 禁止空函数
"@typescript-eslint/no-use-before-define": "off", // 禁止在变量定义之前使用它们
"@typescript-eslint/ban-ts-comment": "off", // 禁止 @ts-<directive> 使用注释或要求在指令后进行描述
"@typescript-eslint/no-non-null-assertion": "off", // 不允许使用后缀运算符的非空断言(!)
"@typescript-eslint/explicit-module-boundary-types": "off", // 要求导出函数和类的公共类方法的显式返回和参数类型
// react (https://github.com/jsx-eslint/eslint-plugin-react)
"react-hooks/rules-of-hooks": "off",
"react-hooks/exhaustive-deps": "off"
}
};
- 新建.eslintignore 忽略文件
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
.eslintrc.js
.prettierrc.cjs
/src/mock/*
发现eslint并没有生效,直接重启vscode后会生效,后面如果有遇到插件没有生效问题,可以重启vscode试试
- 验证下
- 保存自动修复错误,需要在./vscode/settings.json增加内容
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
},
- 验证保存,不规范代码自动修复
- 解决eslint和prettier冲突
eslint既负责了代码质量检测,又负责了一部分的格式美化工作,格式化部分的部分规则和prettier不兼容,所以让eslint只负责代码质量检测而让prettier负责美化,要用上 eslint-config-prettier + eslint-plugin-prettier。
- eslint-config-prettier 的作用是关闭eslint中与prettier相互冲突的规则。
- eslint-plugin-prettier 的作用是赋予eslint用prettier格式化代码的能力。 安装依赖并修改.eslintrc文件
- 安装
npm i eslint-config-prettier@8.5.0 eslint-plugin-prettier@4.0.0 -D
- .eslintrc.js 添加
extends: [
// 这里是越靠后的插件配置优先级越高
"eslint:recommended", // eslint默认规则
"plugin:@typescript-eslint/recommended", // Typescript推荐规范
"plugin:react-hooks/recommended", // React Hooks推荐规范
"plugin:prettier/recommended" // 集成Prettier插件规范
],
stylelint
- vscode安装插件
- 安装
- stylelint:styleLint 的核心模块
- stylelint-config-standard:styleLint 官方推荐的配置规则
- stylelint-config-prettier:该配置用于解决 StyleLint 和 Prettier 之间的规则冲突问题
npm i stylelint@14.9.1 stylelint-config-standard@26.0.0 stylelint-config-prettier@9.0.5 -D
- 根目录新建 .stylelintrc.js .stylelintignore
//.stylelintrc.js
module.exports = {
// 从标准配置中继承规则
extends: ["stylelint-config-standard", "stylelint-config-prettier"],
// 规则配置
rules: {
// 禁用注释前的空行规则
"comment-empty-line-before": null,
// 禁用声明前的空行规则
"declaration-empty-line-before": null,
// 指定函数名的大小写为小写
"function-name-case": "lower",
// 禁用选择器特异性递减规则
"no-descending-specificity": null,
// 禁用无效的双斜杠注释规则
"no-invalid-double-slash-comments": null,
// 指定规则前需要空行
"rule-empty-line-before": "never"
},
// 忽略检查的文件或文件夹
ignoreFiles: ["node_modules/**/*", "build/**/*"]
};
//.stylelintignore
/dist/*
/public/*
public/*
- 规范css书写顺序
stylelint-order该插件的作用是强制你按照某个顺序编写 css。例如先写定位,再写盒模型,再写内容区样式,最后写 CSS3 相关属性。这样可以极大的保证我们代码的可读性。stylelint-config-rational-order一套常见的css书写顺序
npm i stylelint-order@6.0.4 stylelint-config-rational-order@0.1.2 -D
.stylelintrc.js添加
extends: ["stylelint-config-standard", "stylelint-config-rational-order", "stylelint-config-prettier"],
plugins: ["stylelint-order", "stylelint-declaration-block-no-ignored-properties"],
如果没有生效,重启vscode
- 报错自动修复错误
在
./vscode/settings.json添加
// 使用 stylelint 自身的校验即可
"css.validate": false,
"less.validate": false,
"scss.validate": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit"
},
- 验证保存下
EditorConfig
EditorConfig和Prettier一样,都是用来配置格式化你的代码的,这个格式化代码,要和你
lint配置相符!否则会出现你格式化代码以后,却不能通过你的代码校验工具的检验EditorConfig 文件中的设置用于在基本代码库中维持一致的编码风格和设置,例如缩进样式、选项卡宽度、行尾字符以及编码等,而无需考虑使用的编辑器或 IDE
- vscode安装
- 根目录新建
.editorconfig复制内容
root = true # 控制配置文件 .editorconfig 是否生效的字段
[**] # 匹配全部文件
indent_style = space # 缩进风格,可选space|tab
indent_size = 2 # 缩进的空格数
charset = utf-8 # 设置字符集
trim_trailing_whitespace = true # 删除一行中的前后空格
insert_final_newline = true # 设为true表示使文件以一个空白行结尾
end_of_line = lf
[**.md] # 匹配md文件
trim_trailing_whitespace = false
到此eslint+stylelint+prettier的代码规范,整理完成,我们继续
3.git规范
husky操作 git 钩子的工具
lint-staged本地暂存代码检查工具
commitlintcommit 信息校验工具
commitizen辅助 commit 信息 ,可以通过选择输入,规范提交信息
husky&lint-staged
- 安装
npm i husky@8.0.1 lint-staged@13.0.2 -D
- 在
package.json添加
{
"scripts": {
"prepare": "husky install"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
}
- 在根目录创建
lint-staged.config.js,并添加内容
module.exports = {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": ["prettier --write--parser json"],
"package.json": ["prettier --write"],
"*.{scss,less,styl,css}": ["stylelint --fix", "prettier --write"],
"*.md": ["prettier --write"]
};
- 运行
npm run prepare会在根目录生成.husky目录 - 在
.husky目录下创建文件pre-commit,并添加以下内容
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
- 提交下代码试试
git add -A
git commit -m '测试'
发现有个语句错误
变量a声明了未使用,删掉它并重新提交,最后push到远程仓库
commitlint
- 安装
npm i -D @commitlint/cli@17.0.2 @commitlint/config-conventional@17.0.2
- 根目录创建
commitlint.config.js
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" // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
]
]
}
};
.husky目录添加文件commit-msg
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no-install commitlint --edit $1
package.json添加
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint --config commitlint.config.js -E HUSKY_GIT_PARAMS"
}
},
- 重新提交到git
- 提交信息需要规范,type值需要commitlint.config.js定义的一种
commitizen&cz-git
- 通过选择输入,并且自定义配置提交规范
- 安装
npm i commitizen@4.2.4 cz-git@1.3.4 -D
package.json添加
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
},
commitlint.config.js添加
module.exports = {
//...
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": "git pull && git add -A && git-cz && git push"
- 运行
npm run commit,选择合适的选项,并填入信息,按回车并push到远程仓库
远程仓库显示对应的提交信息
4.完毕
代码在仓库