代码检查
使用eslint + prettier + stylelint自动化代码检查,保证代码质量、代码格式和css格式的统一
代码质量检查:eslint
eslint可以对代码中的语法错误、变量未使用、代码风格不一致等问题进行检查
使用:
安裝eslint
安装相关插件:
-
eslint-plugin-vue
检查vue文件 -
eslint-plugin-prettier
、eslint-config-prettier
解决prettier与eslint的规则冲突 -
eslint-plugin-import
对导入导出语法的校验 -
eslint-plugin-unused-imports
自动删除未使用的导入 -
typescript-eslint/parser
解析ts语法 -
eslint-config-airbnb
使用较多的代码风格规范
配置.eslintrc.js文件
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
'vue/setup-compiler-macros': true,
},
parser: 'vue-eslint-parser',
plugins: ['@typescript-eslint', 'import', 'prettier', 'unused-imports'],
extends: [
'airbnb-base',
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
parserOptions: {
tsconfigRootDir: 'src',
parser: '@typescript-eslint/parser',
project: ['../tsconfig.json'],
ecmaVersion: 'latest',
sourceType: 'module',
extraFileExtensions: ['.vue'],
ecmaFeatures: {
jsx: true,
tsx: true,
},
},
rules: {
'prettier/prettier': ['error', { endOfLine: 'auto' }],
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'arrow-body-style': 'off',
'arrow-parens': ['warn', 'as-needed'],
'brace-style': ['warn', '1tbs', { allowSingleLine: true }],
camelcase: 0,
'comma-dangle': ['warn', 'always-multiline'],
complexity: 'off',
curly: ['warn', 'multi-line'],
'import/order': [
'warn',
{
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
pathGroups: [
{
pattern: '@/**',
group: 'internal',
},
],
'newlines-between': 'always',
alphabetize: {
order: 'asc',
},
},
],
'no-bitwise': 'off',
'no-invalid-this': 'off',
'no-underscore-dangle': 0,
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'vue/max-attributes-per-line': 'off',
'vue/first-attribute-linebreak': ['error', { singleline: 'beside' }],
'vue/v-slot-style': ['error', 'shorthand'],
'vue/html-self-closing': ['error', { html: { void: 'always' } }],
'vue/singleline-html-element-content-newline': 'off',
'vue/no-mutating-props': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/require-default-prop': 'off',
'vue/multi-word-component-names': 'off',
'no-shadow': 'off',
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'vue/no-setup-props-destructure': 'off',
'unused-imports/no-unused-imports': 'warn',
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
'import/prefer-default-export': 'off',
},
};
代码风格统一:prettier
prettier专注于统一和美化代码的外观, 可以自动调整代码的缩进、换行、引号等
使用:
安裝prettier
配置.prettierrc.js
module.exports = {
printWidth: 120, // 一行最多 120 字符
tabWidth: 2, // 使用 2 个空格缩进
singleQuote: true, // 使用单引号
trailingComma: 'all', // 末尾需要有逗号
arrowParens: 'avoid', // 箭头函数,只有一个参数的时候,不需要括号
endOfLine: 'auto', // 换行符
htmlWhitespaceSensitivity: 'ignore', // 忽略空白
};
css风格统一:stylelint
stylelint可以对css进行校验和自动格式化,包括换行、属性顺序等格式
使用:
安装stylelint
安装插件:
-
stylelint-config-rational-order
基础配置 -
stylelint-config-prettier
解决prettier与eslint的规则冲突 -
stylelint-order
、stylelint-config-rational-order
属性书写排序 -
stylelint-config-standard-scss
、stylelint-config-standard-vue
处理scss
配置stylelint.config.js
module.exports = {
plugins: ['stylelint-order', 'stylelint-scss'],
extends: [
'stylelint-config-standard-scss',
'stylelint-config-prettier',
'stylelint-config-rational-order',
'stylelint-config-standard-vue/scss',
],
rules: {
'selector-pseudo-class-no-unknown': null,
'selector-pseudo-element-no-unknown': null,
'scss/at-extend-no-missing-placeholder': null,
'declaration-block-trailing-semicolon': null,
'selector-class-pattern': null,
'custom-property-empty-line-before': null,
'no-descending-specificity': null,
'string-quotes': null,
'declaration-block-no-duplicate-properties': [
true,
{
ignore: ['consecutive-duplicates-with-different-values'],
},
],
},
};
在package.json中增加脚本:
"lint": "eslint --ext .ts,.tsx,.vue ./src",
"lint:style": "stylelint \"**/*.{css,scss,sass,vue}\"",
"lint:all": "pnpm lint && pnpm lint:style",
执行相应脚本即可对代码进行检查
配合vscode插件:
在vscode中安装扩展插件ESLint、Prettier、Stylelint后,可以对不合规范的代码报错提示,同时保存文件后可以自动格式化代码
lint-staged
通过lint-staged插件实现代码校验时只扫描暂存区的文件而不是全盘扫描
安装lint-staged
配置lint-staged.config.js
module.exports = {
'src/**/*.{ts,tsx}': ['prettier', 'eslint --max-warnings 0'],
'src/**/*.{scss,css}': ['prettier', 'stylelint'],
'src/**/*.vue': ['prettier', 'eslint --max-warnings 0', 'stylelint'],
};
在package.json中添加脚本:
"scripts": {
"lint:staged": "pnpm lint-staged",
}
执行pnpm lint:staged后会对暂存区的文件进行代码检查
commit校验
在提交代码通常需要执行代码质量检查和提交信息规范检查
husky
husky是一个git hooks管理工具,可以在提交代码时触发不同的钩子,执行不同的脚本
安装步骤:
首先安装husky;
之后在package.json中增加脚本:"prepare": "husky install"
,prepare时npm的一个钩子,在执行 npm install
命令时触发。配置后,当我们执行npm install时,会自动执行husky install
,然后在根目录生成.husky目录
设置git hooks
pre-commit
在提交代码前执行,进行代码规范校验
在husky目录下新建pre-commit文件,添加以下内容:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
pnpm lint:staged
commit-msg
规范git commit中的message
使用commitlint检验工具
安装@commitlint/cli
、@commitlint/config-conventional
根目录新建commitlint.config.js:
// commitlint.config.js
module.exports = {
extends: ["@commitlint/config-conventional"],
rules: [], // 可选,自定义rules,覆盖@commitlint/config-conventional的配置
};
之后再执行commit如果提交信息不符合规定则会终止提交。
使用commitizen在commit时提供带提示的交互式命令行
安装commitizen、@commitlint/cz-commitlint
在package.json中添加:
"scripts": {
"commit": "git-cz"
},
"config": {
"commitizen": {
"path": "@commitlint/cz-commitlint"
}
}
在提交代码时,将命令git commit替换成npm commit
通过以上方式实现了代码校验和提交信息校验的功能,但有个问题需要优化:执行npm commit后会先书写提交信息,之后再对代码进行校验,如果校验失败则又要重新书写提交信息,这样会导致重复提交的烦恼
解决方案:
在husky中创建hook文件:prepare-commit-msg,这个hook在提交(commit)消息生成后,提交编辑器打开之前执行,配置:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
if [ -n "$SKIP_PREPARE_COMMIT_MSG" ]
then
echo 'skip-prepare-commit-msg'
else
exec < /dev/tty && pnpm git-cz --hook || true
fi
之后不再需要使用pnpm commit,直接使用git commit,会先进行代码校验,校验通过后会触发这个钩子,然后自动执行pnpm git-cz打开交互式命令行。
如果需要使用pnpm commit命令,之前的package.json需要修改一下:
"scripts": {
"commit": "cross-env SKIP_PREPARE_COMMIT_MSG=1 git-cz"
},
CI/CD
使用群组Runner,方便共享
编写makefile自动化构建命令
COMMIT=$(shell git rev-parse --short HEAD)
DATE=$(shell date +%Y%m%d%H%M)
install:
pnpm install
build:
pnpm build
tar:
rm -f fe-*.tar.gz && tar --exclude=".DS_Store" -zcvf fe-${DATE}-${COMMIT}.tar.gz ./dist
编写.gitlab-ci.yml
stages:
- build
build:
stage: build
script:
- make install
- make build
- make tar
rules:
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == 'main' || $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^dev.*$/
tags:
- dev-k8s