前端项目规范配置

1,279 阅读13分钟

创建项目

使用 vite 创建项目

pnpm create vite my-vue-app --template vue-ts

cd my-vue-app
pnpm install
pnpm run dev

路径别名、端口

设置项目路径别名、端口号

pnpm i @types/node -D

vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

function pathResolve(dir: string) {
  return resolve(process.cwd(), dir)
}

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: [
      {
        find: /\/@\//,
        replacement: pathResolve('src') + '/',
      },
      {
        find: /\/#\//,
        replacement: pathResolve('types') + '/',
      },
    ],
  },
  server: {
    host: '0.0.0.0',
    port: 4399,
    open: true,
  },
})

tsconfig.app.json

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "/@/*": [
        "src/*"
      ],
      "/#/*": [
        "types/*"
      ]
    }
  },
}

修改后,记得重启 VSCode

npm 镜像

在项目根目录下,新建 .npmrc 文件

registry=https://registry.npmmirror.com

ESLint

安装依赖

npm init @eslint/config

image.png

运行成功之后,会自动在项目根目录下,创建 .eslintrc.cjs 文件,默认安装的 eslint 版本是最新的,由于最新的 eslint 生态还未完善,这里进行降级处理,安装 eslint@8

pnpm i eslint@8 -D

配置ESLint

配置文件如下: .eslintrc.cjs

module.exports = {
  // 停止在其父级目录中寻找 eslint 规则
  root: true,
  // 指定运行的环境
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  // 继承推荐的语法校验规则
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:vue/vue3-recommended',
  ],
  overrides: [
    {
      env: {
        node: true,
      },
      files: ['.eslintrc.{js,cjs}'],
      parserOptions: {
        sourceType: 'script',
      },
    },
  ],
  // 解析器配置
  parserOptions: {
    ecmaVersion: 'latest',
    parser: '@typescript-eslint/parser',
    sourceType: 'module',
  },
  // 使用的插件
  plugins: ['@typescript-eslint', 'vue'],
  // 规则
  // "off" 或 0 - 关闭规则
  // "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出)
  // "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
  rules: {
    // 在这里添加或覆盖规则
    // 使用单引号
    quotes: ['error', 'single'],
    // 不允许使用未声明的变量
    'no-undef': 'error',
    // 禁止未使用的变量
    'no-unused-vars': 'error',
    // 禁止使用 var 变量
    'no-var': 'error',
  },
}

在项目根目录下,创建 .eslintignore 文件,避免这些文件或目录进行 eslint 校验,配置如下: .eslintignore

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

配置脚本

添加 script 脚本进行 eslint 校验修复 package.json

 "scripts": {
    "lint:eslint": "eslint --max-warnings 0  \"{src,mock}/**/*.{vue,ts,tsx}\" --fix"
  },

测试 eslint 是否生效

// main.ts
var a = '1'

运行脚本进行校验修复

pnpm run lint:eslint
# eslint 会进行修复,将 var 变量改为 const,并且报错如下:
# error  'a' is assigned a value but never used  no-unused-vars
# error  'a' is assigned a value but never used  @typescript-eslint/no-unused-vars

Prettier

安装依赖

pnpm i prettier -D

安装 prettier-plugin-packagejson 插件对  package.json 中的 key 进行合理的化的排序

pnpm i prettier-plugin-packagejson -D

配置Prettier

在项目根目录下,创建 .prettierrc.js 文件,配置如下: .prettierrc.js

export default {
  // 一行最多 120 字符
  printWidth: 120,
  // 使用 2 个空格缩进
  tabWidth: 2,
  // 不使用缩进符,而使用空格
  useTabs: false,
  // 行尾需要有分号
  semi: false,
  // 使用单引号
  singleQuote: true,
  // 对象的 key 仅在必要时用引号
  quoteProps: 'as-needed',
  // jsx 不使用单引号,而使用双引号
  jsxSingleQuote: false,
  // 末尾需要有逗号
  trailingComma: 'none',
  // 大括号内的首尾需要空格
  bracketSpacing: true,
  // jsx 标签的反尖括号需要换行
  bracketSameLine: false,
  // 箭头函数,只有一个参数的时候,也需要括号
  arrowParens: 'always',
  // 每个文件格式化的范围是文件的全部内容
  rangeStart: 0,
  rangeEnd: Infinity,
  // 不需要写文件开头的 @prettier
  requirePragma: false,
  // 不需要自动在文件开头插入 @prettier
  insertPragma: false,
  // 使用默认的折行标准
  proseWrap: 'preserve',
  // 根据显示样式决定 html 要不要折行
  htmlWhitespaceSensitivity: 'css',
  // vue 文件中的 script 和 style 内缩进
  vueIndentScriptAndStyle: true,
  // 换行符使用 lf
  endOfLine: 'lf',
  // 格式化嵌入的内容
  embeddedLanguageFormatting: 'auto',
  // 使用 prettier-plugin-packagejson 插件合理排序 package.json 中 key 的顺序
  plugins: ['prettier-plugin-packagejson']
}

在项目根目录下,创建 .prettierignore 文件,避免这些文件或目录进行 prettier 代码格式化,配置如下: .prettierignore

dist
.local
.output.js
node_modules

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

public
.npmrc

*-lock.yaml

配置VSCode

vscode 进行配置,实现编辑器保存时,根据 prettier 配置文件自动格式化,在项目根目录下创建 .vscode/settings.json 文件,配置如下: .vscode/settings.json

{
  // 保存时格式化文件
  "editor.formatOnSave": true,
  // tab 缩进 2 个字符
  "editor.tabSize": 2,
  // 默认格式化程序
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  // 保存代码时的操作
  "editor.codeActionsOnSave": {
    // 保存时移除未使用的 import 声明
    // 按引用深度排序合并 import 声明
    "source.organizeImports": "explicit"
  }
}

配置脚本

添加 script 脚本进行 prettier 格式化 package.json

"scripts": {
  "lint:prettier": "prettier --write  \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\""
}

ESLint 与 Prettier 冲突

eslintprettier 中的一些规则会进行冲突,使用如下插件进行解决,具体配置如下:

  • eslint-config-prettier:关闭 eslint 中与 prettier 相互冲突的规则
  • eslint-plugin-prettier:赋予 eslint 用 prettier 格式化代码的能力
pnpm i eslint-config-prettier eslint-plugin-prettier -D

.eslintrc.cjs 修改 .eslintrc.cjs 文件,新增 plugin:prettier/recommended 这条规则

module.exports = {
  extends: [
    'plugin:prettier/recommended'
  ],
}

EditorConfig

为统一不同编辑器之间的代码风格,在项目跟目录下新建 .editorconfig 文件 .editorconfig

# editorconfig.org
root = true

# 适用于所有文件的通用配置
[*]
# 指定使用空格进行代码缩进
indent_style = space
# 指定缩进的空格数为 2
indent_size = 2
# 指定行尾字符为 lf
end_of_line = lf
# 字符编码格式为 utf-8
charset = utf-8
# 自动去除行尾的多余空格
trim_trailing_whitespace = true
# 在文件末尾自动添加一个新行
insert_final_newline = true

[*.md]
# 对于 markdown 文件,不自动去除行尾空格
trim_trailing_whitespace = false 

Stylelint

stylelint 是一个强大、先进的 css 代码检查器,可以帮助你规避 css 代码中的错误并保持一致的编码风格

安装依赖

安装与 less相关的依赖

pnpm i stylelint stylelint-config-standard stylelint-config-html stylelint-config-recess-order  stylelint-config-standard-less less postcss-html postcss-less -D

安装与 scss相关的依赖

pnpm i stylelint stylelint-config-standard stylelint-config-html stylelint-config-recess-order stylelint-config-recommended-vue stylelint-config-standard-scss sass-embedded postcss-html postcss-scss -D

配置Stylelint

在项目根目录下创建 .stylelintrc.cjs 文件,相关配置如下: .stylelintrc.cjs

module.exports = {
  root: true,
  // 继承规则配置
  extends: [
    // 继承 Stylelint 中标准的配置
    'stylelint-config-standard',
    // 继承 Stylelint 中适合于 vue 中 template 样式格式化的配置
    'stylelint-config-html/vue',
    /* // 继承 Stylelint 中标准的适合 scss 的配置
    'stylelint-config-standard-scss',
    // 继承 Stylelint 中推荐的适合于 vue 中 scss 样式格式化的配置
    'stylelint-config-recommended-vue/scss', */
    // 继承 Stylelint 中标准的适合 less 的配置
    'stylelint-config-standard-less',
    // 继承 Stylelint 中以 recess 的方式对 CSS 属性进行排序的配置
    'stylelint-config-recess-order'
  ],
  // 对继承的规则配置进行重写覆盖
  overrides: [
    // 使用 PostCSS 的 html 语法解析器解析匹配文件中的代码
    {
      files: ['**/*.(css|html|vue)'],
      customSyntax: 'postcss-html'
    },
    // 使用 PostCSS 的 less 语法解析器解析匹配文件中的样式代码
    {
      files: ['.less', '**/*.less'],
      customSyntax: 'postcss-less'
    },
    // 使用 PostCSS 的 scss 语法解析器解析匹配文件中的样式代码
    {
      files: ['*.scss', '**/*.scss'],
      customSyntax: 'postcss-scss'
    }
  ],
  /**
   * 自定义 Stylelint 规则
   * null  => 关闭该规则
   * always => 必须
   */
  rules: {
    // 为样式属性关键字的属性值指定小写或大写,"lower"(属性值必须小写)|"upper"(属性值必须大写)
    'value-keyword-case': null,
    // 关闭禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器
    'no-descending-specificity': null,
    // 要求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)"
    'function-url-quotes': 'always',
    // 关闭禁止存在空的源码,即样式代码块中可以为空
    'no-empty-source': null,
    // 关闭强制选择器类名的格式
    'selector-class-pattern': null,
    // 关闭禁止未知的样式属性,即允许使用未知的样式属性
    'property-no-unknown': null,
    // 大括号之前必须有一个空格或不能有空白符,always —— 大括号 {} 之前必须有一个空格
    // 'block-opening-brace-space-before': 'always',
    // 关闭禁止使用带有浏览器前缀的属性值,如 --webkit-box,即允许使用
    'value-no-vendor-prefix': null,
    // 关闭禁止使用带有浏览器前缀的属性,如 -webkit-mask,即允许使用
    'property-no-vendor-prefix': null,
    // 禁止使用未知的伪类选择器
    'selector-pseudo-class-no-unknown': [
      // 不允许使用未知的伪类选择器
      true,
      {
        // 忽略属性,对于配置在 ignorePseudoClasses 中的伪类选择器允许使用
        // 修改element默认样式的时候能使用到
        ignorePseudoClasses: ['global', 'deep']
      }
    ],
    'selector-pseudo-element-no-unknown': [
      true,
      {
        ignorePseudoElements: ['v-deep']
      }
    ]
  },
  // 配置不需要 Stylelint 检查的文件类型
  ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts', '**/*.json', '**/*.md', '**/*.yaml']
}

在项目根目录下,创建 .stylelintignore 文件,避免这些文件或目录进行 stylelint 代码格式化,配置如下: .stylelintignore

dist
public

配置脚本

添加 script 脚本进行 stylelint 格式化

"scripts": {
  "lint:stylelint": "stylelint \"**/*.{vue,css,less,scss}\" --fix"
},

配置VSCode

在项目根目录下的 .vscode/settings.json 文件中进行如下配置: .vscode/settings.json

{
  "editor.codeActionsOnSave": {
    "source.fixAll.stylelint": "explicit",
    "source.fixAll": "explicit",
  },
  // stylelint配置
  "stylelint.enable": true,
  // 关闭编辑器内置样式检查(避免与stylelint冲突)
  "css.validate": false,
  "less.validate": false,
  "scss.validate": false,
  "stylelint.validate": ["css", "less", "postcss", "scss", "sass", "vue"]
}

Husky

husky 是一个让 git hooks 变的更为简单的一个工具,在提交或推送代码的时候,能自动化检查提交信息、检查代码和运行测试

安装依赖

pnpm i husky -D

配置Husky

husky init 命令会简化了项目中的 husky 设置。它会在 .husky/ 中创建 pre-commit 脚本,并更新 package.json 中的 prepare 脚本

pnpm exec husky init

package.json

"scripts": {
  "prepare": "husky"
},

配置脚本

在项目根目录下,创建 .husky/pre-commit 文件,进行 git commit 命令时,就会触发 pre-commit 中的脚本,配置如下: .husky/pre-commit

pnpm run lint:eslint && pnpm run lint:prettier && pnpm run lint:stylelint

LintStaged

在前面配置了 husky,由于 pre-commit 文件里的脚本校验的是整个项目,当项目较大时,会比较耗时,这时候就需要用到 lint staged 这个工具,它只对 git 暂存区里的文件进行检查,这样检查体量的就少

安装依赖

pnpm i lint-staged -D

配置LintStaged

package.json 文件中进行如下配置: package.json

{
  "lint-staged": {
    "*.{js,jsx,ts,tsx}": [
      "prettier --write",
      "eslint --fix"
    ],
    "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
      "prettier --write--parser json"
    ],
    "package.json": [
      "prettier --write"
    ],
    "*.vue": [
      "prettier --write",
      "eslint --fix",
      "stylelint --fix"
    ],
    "*.{scss,less,styl,html}": [
      "prettier --write",
      "stylelint --fix"
    ],
    "*.md": [
      "prettier --write"
    ]
  }
}

配置脚本

更新 .husky/pre-commit 文件中的脚本命令 .husky/pre-commit

pnpm exec lint-staged

Commitlint

commitlint 是一个 git commit 校验约束工具,能够约束提交格式

安装依赖

pnpm i @commitlint/cli @commitlint/config-conventional -D

提交格式

git commit -m type(scope?): subject
body?
footer?

# type 类型
feat:新增功能
fix:修复bug
pref:性能优化
style:代码格式
docs:文档变更
test:增加或修改测试
refactor:代码重构(即不是新增功能,也不是修改bug的代码变动)
build:构建流程或外部依赖变更(如升级 npm 包、修改打包配置等)
chore:构建过程或辅助工具和库的变动
revert:回滚 commit
wip:正在开发中
workflow:工作流程变更
types:类型定义文件修改

git commit 包括三部分:headerbodyfooter

  1. header 包括:
    1. type:指定 commit 提交的类型
    2. scope:影响的范围(可选)
    3. subject:commit 简要描述
  2. body(可选):对 commit 的详细描述,可以分成多行
  3. footer(可选):只用于代码版本不兼容变动、关闭 issue 以及特殊情况 revert

配置Commitlint

在项目根目录下,创建 commitlint.config.js 文件,进行如下配置: commitlint.config.js

export default {
  // 忽略某些提交信息,提交信息包含了 init,则不进行检查
  ignores: [(commit) => commit.includes('init')],
  // 集成了其他的规则集
  extends: ['@commitlint/config-conventional'],
  // 指定输出格式化器
  formatter: '@commitlint/format',
  /***
   * 规则配置
   * 0:禁用规则 1:警告 2:错误
   * always:某项规则必须满足,不满足则会触发错误或警告
   * never:某些规则不能被满足,满足则会触发错误或警告
   */
  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', // 修复 bug
        'perf', // 性能优化
        'style', // 代码格式
        'docs', // 文档变更
        'test', // 添加或修改测试
        'refactor', // 代码重构
        'build', // 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)
        'ci', // 修改 CI 配置、脚本
        'chore', // 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)
        'revert', // 回滚 commit
        'wip', // 正在开发中
        'workflow', // 工作流程变更
        'types' // 类型定义文件修改
      ]
    ]
  }
}

配置脚本

在项目根目录下,创建 .husky/commit-msg 文件,设置如下脚本命令 .husky/commit-msg

pnpm dlx commitlint --edit $1

Commitizen

commitizen 是一个帮助编写规范的提交信息工具,使用 commitizen 提交时,提供了一种交互式的方式来生成符合约定格式的提交信息

安装依赖

pnpm i commitizen -D

安装适配器

安装 cz-git 适配器去更换 commitizen 命令行工具的交互方式插件

pnpm i cz-git -D

配置适配器

修改 package.json 添加 config 指定使用的适配器

{
  "config": {
    "commitizen":{
      "path": "node_modules/cz-git"
    }
  }
}

commitlint.config.js 文件中添加自定义配置 commitlint.config.js

export default {
  // 忽略某些提交信息,提交信息包含了 init,则不进行检查
  ignores: [(commit) => commit.includes('init')],
  // 集成了其他的规则集
  extends: ['@commitlint/config-conventional'],
  // 指定输出格式化器
  formatter: '@commitlint/format',
  /***
   * 规则配置
   * 0:禁用规则 1:警告 2:错误
   * always:某项规则必须满足,不满足则会触发错误或警告
   * never:某些规则不能被满足,满足则会触发错误或警告
   */
  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', // 修复 bug
        'perf', // 性能优化
        'style', // 代码格式
        'docs', // 文档变更
        'test', // 添加或修改测试
        'refactor', // 代码重构
        'build', // 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)
        'ci', // 修改 CI 配置、脚本
        'chore', // 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)
        'revert', // 回滚 commit
        'wip', // 正在开发中
        'workflow', // 工作流程变更
        'types' // 类型定义文件修改
      ]
    ]
  },
  prompt: {
    alias: { fd: 'docs: fix typos' },
    messages: {
      type: '选择你要提交的类型 :',
      scope: '选择一个提交范围(可选):',
      customScope: '请输入自定义的提交范围 :',
      subject: '填写简短精炼的变更描述 :\n',
      body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
      breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
      footerPrefixesSelect: '选择关联issue前缀(可选):',
      customFooterPrefix: '输入自定义issue前缀 :',
      footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
      confirmCommit: '是否提交或修改commit ?'
    },
    types: [
      { value: 'feat', name: 'feat:     ✨  新增功能', emoji: ':sparkles:' },
      { value: 'fix', name: 'fix:      🐛  修复bug', emoji: ':bug:' },
      { value: 'docs', name: 'docs:     📝  文档变更', emoji: ':memo:' },
      { value: 'style', name: 'style:    💄  代码格式', emoji: ':lipstick:' },
      {
        value: 'refactor',
        name: 'refactor: ♻️   代码重构',
        emoji: ':recycle:'
      },
      { value: 'perf', name: 'perf:     ⚡️  性能提升', emoji: ':zap:' },
      {
        value: 'test',
        name: 'test:     ✅  测试相关',
        emoji: ':white_check_mark:'
      },
      {
        value: 'build',
        name: 'build:    📦️  构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)',
        emoji: ':package:'
      },
      { value: 'ci', name: 'ci:       🎡  修改 CI 配置、脚本', emoji: ':ferris_wheel:' },
      {
        value: 'chore',
        name: 'chore:    🔨  对构建过程或辅助工具和库的更改(不影响源文件、测试用例)',
        emoji: ':hammer:'
      },
      { value: 'revert', name: 'revert:   ⏪️  回退代码', emoji: ':rewind:' },
      { value: 'wip', name: 'wip:      🚧  正在开发中', emoji: ':construction:' },
      { value: 'workflow', name: 'workflow: 👷  工作流程改进', emoji: ':construction_worker:' },
      { value: 'types', name: 'types:    🏷️   类型定义文件修改', emoji: ':label:' }
    ],
    useEmoji: true
  }
}

配置脚本

添加 script 脚本代替 git commit 命令

"scripts": {
  "commit": "git-cz"
},

运行如下命令就会出现交互提示,根据消息提示进行填写即可

git add .
pnpm run commit

image.png

git.gif

至此,一个前端项目规范就配置完成啦🚀🎉🎉