随着团队的扩张和业务的发展,代码量越来越大,也不再是一个人一个项目,一个项目往往要多人协作, 需要有一个良好的技术选型和成熟的架构做支撑,也需要团队中每一个开发者都能用心维护项目, 除了人工code review以外,就需要一些规范工具来帮我们提升代码质量,做到编码统一
一、Prettier
译为 “漂亮、美化”,即美化我们的代码,或者说格式化、规范化代码,使其更加工整
一般不会检查我们代码具体的写法,而是在“可读性”上做文章
支持包括多种语言、数据交换格式、语法规范扩展
如:javascript、html、vue、json、yaml、css、less、sass等
官方文档:prettier.io/
译为 “漂亮、美化”,即美化我们的代码,或者说格式化、规范化代码,使其更加工整
一般不会检查我们代码具体的写法,而是在“可读性”上做文章
支持包括多种语言、数据交换格式、语法规范扩展
如:javascript、html、vue、json、yaml、css、less、sass等
官方文档:prettier.io/
特点:
- 构建井统一代码风格
- 帮助团队新成员快速融入团队
- 开发者可以完全聚焦业务开发,不必在代码整理上花费过多心思
- 方便,低成本灵活接入,并快速发挥作用
- 清理井规范已有代码
- 减少潜在 Bug
- 丰富强大的社区支持
配置文件
安装依赖:
pnpm install prettier pretty-quick husky -D
.editorconfig -> .prettierrc.js 、 .prettierrc.js -> VsCode用户设置
.prettierrc
{
"semi": false,
"singleQuote": true,
"overrides": [
{
"files": ".prettierrc",
"options": {
"parser": "json"
}
}
]
}
.prettierignore
dist
node_modules
coverage
pnpm-lock.yaml
项目配置
{
"scripts":{
"lint:prettier": "prettier --write "src/**/*.{js,json,tsx,css,less,scss,vue,html,md}"",
},
"husky":{
"hooks":{
"pre-commit":"pretty-quick --staged"
}
}
}
二、Eslint
官方文档:eslint.org/docs/latest…
- 为什么要使用Eslint?
因为JavaScript不具备先天编译流程,往往在运行时暴露错误
- Eslint是做什么的?
Eslint,允许开发者在执行前发现代码错误,或不合理的写法
官方文档:eslint.org/docs/latest…
因为JavaScript不具备先天编译流程,往往在运行时暴露错误
Eslint,允许开发者在执行前发现代码错误,或不合理的写法
特点:
- 所有规则都插件化
- 所有规则都可插拔(随时开关)
- 所有设计都透明化
- 使用Espree进行JavaScript解析
- 使用AST分析语法
配置文件
安装依赖:
pnpm install eslint @wang-qing/eslint-config eslint-staged -D
.eslintrc.json
说明:
- off/0:关闭规则
- warn/1:以warning形式打开规则
- error/2:以error形式打开规则
.eslintignore
node_modules
dist
pnpm-lock.yaml
!.*
配置文件说明
配置文件优先级
- .eslintrc.js
- .eslintrc.cjs
- .eslintrc.yaml
- .eslintrc.yml
- .eslintrc.json
- package.json
eslint.config.js(实验功能)
export default [ { rules: { indent: ["error", 4],
quotes: ["error", "double"]
}
}
]
项目配置
{
"scripts":{
// 遍历所有文件,并在每个找到错误的文件中提供详细日志,但需要开发者手动打开这些文件并更正错误
"lint":"eslint --debug src/* ",
// --fix 可以自动修复错误
"lint:write":"eslint --debug src/ --fix",
"lint:eslint": "eslint --cache --max-warnings 0 "{src,mock}/**/*.{vue,ts,tsx}" --fix",
"lint:lint-staged": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
"prettier --write--parser json"
],
"package.json": [
"prettier --write"
],
"*.vue": [
"eslint --fix",
"prettier --write",
"stylelint --fix"
],
"*.{scss,less,styl,html}": [
"stylelint --fix",
"prettier --write"
],
"*.md": [
"prettier --write"
]
}
}
三、husky
husky就是git的钩子,在GIt进行到某一时段时,可以交给开发者完成某些特定的操作
例:在整个项目上运行lint会很慢,我们一般只想对更改的文件进行检查,此时就需要使用到lint-staged
官方文档:git-scm.com/book/zh/v2/…
husky和lint-staged结合使用
{
"husky". {
"hooks":{
"pre-commit", "lint-staged"
}
"lint-staged": {
"*.(jslisx)": ["npm run lint:eslint","npm run lint:prettier","git add"]
}
}
四、stylelint
官方文档:stylelint.io/
安装stylelint依赖
husky就是git的钩子,在GIt进行到某一时段时,可以交给开发者完成某些特定的操作
例:在整个项目上运行lint会很慢,我们一般只想对更改的文件进行检查,此时就需要使用到lint-staged
官方文档:git-scm.com/book/zh/v2/…
{
"husky". {
"hooks":{
"pre-commit", "lint-staged"
}
"lint-staged": {
"*.(jslisx)": ["npm run lint:eslint","npm run lint:prettier","git add"]
}
}
官方文档:stylelint.io/
安装stylelint依赖
pnpm install stylelint stylelint-config-html stylelint-config-prettier stylelint-config-standard stylelint-order -D
postcss依赖
pnpm install postcss postcss-less postcss-html -D
package.json
{
"lint:stylelint": "stylelint --cache --fix "**/*.{vue,less,postcss,css,scss}" --cache --cache-location node_modules/.cache/stylelint/"
}
stylelint.config.cjs
module.exports = {
root: true,
plugins: ['stylelint-order'],
// customSyntax: 'postcss-less',
extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
rules: {
'selector-class-pattern': null,
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global'],
},
],
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep'],
},
],
'at-rule-no-unknown': [
true,
{
ignoreAtRules: [
'tailwind',
'apply',
'variants',
'responsive',
'screen',
'function',
'if',
'each',
'include',
'mixin',
],
},
],
'no-empty-source': null,
'named-grid-areas-no-invalid': null,
'unicode-bom': 'never',
'no-descending-specificity': null,
'font-family-no-missing-generic-family-keyword': null,
'declaration-colon-space-after': 'always-single-line',
'declaration-colon-space-before': 'never',
// 'declaration-block-trailing-semicolon': 'always',
'rule-empty-line-before': [
'always',
{
ignore: ['after-comment', 'first-nested'],
},
],
'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }],
'order/order': [
[
'dollar-variables',
'custom-properties',
'at-rules',
'declarations',
{
type: 'at-rule',
name: 'supports',
},
{
type: 'at-rule',
name: 'media',
},
'rules',
],
{ severity: 'warning' },
],
},
ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'],
overrides: [
{
files: ['*.vue', '**/*.vue', '*.html', '**/*.html'],
extends: ['stylelint-config-recommended', 'stylelint-config-html'],
rules: {
'keyframes-name-pattern': null,
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['deep', 'global'],
},
],
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'],
},
],
},
},
],
};
五、.editorconfig
官方文档:editorconfig.org/
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
quote_type = single
六、jsconfig.json
官方文档:code.visualstudio.com/docs/langua…
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"#/*": ["types/*"]
},
"jsx": "preserve"
},
"include": ["src/**/*.d.ts", "src/**/*.js"],
"exclude": ["node_modules", "**/node_modules", "dist"]
}
七、Vscode
推荐扩展
官方文档:editorconfig.org/
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
quote_type = single
官方文档:code.visualstudio.com/docs/langua…
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"#/*": ["types/*"]
},
"jsx": "preserve"
},
"include": ["src/**/*.d.ts", "src/**/*.js"],
"exclude": ["node_modules", "**/node_modules", "dist"]
}
七、Vscode
推荐扩展
名称 | 描述 |
---|---|
Vue Language Features | 为Vue,Vitepress和petite-vue构建的语言支持扩展 |
Prettier | Prettier是一个固执己见的代码格式化程序 |
Eslint | 将 ESLint 集成到 VS Code 中 |
Stylelint | Stylelint的扩展 |
Sass | sass的扩展插件 |
Editor for VS Code | 此插件尝试使用 .editorconfig 文件中的设置覆盖用户/工作区设置 |
extensions.json
extensions.json在项目下的.vscode文件夹中
{
"recommendations": [
"Vue.volar",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint",
"syler.sass-indented",
"EditorConfig.EditorConfig"
]
}
settings.json
settings.json在项目下的.vscode文件夹中
个人设置参考
{
//===========================================
//============= Editor ======================
//===========================================
"editor.tabSize": 2,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.fontSize": 15,
// "editor.formatOnSave": true,
"editor.inlineSuggest.enabled": true,
"editor.accessibilitySupport": "off",
"editor.wordWrap": "on",
"editor.cursorSmoothCaretAnimation": true,
"editor.snippetSuggestions": "top",
// 保存后自动修复格式
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
//===========================================
//============= workbench =======================
//===========================================
"workbench.iconTheme": "vscode-great-icons",
"workbench.colorTheme": "Vitesse Dark Soft",
"workbench.tree.indent": 16,
//===========================================
//============= files =======================
//===========================================
"files.autoSave": "onFocusChange",
"files.eol": "\n",
"search.exclude": {
"**/node_modules": true,
"**/*.log": true,
"**/*.log*": true,
"**/bower_components": true,
"**/dist": true,
"**/elehukouben": true,
"**/.git": true,
"**/.gitignore": true,
"**/.svn": true,
"**/.DS_Store": true,
"**/.idea": true,
"**/.vscode": false,
"**/yarn.lock": true,
"**/tmp": true,
"out": true,
"dist": true,
"node_modules": true,
"CHANGELOG.md": true,
"examples": true,
"res": true,
"screenshots": true,
"yarn-error.log": true,
"**/.yarn": true
},
"files.exclude": {
"**/.cache": true,
"**/.editorconfig": true,
"**/.eslintcache": true,
"**/bower_components": true,
"**/.idea": true,
"**/tmp": true,
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true
},
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/.vscode/**": true,
"**/node_modules/**": true,
"**/tmp/**": true,
"**/bower_components/**": true,
"**/dist/**": true,
"**/yarn.lock": true
},
"files.associations": {
"*.cjson": "jsonc",
"*.wxss": "css",
"*.wxs": "javascript"
},
"emmet.includeLanguages": {
"wxml": "html"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// "[vue]": {
// "editor.codeActionsOnSave": {
// "source.fixAll.eslint": false
// }
// },
"fileheader.configObj": {
"createFileTime": true,
"language": {
"languagetest": {
"head": "/$$",
"middle": " $ @",
"end": " $/",
"functionSymbol": {
"head": "/** ",
"middle": " * @",
"end": " */"
},
"functionParams": "js"
}
},
"autoAdd": false,
"autoAddLine": 100,
"autoAlready": false,
"annotationStr": {
"head": "/*",
"middle": " * @",
"end": " */",
"use": false
},
"headInsertLine": {
"php": 2,
"sh": 2
},
"beforeAnnotation": {
"文件后缀": "该文件后缀的头部注释之前添加某些内容"
},
"afterAnnotation": {
"文件后缀": "该文件后缀的头部注释之后添加某些内容"
},
"specialOptions": {
"特殊字段": "自定义比如LastEditTime/LastEditors"
},
"switch": {
"newlineAddAnnotation": true
},
"supportAutoLanguage": [],
"prohibitAutoAdd": ["json"],
"folderBlacklist": ["node_modules", "文件夹禁止自动添加头部注释"],
"prohibitItemAutoAdd": [
"项目的全称, 整个项目禁止自动添加头部注释, 可以使用快捷键添加"
],
"moveCursor": true,
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"atSymbol": ["@", "@"],
"atSymbolObj": {
"文件后缀": ["头部注释@符号", "函数注释@符号"]
},
"colon": [": ", ": "],
"colonObj": {
"文件后缀": ["头部注释冒号", "函数注释冒号"]
},
"filePathColon": "路径分隔符替换",
"showErrorMessage": false,
"writeLog": false,
"wideSame": false,
"wideNum": 13,
"functionWideNum": 0,
"CheckFileChange": false,
"createHeader": false,
"useWorker": false,
"designAddHead": false,
"headDesignName": "random",
"headDesign": false,
"cursorModeInternalAll": {},
"openFunctionParamsCheck": true,
"functionParamsShape": ["{", "}"],
"functionBlankSpaceAll": {},
"functionTypeSymbol": "*",
"typeParamOrder": "type param",
"customHasHeadEnd": {},
"throttleTime": 60000,
"functionParamAddStr": "",
"NoMatchParams": "no show param",
"search.followSymlinks": false,
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/tmp": true,
"**/node_modules": true,
"**/bower_components": true,
"**/dist": true
},
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/node_modules/**": true,
"**/tmp/**": true,
"**/bower_components/**": true,
"**/dist/**": true
}
},
//===========================================
//============= terminal =======================
//===========================================
"terminal.integrated.defaultProfile.osx": "zsh",
"terminal.integrated.fontSize": 14,
"terminal.integrated.env.osx": {
"FIG_NEW_SESSION": "1"
},
//===========================================
//============= volar =======================
//===========================================
"volar.autoCompleteRefs": true,
"volar.tsPlugin": true,
"volar.tsPluginStatus": false,
//===========================================
//============= eslint =======================
//===========================================
"eslint.codeActionsOnSave.rules": null,
// 添加vue支持
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"html",
"vue",
"json",
"json5",
"jsonc",
"yaml"
],
"eslint.probe": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"html",
"vue",
"json",
"json5",
"jsonc",
"yaml"
],
//===========================================
//============= stylelint =======================
//===========================================
"css.validate": false,
"scss.validate": false,
"less.validate": false,
"stylelint.enable": true,
"stylelint.packageManager": "yarn",
//===========================================
//============= other =======================
//===========================================
"window.nativeTabs": true,
"errorLens.enabledDiagnosticLevels": [
"error"
],
"window.zoomLevel": 1,
"path-intellisense.mappings": {
"@/": "${workspaceRoot}/src"
},
}
八、其他配置文件
.npmrc(使用pnpm)
shamefully-hoist=true
strict-peer-dependencies=false
.nvmrc
shamefully-hoist=true
strict-peer-dependencies=false
v18
.browserslistrc
# Browsers that we support
last 1 version
> 1%
IE 10 # sorry
.markdownlint.json
{
"MD033": false,
"MD013": false
}