Skip to content
快速预览

vue项目中代码规范配置

✍️ w 🕒 2023-09-19 09:31:13(8 months ago) 🔗 H.各种练习项目

在团队开发过程中需要良好的代码规范帮助我们提高团队代码协作,常见的方式就是 使用 eslint 配合 prettier 来进行代码规范的约束。具体使用可以参考 eslintprettier 官网。 或者是章节中的前端工程化 / 搭建代码规范 章节中讲解

关于 vue 配置 eslint 和 prettier

在通过vite安装完成项目后,选择了 eslint 和 prettier 作为代码规范检测工具后生成两个文件 .eslintrc.cjs.prettierrc.json

.eslintrc.cjs 文件

  • plugin:vue/vue3-essential这是 Vue 3 的基本 linting 规则,并且替换了默认的 JavaScript 解析器,因为 Vue.js 单个文件组件不是普通的 JavaScript,所以为了能够让语法树进行分析就需要是要vue 自己的解析器Vue-eslint-parser。 使用他首先安装 yarn add -D eslint eslint-plugin-vue 其中 plugin:vue/vue3-essential 规则主要针对 加上防止错误或意外行为的规则,但不会强制执行个人偏好的规则。如果你想要一个更严格的规则集,可以使用 plugin:vue/vue3-strongly-recommended 或 plugin:vue/vue3-recommended。查看他的规则

  • eslint:recommended 这是 ESLint 推荐的规则集 该规则集包含一些在 ESLint 官方文档中被认为是最佳实践的规则,这些规则可以帮助你避免一些常见的错误。

  • @vue/eslint-config-typescript:这是 Vue 官方提供的 TypeScript linting 规则 ,它还关闭了 eslint 中的几个冲突规则: 推荐规则集,这个配置是专门为 @vue/cli & create-vue 设置而设计的,不适合外部使用(它可以使用,但可能需要在用户端进行一些修改——详细信息请参阅配置文件)。需要配合 @rushstack/eslint-patch 安装 npm add --dev @vue/eslint-config-typescript @rushstack/eslint-patch@vue/eslint-config-typescript 有两套规则集,一个是 @vue/eslint-config-typescript ,一个就是 @vue/eslint-config-typescript/recommended 。其中,后者更加严格参考规则

  • @vue/eslint-config-prettier/skip-formatting:专门给 Vue 使用的 Prettier 验证规则(eslint-config-prettier)。作用:关闭所有不需要的、或者可能与 Prettier 产生冲突的 eslint 规则。

  • parserOptions:解析器选项,允许你指定 JS 语言(包括 JSX 语法),默认为 ES5。这里设置为 latest,表示支持最新的 ES 语法。

注意他们的顺序 Prettier 它应该被放在 extends 数组的最后而覆盖其他配置,这样就能完全关闭 ESLint 规则集中与格式化代码相关的规则,并且如果在 eslint 中集成了 Prettier,那么在使用 eslint fix 时候也会一并修复 prettier 的规则。

js
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = {
  root: true,
  'extends': [
    'plugin:vue/vue3-essential',//vue3语法规则
    'eslint:recommended', //全部规则默认是关闭的,这个配置项开启推荐规则
    '@vue/eslint-config-typescript', // ts语法规则
    '@vue/eslint-config-prettier/skip-formatting' // 关闭eslint 和 prettier 的冲突
  ],
	//指定解析器:解析器
	//Esprima 默认解析器
	//Babel-ESLint babel解析器
	//@typescript-eslint/parser ts解析器
	// "parser": "@typescript-eslint/parser",
  parserOptions: {
    ecmaVersion: 'latest' //校验ECMA最新版本
  }
}

这段代码 require('@rushstack/eslint-patch/modern-module-resolution')

问题背景在大型的 JavaScript 或 TypeScript 项目中,特别是使用了多包(monorepo)结构的项目,依赖管理可能会变得相当复杂。这种情况下,ESLint 的默认模块解析

这是一个由 Rush Stack 提供的补丁,用于改进 ESLint 的模块解析逻辑。它主要解决了两类问题:

  • 依赖查找:在多包结构中,node_modules 目录可能不仅仅位于项目的根目录,还可能在各个子包中也有。这个补丁改进了对 node_modules 的搜索逻辑,使其能够在这种环境中更准确地解析依赖。

  • 插件和配置解析:在使用 ESLint 的过程中,你可能会引用一些第三方插件或预定义的配置。这个补丁确保 ESLint 可以正确地找到并应用这些资源,即使在复杂的项目结构中。

要使用这个补丁,你需要在项目的 ESLint 配置文件(通常是 .eslintrc.js)的顶部添加以下代码:

javascript
require('@rushstack/eslint-patch/modern-module-resolution');

这样,当 ESLint 运行时,它会使用这个补丁改进的模块解析逻辑,而不是默认的逻辑。

这个补丁特别适用于以下几种场景

  • 使用 Yarn Workspaces 管理依赖的项目。
  • 使用 Rush.js 或 Lerna 这样的多包管理工具。
  • 在一个大型项目中,有多个嵌套的 node_modules 目录。

通过应用这个补丁,你可以避免因模块解析问题导致的一系列常见错误,如 "ESLint 插件未找到" 或 "配置未找到" 等。

希望这能让你对 @rushstack/eslint-patch/modern-module-resolution 有更深入的了解!有其他问题,随时问我。

具体参考

说明

在之前章节中说过 解释器 和冲突,但在项目搭建生成中并没有看到 用来解决 eslint 和 prettier 冲突的插件,这是因为在 @vue/eslint-config-prettier 依赖解决了 eslint 和 prettier 的冲突,所以在项目中不需要再次安装了。

关于vue 的解释器配置 参考在 plugin:vue/vue3-essential

配置vscode

在项目的 .vscode/settings.json 配置文件中写好了自动格式化规则,当保存时候 就可以采取 Prettier 来进行格式化

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"
  }
}

使用git 钩子

每个人开发环境都不同,不能保证每个人都遵守 这些提交规则,因此在实际开发中也会对 git hooks 做一些校验保证项目的规范,这里具体的可以参考git限制提交

整体可以归纳总结

安装 husky 来接管 git hooks ,直接去改动git hook是不明智因为改动本地的钩子是无法同步到远程仓库的git 钩子上因此可以使用 Husky 是一个 Git hooks 工具,它允许你在项目中配置钩子脚本

bash
npm install -D husky

初始化 husky

bash
npx husky-init

pre-commit (提交前钩子),在执行真正的提交操作之前运行的钩子当我们执行 git commit 命令提交代码时,Git会在实际进行提交操作之前触发 pre-commit 钩子,这个阶段用来检查代码将代码格式化最好阶段

但这个阶段一般只需要对暂存的文件进行格式化,因此需要 lint-staged 只检测暂存区的代码lint,会阻止提交,以便你有机会修复这些问题

bash
npm install lint-staged --save-dev

注册运行暂存检查的指令 npm pkg set scripts.lint-staged="lint-staged"

json
// change 1: 配置lint-staged指令
"scripts": {
    // 新增这一行
    "lint-staged": "lint-staged",
    ...
},

配置lint-staged的具体任务 在package.json 文件中

  • 如果您已经在 ESLint 配置中集成了 Prettier(通过使用 eslint-plugin-prettiereslint-config-prettier),那么您只需要运行 eslint --fix。这样,Prettier 的格式化规则也会被应用,无需再单独运行 prettier --write

  • ESLint 主要用于检查 JavaScript、TypeScript 和现代 JavaScript 框架(如 React 和 Vue)的代码。它不是设计用来检查 JSON、Markdown 或其他非-JavaScript 文件的,因此除了这类文件依旧采用的是 prettier --write 检测

json
// change 2: 配置lint-staged的具体任务
{
  "lint-staged": {
    "*.{js,jsx,ts,tsx,vue}": "eslint --fix",
    "*.{scss,less,styl,html}": [
      "stylelint --fix",
      "prettier --write"
    ],
    "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": "prettier --write --parser json",
    "package.json": "prettier --write",
    "*.md": "prettier --write"
  }
}

lint-staged 指令配置到 .husky/pre-commit 钩子中

bash
npx husky add .husky/pre-commit "npx lint-staged"

commit-msg(提交信息钩子)为了能规范大家git 提交信息这里需要使用,我们可以通过commit lint来限制提交,安装 @commitlint/config-conventional@commitlint/cli

  • @commitlint/config-conventional:这个包主要用于定义和配置 Conventional Commits 规范,规定了提交消息的格式和规则,但它本身不会执行验证

  • @commitlint/cli:这个包是一个命令行工具,用于在 Git 提交时验证提交消息是否符合规范@commitlint/cli 实际执行验证操作,检查提交消息是否符合 @commitlint/config-conventional 中定义的规范。

shell
npm i @commitlint/config-conventional @commitlint/cli -D

安装完成后可以在 commitlint.config.js文件,配置 commitlint ,我们告诉 commitlint 在验证提交信息时应该使用 @commitlint/config-conventional 规范配置中定义的规则

js
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      [
        '新功能', // 添加新功能
        '修复', // 修复 bug
        '文档', // 文档变更
        '样式', // 样式变更
        '重构', // 代码重构
        '性能', // 性能优化
        '测试', // 添加或修改测试代码
        '构建', // 构建过程或工具变动
        '配置', // 配置文件变动
        '版本', // 版本号变更
        '回滚', // 代码回滚
        '其他' // 其他变更
      ]
    ],
    'type-case': [0], // 类型大小写不作要求
    'type-empty': [0], // 类型不能为空
    'subject-max-length': [2, 'always', 100], // 主题最大长度为 100
    'subject-case': [0], // 主题大小写不作要求
    'subject-empty': [2, 'never'], // 主题不能为空
    'body-max-line-length': [2, 'always', 100], // 详细描述每行最大长度为 100
    'footer-max-line-length': [2, 'always', 100] // 关联问题每行最大长度为 100
  }
};

使用husky生成commit-msg文件,验证提交信息

shell
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"

新的问题每次都让开发在提交git 时候按照标准规范提交代码实际是一件麻烦的事,我们可以使用一个工具:Commitizen,这里直接推荐使用 czg

shell
npm install -D czg

配置模板

在文件 .commitlintrc.js

js
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

const scopes = fs
  .readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })
  .filter((dirent) => dirent.isDirectory())
  .map((dirent) => dirent.name.replace(/s$/, ''));

// precomputed scope
const scopeComplete = execSync('git status --porcelain || true')
  .toString()
  .trim()
  .split('\n')
  .find((r) => ~r.indexOf('M  src'))
  ?.replace(/(\/)/g, '%%')
  ?.match(/src%%((\w|-)*)/)?.[1]
  ?.replace(/s$/, '');

/** @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',
        'perf',
        'style',
        'docs',
        'test',
        'refactor',
        'build',
        'ci',
        'chore',
        'revert',
        'wip',
        'workflow',
        'types',
        'release',
      ],
    ],
  },
  prompt: {
    /** @use `yarn commit :f` */
    alias: {
      f: 'docs: fix typos',
      r: 'docs: update README',
      s: 'style: update code format',
      b: 'build: bump dependencies',
      c: 'chore: update config',
    },
    customScopesAlign: !scopeComplete ? 'top' : 'bottom',
    defaultScope: scopeComplete,
    scopes: [...scopes, 'mock'],
    allowEmptyIssuePrefixs: false,
    allowCustomIssuePrefixs: false,

    // English
    typesAppend: [
      { value: 'wip', name: 'wip:      work in process' },
      { value: 'workflow', name: 'workflow: workflow improvements' },
      { value: 'types', name: 'types:    type definition file changes' },
    ],

    // 中英文对照版
    // 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:     新增功能' },
    //   { value: 'fix', name: 'fix:      修复缺陷' },
    //   { value: 'docs', name: 'docs:     文档变更' },
    //   { value: 'style', name: 'style:    代码格式' },
    //   { value: 'refactor', name: 'refactor: 代码重构' },
    //   { value: 'perf', name: 'perf:     性能优化' },
    //   { value: 'test', name: 'test:     添加疏漏测试或已有测试改动' },
    //   { value: 'build', name: 'build:    构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
    //   { value: 'ci', name: 'ci:       修改 CI 配置、脚本' },
    //   { value: 'revert', name: 'revert:   回滚 commit' },
    //   { value: 'chore', name: 'chore:    对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
    //   { value: 'wip', name: 'wip:      正在开发中' },
    //   { value: 'workflow', name: 'workflow: 工作流程改进' },
    //   { value: 'types', name: 'types:    类型定义文件修改' },
    // ],
    // emptyScopesAlias: 'empty:      不填写',
    // customScopesAlias: 'custom:     自定义',
  },
};

package.json 配置

js
"scripts": {
	    "commit": "czg"
}

排除校验文件

.prettierignore

bash
/dist/*
/html/*
.local
/node_modules/**
**/*.svg
**/*.sh
/public/*

.eslintignore

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

.stylelintignore

shell
/node_modules/*
/dist/*
/html/*
/public/*

参考

团队协作(一)—— 你不知道的 ESLint + Prettier

Released under the MIT License.