工程化代码检查不是挑刺,是在救未来的你!!!

59 阅读4分钟

1.背景

随着团队成员的不断增加以及项目规模的逐步扩大,代码维护的复杂度也随之提升。为了提升代码的可读性、可维护性以及团队协作效率,团队需要统一代码风格和开发规范。

在实际开发过程中,常出现以下问题

  • 同一项目中存在多种代码风格,影响阅读和理解;
  • 提交未经格式化的代码,增加 review 成本;
  • 不一致的命名、缩进、空格、分号等细节,降低代码质量
  • 测试环境的console忘记删除,变量声明未使用等

2.工具

  • ESLint:统一代码语法和逻辑规范,防止潜在错误;
  • Prettier:统一代码格式,提升代码可读性;
  • Husky + lint-staged:在提交前自动检查并格式化代码,防止低质量代码进入代码仓库;
  • Commitlint:规范 Git 提交信息,提升版本管理效率
  • ls-lint: 文件名称检查

3.eslint代码检查

1.安装eslint

npm install eslint--save-dev

2.初始化eslint配置文件

npm init @eslint/config

image.png

3.生成eslint.config.ts文件


  const js = require('@eslint/js');
  const globals = require('globals');
  const pluginVue = require('eslint-plugin-vue');
  const tsPlugin = require('@typescript-eslint/eslint-plugin');
  const tsParser = require('@typescript-eslint/parser');
  const eslintConfigPrettier = require('eslint-config-prettier/flat');
  const { defineConfig } = require('eslint/config');

  module.exports = defineConfig([
    {
      ignores: ['node_modules/**', 'dist/**', '**/*.min.js', 'package-lock.json', 'tsconfig.json', '**/*.json', '**/*.md',],
    },
    {
      files: ['**/*.{js,ts,mjs,cjs,vue}'],
      plugins: { '@typescript-eslint': tsPlugin, js },
      languageOptions: {
        parser: tsParser,
        parserOptions: {
          ecmaVersion: 'latest',
          sourceType: 'module',
          project: ['./tsconfig.eslint.json'], // 确保 tsconfig.json 存在
          tsconfigRootDir: __dirname,
        }, 
        globals: { ...globals.browser, ...globals.node } 
      },
      rules: {
        'no-console': 'warn',
        semi: ['warn', 'always'],
        quotes: ['error', 'single'],
        eqeqeq: ['error', 'always'],
        'no-useless-escape': 'off',
      },
    },
    {
      files: ['**/*.vue'],
      languageOptions: {
        parser: tsParser,
        parserOptions: {
          ecmaVersion: 'latest',
          sourceType: 'module',
          project: ['./tsconfig.eslint.json'],
          tsconfigRootDir: __dirname,
          extraFileExtensions: ['.vue'],
        },
        globals: {
          ...globals.browser,
          ...globals.node,
        },
      },
      ...pluginVue.configs['flat/essential'],
    },
    eslintConfigPrettier,
  ]);

4.package的script中配置eslint命令

"lint"``: ``"eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix"

5.测试

  • 测试代码

image.png

  • 执行npm run lint

image.png

4.prettier代码风格工具

1.安装prettier 和 eslint-config-prettier

eslint-config-prettier,ESLint 将自动禁用与 Prettier 冲突的规则,确保代码风格一致。

npm i prettier eslint-config-prettier --save-dev

2.根目录下创建.prettierrc.json文件

{
  "printWidth": 600,

  "tabWidth": 2,

  "semi": true,

  "singleQuote": true,

  "jsxSingleQuote": true
}

3.根目录增加.prettierignore文件

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

4.package.json中增加prettier修复命令

"format": "prettier --write .",

5.ls-lint文件命名规范

1.安装@ls-lint/ls-lint

npm install @ls-lint/ls-lint --save-dev

2.根目录中新增.ls-lint.yml文件

ls:
  core/**/hooks:
    .ts: regex:^use[A-Z][a-zA-Z0-9]*$
    .js: regex:^use[A-Z][a-zA-Z0-9]*$

  composables/**:
    .ts: regex:^use[A-Z][a-zA-Z0-9]*$
    .js: regex:^use[A-Z][a-zA-Z0-9]*$

  pages/**:
    .vue: regex:^[([a-z0-9-]+)]$|^([a-z0-9-]+)$

  .vue: kebab-case # Vue 组件文件名
  .ts: kebab-case # 普通 TypeScript 文件
  .js: kebab-case # 普通 JavaScript 文件

ignore:
  - node_modules
  - dist
  - .git
  - .nuxt
  - .vscode
  - .github

3.package.json文件中新增script命令

"ls-lint": "ls-lint",

4.安装 @typescript-eslint/eslint-plugin 和 @typescript-eslint/parser

在eslint.config.js中修改Vue文件校验


  const js = require('@eslint/js');
  const globals = require('globals');
  const pluginVue = require('eslint-plugin-vue');
  const tsPlugin = require('@typescript-eslint/eslint-plugin');
  const tsParser = require('@typescript-eslint/parser');
  const eslintConfigPrettier = require('eslint-config-prettier/flat');
  const { defineConfig } = require('eslint/config');

  module.exports = defineConfig([
    {
      ignores: ['node_modules/**', 'dist/**', '**/*.min.js', 'package-lock.json', 'tsconfig.json', '**/*.json', '**/*.md',],
    },
    {
      files: ['**/*.{js,ts,mjs,cjs,vue}'],
      plugins: { '@typescript-eslint': tsPlugin, js },
      languageOptions: {
        parser: tsParser,
        parserOptions: {
          ecmaVersion: 'latest',
          sourceType: 'module',
          project: ['./tsconfig.eslint.json'], // 确保 tsconfig.json 存在
          tsconfigRootDir: __dirname,
        }, 
        globals: { ...globals.browser, ...globals.node } 
      },
      rules: {
        'no-console': 'warn',
        semi: ['warn', 'always'],
        quotes: ['error', 'single'],
        eqeqeq: ['error', 'always'],
        'no-useless-escape': 'off',
      },
    },
    {
      files: ['**/*.vue'],
      languageOptions: {
        parser: tsParser,
        parserOptions: {
          ecmaVersion: 'latest',
          sourceType: 'module',
          project: ['./tsconfig.eslint.json'],
          tsconfigRootDir: __dirname,
          extraFileExtensions: ['.vue'],
        },
        globals: {
          ...globals.browser,
          ...globals.node,
        },
      },
      ...pluginVue.configs['flat/essential'],
    },
    eslintConfigPrettier,
  ]);

6.Git规范

安装Husky进行git hook钩子的控制,根据pre-commit和commit-msg两个git钩子,提交之前进行代码检查

1.安装husky进行git hook钩子控制

npm install husky --save-dev

2.初始化husky

npx husky init

生成.husky文件夹,在pre-commit文件中配置commit执行前的脚本

npx lint-staged

image.png

3.lint-stage

在代码提交之前进行代码检测,确保不规范代码进入远程仓库,但是整个项目的检测过程是缓慢的,检测结果可能是无关的,我们提交代码只希望对本次新增代码进行检查,lint-staged是用来控制只检测暂存区代码的工具库

npm install lint-staged --save-dev

在package.json中添加

  "lint-staged": {
    "*.{js,ts,vue}": "eslint --fix",
    "*.{js,ts,vue,json,css,scss,md}": "prettier --write",
  }

执行commit会拦截相应的报错代码

image.png

4.commit-msg

commitlint 搭配 husky 的 commit-msg 钩子,每次commit时候都会由commitlint对commit message进行校验,若不符合规则,则commit失败,并提示相应的报错信息

  • 安装commitlint
npm install --save-dev @commitlint/{cli,config-conventional}
  • 根目录下创建commitlint.config.js文件,根据commit日志标准,增加配置信息

module.exports = {
  parserPreset: {
    parserOpts: {
      headerPattern: /^[(w+)]((.+)): (.+)$/,
      headerCorrespondence: ['type', 'scope', 'subject'],
    },
  },
  rules: {
    'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'debug', 'revert', 'hotfix']],
    'scope-empty': [2, 'never'],
    'subject-empty': [2, 'never'],
    'header-max-length': [2, 'always', 100],
  },
};

  • husky文件夹中创建commi-msg文件,增加命令
npx --no -- commitlint --edit "$1"

以上commit-msg钩子配置完成,此时尝试不符合规范的commit message提交,终端会提示报错信息

image.png