前端项目规范自动化

310 阅读7分钟

搭建前端项目规范,可以让团队协作的项目遵循统一的风格,便于维护和美观易读,再加上自动化的流程能让规范的遵循更容易,也更高效,降低管理心智,以下我整理了主流前端项目的规范自动化方案,最终将形成如下的项目结构:

my-project/
├── .husky/ -------------------------------- git拦截
│   ├── commit-msg ------------------------- 执行commitlint
│   ├── commit-wizard.js ------------------- commit message辅助生成脚本
│   ├── pre-commit ------------------------- 执行lint-staged
│   └── prepare-commit-msg ----------------- 执行commit message辅助生成工具或脚本
├── .vscode/ ------------------------------- vscode开发环境规范
│   └── settings.json
├── .editorconfig -------------------------- IDE编码样式规范
├── eslint.config.js ----------------------- 前端代码检查与规范
├── .prettierrc.json ----------------------- 编写风格规范
├── .commitlintrc.js ----------------------- commit message规范
├── .lintstagedrc.json --------------------- 自动化规范修复
├── .cz-config.js -------------------------- commit message辅助生成工具
├── package.json
└── tsconfig.json -------------------------- Typescript规范

IDE规范

.editorconfig

在项目根目录下创建 .editorconfig 文件,可以约束文件在不同的编辑器和IDE之间定义和维护一致的编码样式

# http://editorconfig.org
root = true[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true[*.md]
trim_trailing_whitespace = false

.vscode

通过vscode配置文件。可以让团队在各自的电脑上使用IDE进行开发时,都使用统一IDE配置环境,例如插件的作用范围使用规则等。

在项目根目录下创建 .vscode 文件夹,下面再创建一个 settings.json 文件:

{
  // 在保存时自动进行代码格式化
  "editor.formatOnSave": true,
  // 设置默认的代码格式化工具为 Prettier
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  // 在保存时运行 ESLint 插件进行代码修复
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  // 针对 JavaScript 文件,禁用保存时的自动格式化,通过 ESLint 进行修复
  "[javascript]": {
    "editor.formatOnSave": false
  },
  // 针对 JavaScript React 文件,禁用保存时的自动格式化,通过 ESLint 进行修复
  "[javascriptreact]": {
    "editor.formatOnSave": false
  },
  // 针对 TypeScript 文件,禁用保存时的自动格式化,通过 ESLint 进行修复
  "[typescript]": {
    "editor.formatOnSave": false
  },
  // 针对 Vue 文件,设置默认的代码格式化工具为 ESLint
  "[vue]": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  }
}

代码规范

TypeScript

在项目中集成ts可以提高代码的可读性,也自带了风格和代码的约束与静态检查,写出容错更高的代码。

在项目中集成ts

npm install -D typescript

如果你使用的是Vite构建项目,直接配置tsconfig.json即可,如果是webpack构建项目还需要安装babel预设

npm install -D @babel/preset-typescript

然后在你项目的babel配置 .babelrc.js 中使用这个预设

// 根目录.babelrc.js,或者写入你的webpack配置中
{
  // ...其他配置
  "presets": [
    // ... 其他配置
    "@babel/preset-typescript"
  ]
} 

tsconfig.json配置

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "skipLibCheck": true,
    "outDir": "dist",
    "rootDir": "src",
    "declaration": true,
    "sourceMap": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Eslint

eslint可以检查js,ts,jsx,tsx文件的静态错误和规范,通过在根目录目录创建eslint.config.js配置文件,旧版的eslint是.eslintrc.json。

安装eslint和需要的插件

npm install -D \
  eslint \
  eslint-config-prettier \
  eslint-plugin-prettier \
  @typescript-eslint/eslint-plugin \
  @typescript-eslint/parser 

项目根目录创建配置文件 eslint.config.js

import eslint from "@eslint/js";
import tsPlugin from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
import prettierPlugin from "eslint-plugin-prettier";
import prettierConfig from "eslint-config-prettier";
import globals from "globals";
​
export default [
  // 使用 ESLint 推荐配置
  eslint.configs.recommended,
​
  // 使用 @typescript-eslint 推荐配置
  {
    files: ["**/*.ts", "**/*.tsx"],
    languageOptions: {
      parser: tsParser, // 指定 TypeScript 解析器
      ecmaVersion: "latest",
      sourceType: "module",
    },
    plugins: {
      "@typescript-eslint": tsPlugin,
    },
    rules: {
      "@typescript-eslint/no-explicit-any": "off", // 关闭 any 类型警告
      // 禁用基础规则,启用 TypeScript 增强规则
      "no-unused-vars": "off",
      "@typescript-eslint/no-unused-vars": [
        "error",
        {
          argsIgnorePattern: "^_", // 忽略以 _ 开头的参数
          varsIgnorePattern: "^_", // 忽略以 _ 开头的变量
          caughtErrorsIgnorePattern: "^_", // 忽略以 _ 开头的错误变量
        },
      ],
    },
  },
​
  // 使用 Prettier 配置
  {
    plugins: {
      prettier: prettierPlugin,
    },
    rules: {
      ...prettierConfig.rules,
      "prettier/prettier": "error", // 启用 Prettier 规则
    },
  },
​
  // 全局规则
  {
    languageOptions: {
      globals: {
        ...globals.node,
      },
    },
    rules: {
      "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", // 生产环境禁用 console
      "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", // 生产环境禁用 debugger
    },
  },
​
  // 排除文件
  {
    ignores: ["node_modules", "dist"],
  },
];

风格规范

Prettier

prettier则是在书写风格上的规范约束,他不像eslint那样检查代码,而是规范编写的习惯,且不局限于js文件,对所有文件均可生效。

安装

npm install -D prettier 

在项目根目录创建 perttier.json 配置文件

{
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": false,
  "trailingComma": "all",
  "bracketSpacing": true,
  "arrowParens": "always",
  "endOfLine": "auto"
}

git拦截

husky提供git钩子,可以监听git指令对指定环节进行拦截,从而满足一些额外的定制化处理。

安装husky

npx husky install
npm pkg set scripts.prepare="husky install"

执行以上指令后,项目根目录就会新增.husky文件夹,并在package.json中增加了prepare脚本,这样husky遍安装好可以投入使用,钩子的具体使用请看下面的内容。

git缓存

lint-staged可以自动执行eslint和prettier,在提交代码之前,进行代码检查的自动化处理,不仅检查代码也会修复代码问题,不过建议在提交之前手动执行lint-stage,以免代码调整后出现bug。除此之外,lint-stage还有git暂存区的diff功能,这样可以让代码的检查和修复只作用于本次git提交有变化的文件,提高规范处理的效率。

.lintstagedrc.json 文件配置:

{
  "*.{js,jsx,ts,tsx}": [
    "prettier --write",
    "eslint --fix --max-warnings=0"
  ],
  "*.{css,scss,less,md,json}": [
    "prettier --write"
  ]
}

然后添加husky的pre-commit钩子,自动执行lint-staged:

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

commit规范

即便有了husky等git拦截,仍然挡不住有一些通过脚本或工具库等绕过husky监听进行提交的行为,而使用 commitlint 工具,可以在git commit的最后环节进行message的校验,进一步防范不符合规范的意外提交。

安装

npm install -D @commitlint/cli @commitlint/config-conventional

在项目根目录下创建.commitlintrc.js 配置文件

export default {
  extends: ["@commitlint/config-conventional"],
  rules: {
    "type-enum": [
      2,
      "always",
      [
        "feat", // 新功能
        "fix", // bug修复
        "docs", // 文档变更
        "style", // 样式/格式
        "refactor", // 重构(不增加功能)
        "perf", // 性能优化
        "test", // 测试用例
        "chore", // 构建/工具
        "revert", // 回滚
        "release", // 发布
      ],
    ],
    "subject-case": [0], // 不限制subject大小写
  },
};
​

然后在husky中增加commit-msg钩子,执行commitlint:

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

commit辅助

手动输入commit太繁琐且易错,通过设计交互的形式辅助编写,更准确也更高效,你可以选择使用工具 Commitizen 快速配置,也可以手动编写脚本高定制可控:

维度Commitizen手写脚本
灵活性依赖适配器,修改成本较高完全可控,可快速响应业务变化
依赖复杂度需安装 cz-* 系列工具链仅需 husky + inquirer
学习曲线需理解适配器配置逻辑直接使用 Node.js 开发逻辑
定制化能力受限于适配器扩展机制可自由设计交互流程和校验规则
维护成本依赖社区维护适配器自主维护,问题定位直接
启动速度需要加载额外依赖轻量级,启动更快

手写脚本

.husky文件夹下创建脚本文件 commit-wizard.js

然后创建husky钩子 prepare-commit-msg ,并写入执行交互脚本的指令,使用以下命令指令可以快速创建:

npx husky add .husky/prepare-commit-msg "exec < /dev/tty && node .husky/commit-wizard.js"

commit-wizard.js 脚本参考:

#!/usr/bin/env node
import fs from "fs";
import inquirer from "inquirer";
import chalk from "chalk";
import { execSync } from "child_process";
​
/** 通过分支名称获取默认的commit type */
const getBranchInfo = () => {
  const branch = execSync("git branch --show-current").toString().trim();
​
  return {
    issue: branch.match(/^(fix|feat)/(\w+-\d+)/)?.[2],
    type: branch.match(/^(feat|fix|hotfix)/)?.[1],
  };
};
​
// 获取 Git 提交信息文件路径
const commitMsgFile = process.argv[2]
// 定义 Git Commit类型,尽量符合规范
const commitTypes = [
  { name: "✨ 新功能 (feat)", value: "feat" },
  { name: "🐛 Bug修复 (fix)", value: "fix" },
  { name: "📚 文档变更 (docs)", value: "docs" },
  { name: "🎨 代码样式 (style)", value: "style" },
  { name: "♻️ 代码重构 (refactor)", value: "refactor" },
  { name: "⚡️ 性能优化 (perf)", value: "perf" },
  { name: "✅ 测试用例 (test)", value: "test" },
  { name: "🔧 构建工具 (chore)", value: "chore" },
  { name: "⚡️ 发布版本 (release)", value: "release" },
  { name: "⏪ 回滚提交 (revert)", value: "revert" },
];
​
async function run() {
  try {
    const answers = await inquirer.prompt([
      {
        type: "list",
        name: "type",
        message: "选择提交类型:",
        choices: commitTypes,
        pageSize: 10,
        default: () => getBranchInfo().type || "feat",
      },
      {
        type: "input",
        name: "scope",
        message: ({ type }) => `输入影响范围 (${type}):`,
        validate: (input) => !!input.trim() || "作用域不能为空!",
      },
      {
        type: "input",
        name: "subject",
        message: "输入简短描述:",
        validate: (input) => {
          if (!input.trim()) return "描述不能为空!";
          if (input.length > 72) return "不超过72个字符!";
          return true;
        },
      },
      {
        type: "editor",
        name: "body",
        message: "输入详细说明 (可选):",
        wait: true,
      },
      {
        type: "confirm",
        name: "isBreaking",
        message: "包含破坏性变更?",
        default: false,
      },
      {
        type: "input",
        name: "footer",
        message: "输入关联的 Issue (如 #123):",
        default: () => getBranchInfo().issue || "",
        when: (answers) => !answers.isBreaking,
      },
    ]);
​
    // 构建提交信息
    const message = [
      `${answers.type}(${answers.scope}): ${answers.subject}`,
      answers.body,
      answers.isBreaking ? `BREAKING CHANGE: ${answers.body}` : "",
      answers.footer ? `Closes ${answers.footer}` : "",
    ]
      .filter(Boolean)
      .join("\n\n");
​
    // 写入提交信息文件
    fs.writeFileSync(commitMsgFile, message, "utf-8");
    console.log(chalk.green("\n✅ 提交信息已生成!"));
  } catch (err) {
    console.error(chalk.red("❌ 生成失败:", err));
    process.exit(1);
  }
}
​
run();

Commitizen

Commitizen可以使用封装好的工具,选择适配器 cz-conventional-changelog 免配置快速按主流的开源规范生成commit,但是我更喜欢用 cz-customizable 适配器自定义,只需一个配置文件即可,省去了自己写脚本的麻烦。所以以下是cz-customizable的演示

在项目中安装

npm install -D commitizen cz-customizable

配置文件 .cz-config.js 参考

module.exports = {
  types: [
    { value: 'feat',     name: 'feat:     新功能' },
    { value: 'fix',      name: 'fix:      Bug修复' },
    { value: 'docs',     name: 'docs:     文档变更' },
    { value: 'style',    name: 'style:    代码样式' },
    { value: 'refactor', name: 'refactor: 代码重构' },
    { value: 'perf',     name: 'perf:     性能优化' },
    { value: 'test',     name: 'test:     测试相关' },
    { value: 'chore',    name: 'chore:    构建/工具' },
    { value: 'revert',   name: 'revert:   回滚提交' }
  ],
  scopes: [
    { name: 'user' },
    { name: 'order' },
    { name: 'payment' },
    { name: 'config' }
  ],
  messages: {
    type: '选择提交类型:',
    scope: '选择影响范围:',
    customScope: '输入自定义范围:',
    subject: '输入简短描述 (72字符内):\n',
    body: '输入详细说明 (可选):\n',
    breaking: '列出破坏性变更 (可选):\n',
    footer: '关联的 Issue (如 #123):\n',
    confirmCommit: '确认提交信息?'
  },
  allowCustomScopes: true,
  allowBreakingChanges: ['feat', 'fix'],
  skipQuestions: ['footer'],
  subjectLimit: 72
}

配置 package.json

{
  "config": {
    "commitizen": {
      "path": "node_modules/cz-customizable"
    },
    "cz-customizable": {
      "config": ".cz-config.js"
    }
  }
}

husky增加prepare-commit-msg钩子

npx husky add .husky/prepare-commit-msg "exec < /dev/tty && node_modules/.bin/git-cz --hook || true"

总结

以上便是完整的前端项目规范自动化的建设方案,通过这套方案的集成,你的项目在多人协作中都能呈现出统一的风格和规范,并且配置完成后,都可以作为基建复用到其他项目中,以后便能统一所有项目的风格,形成你公司的前端规范。