赞
踩
前端代码风格因人而异,一个项目参与的人多了,不加强控制可能就是一个大杂烩,对开发人员来讲就是一个噩梦。
如何解决这种困境?
通过使用 ESLint +Prettier+ Husky + Lint-staged+Commitlint + Commitizen 这套方案,它能够在提升代码质量,保障团队协作效率,统一项目代码风格,强化代码审查流程,支持自动化运维 和促进项目管理等方面发挥重要作用,同时为项目的长期稳健发展打下坚实基础。
吴冬林| 前端开发工程师
目录
为何要打造这样一套前端现代化规范工程?
1、代码风格一致性:
2、自动化代码质量保障:
3、规范化提交信息:
4、标准化提交流程:
认识:
ESLint 是一个开源的、强大的静态代码分析工具,主要用于检测 JavaScript 和相关编程语言(如 TypeScript、Vue、React、Angular 等)的代码中潜在的错误、不符合最佳实践的模式以及不一致的编码风格。
网址:
·官网地址:https://eslint.org/
·中文网地址:https://eslint.nodejs.cn/
·eslint-vue配置规则:https://eslint.vuejs.org/rules/
使用方法:
1、需要安装相关依赖如下:
2、安装方法:
pnpm i -D eslint eslint-plugin-importeslint-plugin-prettier eslint-config-prettier eslint-plugin-vue vue-eslint-parser @typescript-eslint/parser @typescript-eslint/eslint-plugin
3、配置,eslintrc.js
在根目录下新建 .eslintrc.js 文件, rules 里面的内容根据实际需求自行添加,编辑内容如下:
- module.exports = {
- root: true,
- env: {
- browser: true,
- node: true,
- es6: true
- },
- parser: 'vue-eslint-parser',
- extends: [
- 'eslint:recommended', // 推荐使用eslint基础配置规则
- 'plugin:vue/vue3-recommended', // 对于Vue3项目,识别vue3语法规则
- 'plugin:@typescript-eslint/recommended', // 使用推荐的TypeScript 专用 lint 规则
- 'prettier', // 引入eslint-config-prettier,应用 Prettier 的格式化规则,禁用冲突规则
- 'plugin:prettier/recommended'// 引入eslint-plugin-prettier,推荐的 prettier 专用 lint 规则
- ],
- parserOptions: {
- parser: '@typescript-eslint/parser',
- ecmaVersion: 2020,
- sourceType: 'module',
- jsxPragma: 'React',
- ecmaFeatures: {
- jsx: true
- }
- },
- /**
- * 自定义或覆盖特定规则 https://www.wenjiangs.com/docs/eslint,vue规则:https://eslint.vuejs.org/rules/
- * 主要有如下的设置规则,可以设置字符串也可以设置数字,两者效果一致
- * 'off' 或 0 - 关闭规则
- * 'warn' 或 1 - 开启警告规则,使用警告级别的错误:warn (不会导致程序退出),
- * 'error' 或 2 - 开启错误规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
- */
- rules: {
- 'no-debugger': 'off',
- 'no-case-declarations': 'off', // 防止在 switch 语句的 case 子句中声明变量
- 'no-console': 'off',
- 'no-undef': 'off',
- 'no-useless-escape': 'off',
- // 'no-unused-vars': 'off', // 防止出现未使用的变量、函数参数或常量
- 'no-restricted-imports': 'off',
- 'no-use-before-define': 'off',
- 'no-sparse-arrays': 'off',
- 'compat/compat': 'off',
- 'no-constant-condition': 'off',
- 'prefer-const': ['warn', { destructuring: 'all', ignoreReadBeforeAssign: true}],
- '@typescript-eslint/ban-ts-ignore': 'off',
- '@typescript-eslint/explicit-function-return-type': 'off',
- '@typescript-eslint/no-explicit-any': 'off',
- '@typescript-eslint/no-var-requires': 'off',
- '@typescript-eslint/no-empty-function': 'off',
- '@typescript-eslint/no-use-before-define': 'off',
- '@typescript-eslint/ban-ts-comment': 'off',
- '@typescript-eslint/ban-types': 'off',
- '@typescript-eslint/no-non-null-assertion': 'off',
- '@typescript-eslint/explicit-module-boundary-types': 'off',
- // 检查未使用的变量、函数参数、类属性
- '@typescript-eslint/no-unused-vars': [
- 'error',
- {
- argsIgnorePattern: '^_',
- varsIgnorePattern: '^_',
- },
- ],
- '@typescript-eslint/no-redeclare': 'off',
- '@typescript-eslint/no-this-alias': 'off',
- 'vue/no-setup-props-destructure': 'off',
- 'vue/script-setup-uses-vars': 'error',
- 'vue/no-reserved-component-names': 'off',
- 'vue/custom-event-name-casing': 'off',
- 'vue/attributes-order': 'off',
- 'vue/one-component-per-file': 'off',
- 'vue/html-closing-bracket-newline': 'off',
- 'vue/max-attributes-per-line': 'off',
- 'vue/multiline-html-element-content-newline': 'off',
- 'vue/singleline-html-element-content-newline': 'off',
- 'vue/attribute-hyphenation': 'off',
- 'vue/require-default-prop': 'off',
- 'vue/require-explicit-emits': 'off',
- 'vue/require-toggle-inside-transition': 'off',
- 'vue/html-self-closing': 'off',
- 'vue/multi-word-component-names': 'off',
- 'vue/no-v-html': 'off',
- 'vue/no-dupe-keys': 'off',
- 'vue/no-deprecated-v-on-native-modifier': 'off',
- 'vue/html-indent': 'off',
- 'vue/no-template-shadow': 'off',
- "prettier/prettier":'off'
- }
- };
4、配置.eslintignore
在根目录下新建.eslintignore文件, 用来让eslint不用检查这些文件
- // .eslintignore
- # Logs
- logs
- *.log
- npm-debug.log*
- yarn-debug.log*
- yarn-error.log*
- pnpm-debug.log*
- lerna-debug.log*
-
- node_modules
- dist
- public
-
- # Editor directories andfiles
- .vscode/*
- !.vscode/extensions.json
- .husky
-
- src/assets/
- plop-templates/
-
- package.json
- README.md
认识:
Prettier 是一个自动化的代码格式化器,支持多种编程语言,包括 JavaScript、TypeScript、HTML、CSS、JSON、Markdown 等。它的目标是提供一种统一、可配置但非协商式的代码风格,旨在消除团队成员之间因代码风格偏好产生的分歧,提高代码可读性和维护性。
网址:
·官方网址:https://prettier.io/
·prettier中文网:https://www.prettier.cn/
使用方法:
1、安装:
pnpmi -D prettier
2、配置.prettierrc.js
在根目录下新建 .prettierrc.js 文件,里面的内容根据实际需求自行添加,编辑内容如下:
- module.exports= {
- // 每行最多字符数量,超出换行(默认80)
- printWidth: 80,
- // 超出打印宽度 (always | never | preserve )
- proseWrap: "preserve",
- // (x)=>{},单个参数箭头函数是否显示小括号。(always:始终显示;avoid:省略括号。默认:always)
- arrowParens: "always",
- // 开始标签的右尖括号是否跟随在最后一行属性末尾,默认false
- bracketSameLine: false,
- // 对象字面量的括号之间打印空格 (true - Example: { foo: bar } ; false - Example: {foo:bar})
- bracketSpacing: true,
- // 是否格式化一些文件中被嵌入的代码片段的风格(auto|off;默认auto)
- embeddedLanguageFormatting: "auto",
- // 指定 HTML 文件的空格敏感度 (css|strict|ignore;默认css)
- htmlWhitespaceSensitivity: "css",
- // 当文件已经被 Prettier 格式化之后,是否会在文件顶部插入一个特殊的 @format 标记,默认false
- insertPragma: false,
- // 在 JSX 中使用单引号替代双引号,默认false
- jsxSingleQuote: false,
- // 对象属性是否使用引号(as-needed | consistent | preserve;默认as-needed:对象的属性需要加引号才添加;)
- quoteProps: "as-needed",
- // 是否只格式化在文件顶部包含特定注释(@prettier| @format)的文件,默认false
- requirePragma: false,
- // 结尾添加分号
- semi: true,
- // 使用单引号 (true:单引号;false:双引号)
- singleQuote: true,
- // 缩进空格数,默认2个空格
- tabWidth: 2,
- // 元素末尾是否加逗号,默认es5: ES5中的 objects, arrays 等会添加逗号,TypeScript 中的 type 后不加逗号
- trailingComma: "es5",
- // 指定缩进方式,空格或tab,默认false,即使用空格
- useTabs: false,
- // vue 文件中是否缩进 <style> 和 <script> 标签,默认 false
- vueIndentScriptAndStyle: false,
- // 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
- endOfLine: "auto",
- };
3、配置.prettierignore
在根目录下新建.prettierignore文件, 用来让prettier不用格式化这些文件
- /dist/*
- /node_modules/**
- /public/*
- src/assets/
-
- .prettierrc.js
- .eslintrc.js
- commitlint.config.js
- README.md
- package.json
- vite.config.ts
-
- # Editor directories andfiles
- .vscode/*
- !.vscode/extensions.json
- .husky/*
Vscode插件:
在vscode插件栏,搜索并安装如下插件;
1、eslint:提供eslint的校验,保存自动修复功能
2、prettier:提供prettier 保存自动格式化的功能
扩展:
项目自身配置eslint、prettier插件与vscode安装插件关系:
相辅相成,共同作用于项目格式化校验和修复;项目自身配置eslint、prettier插件的格式化规范,其优先级要高于vscode安装的eslint、prettier插件;
Vscode设置:
在项目根目录下新建.vscode/setting.json文件,写入以下内容,即可在保存代码的时候自动按照eslint和prettier的规范进行代码格式化
- {
- // 设置npm包管理器为pnpm
- "npm.packageManager": "pnpm",
- // 设置编辑器的Tab大小为2个空格
- "editor.tabSize": 2,
- // 配置编辑器在每次保存时自动格式化代码
- "editor.formatOnSave": true,
- // 设置默认的代码格式化工具为prettier
- "editor.defaultFormatter": "esbenp.prettier-vscode",
- // 配置编辑器在保存时执行的代码动作,包括应用所有明确的修复
- "editor.codeActionsOnSave": {
- "source.fixAll": "explicit",
- "source.fixAll.eslint": "explicit",
- "source.fixAll.stylelint": "explicit"
- },
- // 自定义拼写检查词典,包含一些特定的技术词汇
- "cSpell.words": [
- "lint-staged",
- "lintstagedrc",
- "persistedstate",
- "pinia",
- "pnpm",
- "stylelint",
- ],
- }
前提:
需要安装如下依赖:
认识:
Husky 是一个 Git 钩子管理工具,允许您在 Git 的各个生命周期事件(如 pre-commit、pre-push、post-commit 等)中轻松添加自定义脚本。通过 Husky,您可以确保在提交代码之前执行必要的代码检查(如 ESLint、Prettier、单元测试等),防止不符合规范或存在错误的代码进入版本库。这有助于提高代码质量和维护项目的整洁性。
网址:https://typicode.github.io/husky/
使用方法:
1、配置husky
执行下面两行代码
- npm pkg setscripts.prepare="husky install"// 在 package.json 中添加脚本
- npm run prepare // 初始化 husky,将 git hooks 钩子交由 husky 执行
执行完这两行代码以后,发生了两件事情:
第一个是package.json中新增了一个脚本
- "scripts": {
- "prepare": "husky install"
- },
第二个是根目下新增了 .husky 文件夹;
2、配置pre-commit
2.1、新建pre-commit文件并添加内容
在.husky文件夹下新建pre-commit 文件,然后添加以下内容:
- #!/bin/sh
- . "$(dirname "$0")/_/husky.sh"
-
- pnpm execlint-staged
作用:是在执行git commit时,先加载husky的内部脚本,然后使用pnpm执行lint-staged命令,对暂存区中的代码进行代码风格检查和格式化,确保符合项目规范后再提交。
2.2、配置lint-staged
在package.json中,添加如下配置,表示通过eslint来自动修复各类文件格式;
- "lint-staged": {
- "*.{vue,js,ts,jsx,tsx,md,json}": "eslint --fix"
- }
扩展:
Lint-Staged:是一个在 Git暂存区(staging area)中运行 linters 的工具。当您准备提交代码时,Lint-Staged 仅针对已暂存的文件运行指定的 linting 工具(如 ESLint、Prettier、stylelint 等)。这样可以确保只有即将被提交的改动经过了严格的质量检查,避免了对整个项目进行 linting 所带来的性能开销,同时也确保每次提交都是干净且符合规范的。
配置只校验暂存区文件:
在package.json中,添加如下命令,表示只校验暂存区代码格式;
- "scripts": {
- "lint:lint-staged": "lint-staged"
- }
3、效果展示
到这里为止,代码提交时,代码自动检测功能已经实现了,来测试一下效果。
如图:有三处问题:
提交一下,看一看结果会怎么样?
修改代码后,进行第二次测试;
重新提交,这次提交成功了;结果如下:
结论:通过配置husky和eslint,提交代码的时候会自动进行格式化,如果有格式化解决不了的错误,就会报错。
认识:
Commitlint 是一个用于验证 Git 提交消息格式的工具,基于社区广泛接受的 Conventional Commits 规范。它确保提交消息遵循一定的结构和约定,如明确的类型(fix、feat、docs、chore 等)、简洁的描述、可选的正文和 footer 等。通过规范化提交消息,Commitlint 帮助生成清晰、一致的 changelog,便于追踪项目变更历史,辅助自动化版本发布流程(如通过 semantic-release)。
使用方法:
1、配置commit-msg
新建commit-msg文件并添加内容
在.husky文件夹下新建commit-msg 文件,然后添加以下内容:
- #!/bin/sh
- . "$(dirname "$0")/_/husky.sh"
-
- pnpm execcommitlint --edit "${1}"
作用:使用 pnpm 执行 commitlint 命令,根据 commitlint.config.js 中的配置检查提交消息格式是否符合项目规范。如果提交消息不符合规范,commitlint 尝试自动修正消息内容,以便用户在继续提交时获得符合规范的消息。
2、配置commitlint.config.js
在项目跟目录下新建commitlint.config.js文件,并添加如下配置:
- // @see: https://cz-git.qbenben.com/zh/guide
- /** @type{import('cz-git').UserConfig} */
-
- module.exports = {
- ignores: [commit => commit.includes("init")],
- extends: ["@commitlint/config-conventional"],
- rules: {
- // @see: https://commitlint.js.org/#/reference-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: "Select the type of change that you're committing:",
- scope: "Denote the SCOPE of this change (optional):",
- customScope: "Denote the SCOPE of this change:",
- subject: "Write a SHORT, IMPERATIVE tense description of the change:\n",
- body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
- breaking: 'List any BREAKING CHANGES (optional). Use "|" to break new line:\n',
- footerPrefixsSelect: "Select the ISSUES type of changeList by this change (optional):",
- customFooterPrefixs: "Input ISSUES prefix:",
- footer: "List any ISSUES by this change. E.g.: #31, #34:\n",
- confirmCommit: "Are you sure you want to proceed with the commit above?"
- // 中文版
- // 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: A new feature",
- emoji: " "
- },
- {
- value: "fix",
- name: "fix: A bug fix",
- emoji: " "
- },
- {
- value: "docs",
- name: "docs: Documentation only changes",
- emoji: " "
- },
- {
- value: "style",
- name: "style: Changes that do not affect the meaning of the code",
- emoji: " "
- },
- {
- value: "refactor",
- name: "refactor: ♻️ A code change that neither fixes a bug nor adds a feature",
- emoji: "♻️"
- },
- {
- value: "perf",
- name: "perf: ⚡️ A code change that improves performance",
- emoji: "⚡️"
- },
- {
- value: "test",
- name: "test: ✅ Adding missing tests or correcting existing tests",
- emoji: "✅"
- },
- {
- value: "build",
- name: "build: ️ Changes that affect the build system or external dependencies",
- emoji: " ️"
- },
- {
- value: "ci",
- name: "ci: Changes to our CI configuration files and scripts",
- emoji: " "
- },
- {
- value: "chore",
- name: "chore: Other changes that don't modify src or test files",
- emoji: " "
- },
- {
- value: "revert",
- name: "revert: ⏪️ Reverts a previous commit",
- emoji: "⏪️"
- }
- // 中文版
- // { value: "特性", name: "特性: 新增功能", emoji: " "},
- // { value: "修复", name: "修复: 修复缺陷", emoji: " "},
- // { value: "文档", name: "文档: 文档变更", emoji: " "},
- // { value: "格式", name: "格式: 代码格式(不影响功能,例如空格、分号等格式修正)", emoji: " "},
- // { value: "重构", name: "重构: ♻️ 代码重构(不包括 bug 修复、功能新增)", emoji: "♻️"},
- // { value: "性能", name: "性能: ⚡️ 性能优化", emoji: "⚡️"},
- // { value: "测试", name: "测试: ✅ 添加疏漏测试或已有测试改动", emoji: "✅"},
- // { value: "构建", name: "构建: ️ 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)", emoji: " ️"},
- // { value: "集成", name: "集成: 修改 CI 配置、脚本", emoji: " "},
- // { value: "回退", name: "回退: ⏪️ 回滚 commit", emoji: "⏪️"},
- // { value: "其他", name: "其他: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: " "}
- ],
- }
- };
作用:commitlint.config.js 是 commitlint 工具的核心配置文件,它用于定义项目中 Git 提交消息(commit messages)应遵循的格式规则和规范。
3、配置commit提交命令
在package.json中,添加如下配置,用于自动提交全部文件并执行 git-cz
- // package.json
- "scripts": {
- "commit": "git pull && git add -A && git-cz && git push",
- },
- "config": {
- "commitizen": {
- "path": "node_modules/cz-git"
- }
- }
扩展:
Commitizen:是一个辅助创建符合 Conventional Commits 规范的 Git 提交消息的命令行工具。它提供了一个交互式的提交流程,引导开发者按照规定的格式输入提交信息,包括类型、scope(可选)、描述、正文(可选)和 footer(可选)。
cz-git:这个包名表明它可能是一个与Git结合使用的Commitizen插件或适配器。一般来说,Commitizen通过cz命令行工具与用户交互,引导他们按照预定义的格式填写提交信息。
4、效果展示:
到这里为止,所有的配置都完成了,来测试一下效果;
使用pnpm run commit来执行代码默认自动提交;
代码提交完成且没有报错提示。
1、通过使用 ESLint +Prettier+ Husky + Lint-staged+Commitlint + Commitizen这套方案,它能够在提升代码质量,保障团队协作效率,统一项目代码风格,强化代码审查流程,支持自动化运维 和促进项目管理等方面发挥重要作用,同时为项目的长期稳健发展打下坚实基础。
2、需要安装的依赖包及配置如下:
- {
- "version": "0.0.0",
- "scripts": {
- "dev": "vite",
- "build:dev": "vite build --mode development",
- "build:test": "vite build --mode test",
- "build:prod": "vite build --mode production",
- "lint:lint-staged": "lint-staged",
- "commit": "git pull && git add -A && git-cz && git push",
- "prepare": "husky install"
- },
- "dependencies": {
- "vue": "^3.4.23",
- },
- "devDependencies": {
- "@commitlint/cli": "^17.3.0",
- "@commitlint/config-conventional": "^17.8.1",
- "@typescript-eslint/eslint-plugin": "^5.32.0",
- "@typescript-eslint/parser": "^5.32.0",
- "commitizen": "^4.3.0",
- "cz-git": "^1.3.12",
- "eslint": "^8.57.0",
- "eslint-config-prettier": "^9.1.0",
- "eslint-plugin-import": "^2.29.1",
- "eslint-plugin-prettier": "^5.1.3",
- "eslint-plugin-vue": "^9.25.0",
- "husky": "^9.0.11",
- "lint-staged": "^15.2.2",
- "prettier": "^3.2.5",
- "typescript": "^4.6.4",
- "vue-eslint-parser": "^9.4.2",
- },
- "config": {
- "commitizen": {
- "path": "node_modules/cz-git"
- }
- },
- "lint-staged": {
- "*.{vue,js,ts,jsx,tsx,md,json}": "eslint --fix"
- }
- }
版权声明:本文由神州数码云基地团队整理撰写,若转载请注明出处。
公众号搜索神州数码云基地,了解更多技术干货。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。