代码风格配置


ESLint

https://zh-hans.eslint.org/docs/latest/use/getting-started

  • ESLint是一个插件化并且可配置的 JavaScript 语法规则和代码风格的检查工具
    • 代码质量问题:使用方式有可能有问题
    • 代码风格问题:风格不符合一定规则

初始化

npm init @eslint/config
pnpm install  eslint  eslint-plugin-vue @typescript-eslint/parser @typescript-eslint/eslint-plugin  vue-eslint-parser eslint-define-config -D

常见的包

名称 说明
eslint ESLint 是一个用于识别和报告在 ECMAScript/JavaScript 代码中发现的模式的工具
eslint-plugin-vue Vue 的官方 ESLint 插件
@typescript-eslint/parser 一个 ESLint 解析器,它利用 TypeScript-ESTree 允许 ESLint 检查 TypeScript 源代码
@typescript-eslint/eslint-plugin 一个 ESLint 插件,为 TypeScript 代码库提供 lint 规则
@vue/eslint-config-typescript Vue 的 eslint-config-typescript

案例

.eslintrc.js

const { defineConfig } = require("eslint-define-config")
module.exports = defineConfig({
  root: true,
  env: {
    browser: true,
    node: true,
    es2021: true,
  },
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:vue/vue3-essential",
  ],
  parser: "vue-eslint-parser",
  parserOptions: {
    parser: "@typescript-eslint/parser",
    ecmaVersion: "latest",
    sourceType: "module",
  },
  plugins: ["@typescript-eslint", "vue"],
  rules: {
    // TS
    "@typescript-eslint/no-explicit-any": "off",
    "no-debugger": "off",
    "@typescript-eslint/explicit-module-boundary-types": "off",
    "@typescript-eslint/ban-types": "off",
    "@typescript-eslint/ban-ts-comment": "off",
    "@typescript-eslint/no-empty-function": "off",
    "@typescript-eslint/no-non-null-assertion": "off",
    "@typescript-eslint/no-unused-vars": [
      "error",
      {
        argsIgnorePattern: "^_",
        varsIgnorePattern: "^_",
      },
    ],
    "no-unused-vars": [
      "error",
      {
        argsIgnorePattern: "^_",
        varsIgnorePattern: "^_",
      },
    ],
    // Vue
    "vue/no-v-html": "off",
    "vue/require-default-prop": "off",
    "vue/require-explicit-emits": "off",
    "vue/multi-word-component-names": "off",
    "vue/html-self-closing": [
      "error",
      {
        html: {
          void: "always",
          normal: "always",
          component: "always",
        },
        svg: "always",
        math: "always",
      },
    ],
    // Prettier
    "prettier/prettier": [
      "warn",
      {
        endOfLine: "auto",
      },
    ],
  },
})

.eslintignore

*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
Dockerfile

components.d.ts
auto-imports.d.ts

*.min.js

package.json

{
    "scripts": {
     "dev": "vite",
     "build": "vue-tsc --noEmit && vite build",
+     "lint:eslint": "eslint --cache --max-warnings 0 \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx}\" --fix",
  },
}

Prettier

  • ESLint 主要解决的是代码质量问题

  • 代码质量规则

    • no-unused-vars 禁止出现未使用过的变量
    • no-implicit-globals 禁止在全局范围内使用变量声明和 function 声明
    • prefer-promise-reject-errors 要求使用 Error 对象作为 Promise 拒绝的原因
  • prettier 主要解决的是代码风格问题

    • max-len 最大长度
    • no-mixed-spaces-and-tabs 不允许空格和 tab 混合
    • keyword-spacing 关键字的空
    • comma-style 冒号风格

1 安装

npm install prettier eslint-plugin-prettier  @vue/eslint-config-prettier pretty-quick -D
名称 说明
prettier 代码格式化
eslint-plugin-prettier 作为 ESLint 规则运行得 prettier
@vue/eslint-config-prettier Vue 的 eslint-config-prettier

其他 :关闭所有不必要或可能与 Prettier 冲突的规则。

stylelint-config-prettier

2. 案例

.eslintrc.cjs

module.exports = {
  root: true,
  env: {
    browser: true,
    es2021: true,
    node: true
  },

  extends: [
    "plugin:vue/vue3-recommended",
    "eslint:recommended",
    "@vue/typescript/recommended",
+  	//添加两个插件
+   "prettier",
+   "@vue/eslint-config-prettier"
  ],
  parserOptions: {
    parser: "@typescript-eslint/parser",
    ecmaVersion: 2021
  },
  rules: {
+   //'prettier/prettier': "off",//关闭警告
+   // 配置规则级别和改正规则
+   "prettier/prettier": [
+     "error",
+     {
+       singleQuote: true,
+       tabWidth: 2,
+       indent: 2,
+       semi: false,
+       trailingComma: "none",
+       endOfLine: "auto"
+     }
+   ],
   "no-unused-vars": "off",
   "vue/no-unused-vars": "off",
   "@typescript-eslint/no-unused-vars": "off"
},
  globals: {
    defineProps: "readonly"
  }
}

.prettierrc.cjs

/** 配置项文档:https://prettier.io/docs/en/configuration.html */
module.exports = {
  /** 每一行的宽度 */
  printWidth: 120,
  /** Tab 键的空格数 */
  tabWidth: 2,
  /** 在对象中的括号之间是否用空格来间隔 */
  bracketSpacing: true,
  /** 箭头函数的参数无论有几个,都要括号包裹 */
  arrowParens: "always",
  /** 换行符的使用 */
  endOfLine: "auto",
  /** 是否采用单引号 */
  singleQuote: true,
  /** 对象或者数组的最后一个元素后面不要加逗号 */
  trailingComma: "none",
  /** 是否加分号 */
  semi: false,
  /** 是否使用 Tab 格式化 */
  useTabs: false,
}

.prettierignore

/dist/*
.local
.output.js
/node_modules/**

**/*.svg
**/*.sh

/public/*
.npmrc
index.html

pnpm-lock.yaml

components.d.ts
auto-imports.d.ts

*.min.js

package.json

{
  "lint:prettier": "prettier --write \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx,json,css,less,scss,html,md}\"",
  "lint:pretty": "pretty-quick --staged"
}

3.规则

https://prettier.io/docs/en/options.html

module.exports = {
  printWidth: 120, //最大列宽为 120 字符
  tabWidth: 2, //使用 2 个空格缩进
  useTabs: false, //不使用制表符缩进,使用空格
  semi: false, //不使用分号
  singleQuote: true, //使用单引号
  vueIndentScriptAndStyle: false, //不要在 Vue 文件中缩进脚本和样式标签。
  quoteProps: "as-needed", //仅在需要时在对象属性周围添加引号。
  bracketSpacing: true, //对象文字中括号之间的空格。
  trailingComma: "none", //不使用尾随逗号
  jsxBracketSameLine: false, // 在 jsx 中和后面的标签处于同一行
  jsxSingleQuote: false, //不在 jsx 中使用单引号
  arrowParens: "always", //在唯一的箭头函数参数周围包含括号
  insertPragma: false,
  requirePragma: false,
  proseWrap: "never",
  htmlWhitespaceSensitivity: "strict",
  endOfLine: "auto", // 自动选择行结束符
  rangeStart: 0,
  singleAttributePerLine: false, //在 HTML、Vue 和 JSX 中强制每行使用单一属性
}

editorconfig

  • editorconfig帮助开发人员在不同的编辑器和 IDE 之间定义和维护一致的编码样式
  • 不同的开发人员,不同的编辑器,有不同的编码风格,而 EditorConfig 就是用来协同团队开发人员之间的代码的风格及样式规范化的一个工具,而.editorconfig 正是它的默认配置文件
  • EditorConfig
  • vscode 这类编辑器,需要自行安装 editorconfig 插件

.editorconfig

# 配置项文档:https://editorconfig.org/

# 告知 EditorConfig 插件,当前即是根文件
root = true

# 适用全部文件
[*]
## 设置字符集
charset = utf-8
## 缩进风格 space | tab,建议 space
indent_style = space
## 缩进的空格数(修改这里的话需要将 prettier.config.js 和 .vscode -> settings.json 也同步修改)
indent_size = 2
## 换行符类型 lf | cr | crlf,一般都是设置为 lf
end_of_line = lf
## 是否在文件末尾插入空白行
insert_final_newline = true
## 是否删除一行中的前后空格
trim_trailing_whitespace = true

# 适用 .md 文件
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

.vscode/setting.json

{
  "editor.tabSize": 2,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[jsonc]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[scss]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

extensions.json

{
  "recommendations": [
    "editorconfig.editorconfig",
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "vue.vscode-typescript-vue-plugin",
    "vue.volar",
    "antfu.unocss",
    "zixuanchen.vitest-explorer",
    "wiensss.region-highlighter"
  ]
}

git hooks

  • 可以在git commit之前检查代码,保证所有提交到版本库中的代码都是符合规范的
  • 可以在git push之前执行单元测试,保证所有的提交的代码经过的单元测试
  • husky可以让我们向项目中方便添加git hooks,它会自动在仓库中的 .git/ 目录下增加相应的钩子,比如 pre-commit 钩子就会在你执行 git commit命令的时候的触发
  • lint-staged用于实现每次提交只检查本次提交所修改的文件
  • Commitlint 可以规范git commit -m ""中的描述信息

.gitignore

.DS_Store
node_modules
/screenshots
/dist
dist.zip
dist_electron

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# Editor directories and files
.idea
# .vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

types/auto-imports.d.ts
types/components.d.ts

husky

安装

npm install husky -D
npm pkg set scripts.prepare="husky install"
npm run prepare

使用

Edit package.json > prepare script and run it once:npm run prepare

npm pkg set scripts.prepare="husky install"
npm run prepare
# `npm test` will run every time you commit

LintStaged

https://github.com/okonet/lint-staged

安装

npm install lint-staged -D
npx husky add .husky/pre-commit "npx --no-install lint-staged"

Package.json

"lint-staged": {
  "*.{vue,js,jsx,ts,tsx}": [
    "eslint --fix",
    "prettier --write"
  ],
  "*.{css,less,scss,html,md}": [
    "prettier --write"
  ],
  "package.json": [
    "prettier --write"
  ]
},
 "scripts": {
   "lint": "pnpm lint:eslint && pnpm lint:prettier && pnpm  lint:styleLint",
   "lint:eslint": "eslint --max-warnings 0 \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx}\" --fix --cache --cache-location node_modules/.cache/eslint/",
   "lint:prettier": "prettier --write \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx,json,css,less,scss,html,md}\"",
   "lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
   "lint:lint-staged": "lint-staged",
   "prepare": "husky install",
 },
"lint-staged": {
   "*.{js,jsx,ts,tsx}": [
     "eslint --fix",
     "prettier --write"
   ],
   "*.json": [
     "prettier --write"
   ],
   "*.vue": [
     "eslint --fix",
     "prettier --write",
     "stylelint --fix"
   ],
   "*.{scss,less,styl,html}": [
     "stylelint --fix",
     "prettier --write"
   ],
   "*.md": [
     "prettier --write"
   ]
 },

commitlint 配置

  • commitlint推荐我们使用config-conventional配置去写 commit

  • 提交格式

    git commit -m <type>[optional scope]: <description>
    • type :用于表明我们这次提交的改动类型,是新增了功能?还是修改了测试代码?又或者是更新了文档?
    • optional scope:一个可选的修改范围。用于标识此次提交主要涉及到代码中哪个模块
    • description:一句话描述此次提交的主要内容,做到言简意赅

1. type

类型 描述
build 编译相关的修改,例如发布版本、对项目构建或者依赖的改动
chore 其他修改, 比如改变构建流程、或者增加依赖库、工具等
ci 持续集成修改
docs 文档修改
feature 新特性、新功能
fix 修改 bug
perf 优化相关,比如提升性能、体验
refactor 代码重构
revert 回滚到上一个版本
style 代码格式修改
test 测试用例修改

2. 安装

https://commitlint.js.org/#/guides-local-setup?id=install-commitlint

安装 commitlint

pnpm install @commitlint/cli @commitlint/config-conventional -D
安装 husky
# Install Husky v6
npm install husky --save-dev
# or
yarn add husky --dev

# Activate hooks
npx husky install
# or
yarn husky install

Add hook

npx husky add .husky/commit-msg  'npx --no-install commitlint --edit ${1}'

3. 配置

https://commitlint.js.org/#/reference-configuration

commitlint.config.js

module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    "type-enum": [
      2,
      "always",
      [
        "build",
        "chore",
        "ci",
        "docs",
        "feature",
        "fix",
        "perf",
        "refactor",
        "revert",
        "style",
        "test",
      ],
    ],
  },
}

4. 详细案例

module.exports = {
  ignores: [(commit) => commit.includes("init")],
  extends: ["@commitlint/config-conventional"],
  parserPreset: {
    parserOpts: {
      headerPattern:
        /^(\w*|[\u4e00-\u9fa5]*)(?:[\(\(](.*)[\)\)])?[\:\:] (.*)/,
      headerCorrespondence: ["type", "scope", "subject"],
      referenceActions: [
        "close",
        "closes",
        "closed",
        "fix",
        "fixes",
        "fixed",
        "resolve",
        "resolves",
        "resolved",
      ],
      issuePrefixes: ["#"],
      noteKeywords: ["BREAKING CHANGE"],
      fieldPattern: /^-(.*?)-$/,
      revertPattern: /^Revert\s"([\s\S]*)"\s*This reverts commit (\w*)\./,
      revertCorrespondence: ["header", "hash"],
      warn() {},
      mergePattern: null,
      mergeCorrespondence: null,
    },
  },
  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"],
    "type-enum": [
      2,
      "always",
      [
        "feat", // 新特性
        "fix", // 修复bug
        "perf", // 优化(性能)
        "style", // 样式
        "docs", // 文档
        "test", // 单元测试
        "refactor", // 重构
        "build", // 依赖打包相关
        "ci", // 持续集成
        "chore", // 日常
        "revert", // 回滚
        "wip", // 开发中
        "workflow", // 工作流
        "types", // 类型定义
        "release", // 发布
        "improvement", // 改进
      ],
    ],
  },
}

5. 常见问题

问题 1

hint: The '.husky/pre-commit' hook was ignored because it's not set as executable.
hint: You can disable this warning with `git config advice.ignoredHook false`.
hint: The '.husky/commit-msg' hook was ignored because it's not set as executable.
hint: You can disable this warning with `git config advice.ignoredHook false`.

这些提示的意思是:Husky 预提交钩子和提交消息钩子没有被设置为可执行文件,所以 Git 忽略了它们。

具体原因是:使用 Husky 时,它需要在 .husky 目录下创建一些钩子脚本文件,如:

  • .husky/pre-commit

  • .husky/commit-msg

但这些文件默认情况下不是可执行的。需要使用以下命令设置为可执行:

# 设置为可执行
chmod +x .husky/pre-commit
chmod +x .husky/commit-msg

毕竟只有可执行文件才能被 Git 用作钩子执行。


文章作者: 高红翔
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 高红翔 !
  目录