使用 vue-cli5.0 + vue3 + ts + less + prettier + eslint + commitlint + stylelint 构建项目
目录
5、根目录添加.eslintignore文件,忽略某些文件Eslint检测
7、根目录添加.prettierignore,忽略某些文件的优化
9、根目录添加.stylelintignore文件,忽略某些文件的CSS优化
10、webpack热更新利用.prettierrc.js文件及stylelintrc.js文件配置,保存自动优化代码格式
1、使用vue-cli 5.0生成项目
选择以上选项以后,自动生成代码,生成如下代码结构:
2、关联远程仓库
3、添加commitlint 校验git提交信息
执行完vue add commitlint 后,项目代码有以下变化
项目根目录自动添加commitlint.config.js文件
package.json文件自动添加,变化如下:
手动git提交规范如下:
1. 提交格式
git commit -m <type>[optional scope]: <description>
2. 常用的type类别
type :用于表明我们这次提交的改动类型,是新增了功能?还是修改了测试代码?又或者是更新了文档?总结以下 11 种类型:
• build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
• ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
• docs:文档更新
• feat:新增功能
• fix:bug 修复
• perf:性能优化
• refactor:重构代码(既没有新增功能,也没有修复 bug)
• style:不影响程序逻辑的代码修改(修改空白字符,补全缺失的分号等)
• test:新增测试用例或是更新现有测试
• revert:回滚某个更早之前的提交
• chore:不属于以上类型的其他类型(日常事务)
optional scope:一个可选的修改范围。用于标识此次提交主要涉及到代码中哪个模块。
description:一句话描述此次提交的主要内容,做到言简意赅。
例如:
git commit -m 'feat: 增加 xxx 功能'
git commit -m 'bug: 修复 xxx 功能'
提交失败案例
提交成功案例
通过script脚本提交,执行yarn cz,可能会出现如下报错:
此时只需要执行yarn add right-pad -D ,把right-pad模块加载进来即可,如下:
再次执行yarn cz
根据提示,进行规范提交
4、添加Eslint校验代码规范,提交拦截
在项目根目录中的lint-staged.config.js文件,配置如下:
module.exports = {
'*.{js,jsx,ts,tsx,vue}': [
'vue-cli-service lint ./src --fix',
'git add'
],
};
package.json文件修改husky配置,添加 pre-commit: "lint-staged" ,如下:
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
根据个人项目需求,自由配置.eslintrc.js文件,在这里简单配置如下:
module.exports = {
root: true,
env: {
node: true,
},
extends: [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/typescript/recommended",
"plugin:prettier/recommended",
],
parserOptions: {
ecmaVersion: 2020,
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'prettier/prettier': 'off',
/**
* 代码中可能的错误或逻辑错误
*/
'no-cond-assign': ['error', 'always'], // 禁止条件表达式中出现赋值操作符
'no-constant-condition': [
'error',
{
checkLoops: true
}
], // 禁止在条件中使用常量表达式
'no-control-regex': ['error'], // 禁止在正则表达式中使用控制字符
'no-dupe-args': ['error'], // 禁止 function 定义中出现重名参数
'no-dupe-keys': ['error'], // 禁止对象字面量中出现重复的 key
'no-duplicate-case': ['error'], // 禁止出现重复的 case 标签
'no-empty': [
'error',
{
allowEmptyCatch: true
}
], // 禁止出现空语句块
'no-empty-character-class': ['error'], // 禁止在正则表达式中使用空字符集
'no-ex-assign': ['error'], // 禁止对 catch 子句的参数重新赋值
'no-extra-boolean-cast': ['error'], // 禁止不必要的布尔转换
'no-extra-semi': ['error'], // 禁止不必要的分号
'no-func-assign': ['warn'], // 禁止对 function 声明重新赋值
'no-inner-declarations': ['error'], // 禁止在嵌套的块中出现变量声明或 function 声明
'no-invalid-regexp': [
'error',
{
allowConstructorFlags: []
}
], // 禁止 RegExp 构造函数中存在无效的正则表达式字符串
'no-irregular-whitespace': ['error'], // 禁止在字符串和注释之外不规则的空白
'no-obj-calls': ['error'], // 禁止把全局对象作为函数调用
'no-regex-spaces': ['error'], // 禁止正则表达式字面量中出现多个空格
'no-sparse-arrays': ['error'], // 禁用稀疏数组
'no-unexpected-multiline': ['error'], // 禁止出现令人困惑的多行表达式
'no-unsafe-finally': ['error'], // 禁止在 finally 语句块中出现控制流语句
'no-unsafe-negation': ['error'], // 禁止对关系运算符的左操作数使用否定操作符
'use-isnan': ['error'], // 要求使用 isNaN() 检查 NaN
/**
* 最佳实践
*/
'default-case': ['error'], // 要求 switch 语句中有 default 分支
'dot-notation': ['error'], // 强制尽可能地使用点号
eqeqeq: ['warn'], // 要求使用 === 和 !==
'no-caller': ['error'], // 禁用 arguments.caller 或 arguments.callee
'no-case-declarations': ['error'], // 不允许在 case 子句中使用词法声明
'no-empty-function': ['error'], // 禁止出现空函数
'no-empty-pattern': ['error'], // 禁止使用空解构模式
'no-eval': ['error'], // 禁用 eval()
'no-global-assign': ['error'], // 禁止对原生对象或只读的全局对象进行赋值
'no-magic-numbers': [
'error',
{
ignoreArrayIndexes: true
}
], // 禁用魔术数字
'no-redeclare': [
'error',
{
builtinGlobals: true
}
], // 禁止重新声明变量
'no-self-assign': [
'error',
{
props: true
}
], // 禁止自我赋值
'no-unused-labels': ['error'], // 禁用出现未使用过的标
'no-useless-escape': ['error'], // 禁用不必要的转义字符
radix: ['error'], // 强制在parseInt()使用基数参数
/**
* 变量声明
*/
'no-delete-var': ['error'], // 禁止删除变量
'no-undef': ['error'], // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到
'no-unused-vars': ['error'], // 禁止出现未使用过的变量
'no-use-before-define': ['error'], // 禁止在变量定义之前使用它们
/**
* ECMAScript 6
*/
'arrow-spacing': [
'error',
{
before: true,
after: true
}
], // 强制箭头函数的箭头前后使用一致的空格
'no-var': ['error'], // 要求使用 let 或 const 而不是 var
'object-shorthand': ['error', 'always'], // 要求或禁止对象字面量中方法和属性使用简写语法
'prefer-arrow-callback': [
'error',
{
allowNamedFunctions: false
}
] // 要求回调函数使用箭头函数
},
};
重启项目,执行yarn serve,在src/components/HelloWorld.vue文件添加如下代码,以便测试eslint提交拦截功能
添加完以上代码后,执行提交命令,如下:
出现eslint拦截报错,未提交成功,代码eslint提交拦截功能添加成功
5、根目录添加.eslintignore文件,忽略某些文件Eslint检测
代码如下:
# #开头为注释
/node_modules
/dist
/public
/src/assets
6、添加Prettier,修复eslint报错
在根目录添加.prettierrc.js文件,根据项目需要,进行配置,在这里,简单配置如下:
module.exports = {
// 超过80就换行
printWidth: 80,
// tab缩进大小,默认为2
tabWidth: 2,
// 使用tab缩进,默认false
useTabs: false,
// 使用分号,默认true
semi: false,
// 使用单引号, 默认false,(在jsx中配置无效, 默认都是双引号)
singleQuote: true,
// 行尾逗号,默认none,可选(none|es5|all),es5 包括es5中的数组、对象,all 包括函数对象等所有可选
trailingComma: 'none',
// 对象中的空格 默认true,true: { foo: bar },false: {foo: bar}
bracketSpacing: true,
// JSX标签闭合位置 默认false
jsxBracketSameLine: false,
// 箭头函数参数括号 默认avoid 可选(avoid|always),avoid 能省略括号的时候就省略 例如x => x ,always 总是有括号
arrowParens: 'avoid',
// 不使用prettier格式化的文件填写在项目的.prettierignore文件中
ignorePath: '.prettierignore',
// 在jsx中把'>' 是否单独放一行
jsxBracketSameLine: false
}
在lint-staged.config.js文件,添加‘prettier --write ./src’,如下:
module.exports = {
'*.{js,jsx,ts,tsx,vue}': [
'vue-cli-service lint ./src --fix',
'prettier --write ./src',
'git add'
],
};
此时,在项目中稍作代码示例修改,提交代码,项目就会根据.prettierrc.js文件的配置进行优化
若是在每次执行git add . 时出现如下提示
可执行 git config core.autocrlf false 即可
7、根目录添加.prettierignore,忽略某些文件的优化
代码如下
/node_modules
/dist
/public
/src/assets
在.prettierrc.js文件中设置,忽略文件路径属性
// 不使用prettier格式化的文件填写在项目的.prettierignore文件中
ignorePath: '.prettierignore',
在package.json的script脚本添加
"scripts": {
"format": "prettier . --write",
},
执行npm run format 即可测试忽略文件是否有效
8、添加Stylelint,校验CSS样式,提交拦截
根目录添加.stylelintrc.js文件
module.exports = {
// extends: ['stylelint-config-standard', 'stylelint-config-prettier', 'stylelint-config-html', "stylelint-config-standard-scss", 'stylelint-config-recommended-vue'],
extends: [
'stylelint-config-standard',
'stylelint-config-prettier',
'stylelint-config-html'
],
plugins: ['stylelint-order', 'stylelint-less'],
customSyntax: 'postcss-html',
ignorePath: '.stylelintignore',
rules: {
indentation: 2,
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep']
}
],
'number-leading-zero': 'never',
'no-descending-specificity': null,
'font-family-no-missing-generic-family-keyword': null,
'selector-type-no-unknown': null,
'at-rule-no-unknown': null,
'no-duplicate-selectors': null,
'no-empty-source': null,
'selector-pseudo-class-no-unknown': [
true,
{ ignorePseudoClasses: ['global'] }
],
'max-nesting-depth': null,
'max-line-length': null,
'selector-max-compound-selectors': null,
'selector-no-qualifying-type': null,
'selector-class-pattern': null,
'function-parentheses-newline-inside': null,
'color-function-notation': 'legacy',
'alpha-value-notation': 'number',
'order/properties-order': [
'position',
'top',
'right',
'bottom',
'left',
'z-index',
'display',
'flex-wrap',
'justify-content',
'align-items',
'float',
'clear',
'overflow',
'overflow-x',
'overflow-y',
'padding',
'padding-top',
'padding-right',
'padding-bottom',
'padding-left',
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'width',
'min-width',
'max-width',
'height',
'min-height',
'max-height',
'font-size',
'font-family',
'font-weight',
'text-justify',
'text-align',
'text-indent',
'text-overflow',
'text-decoration',
'white-space',
'color',
'background',
'background-position',
'background-repeat',
'background-size',
'background-color',
'background-clip',
'border',
'border-style',
'border-width',
'border-color',
'border-top-style',
'border-top-width',
'border-top-color',
'border-right-style',
'border-right-width',
'border-right-color',
'border-bottom-style',
'border-bottom-width',
'border-bottom-color',
'border-left-style',
'border-left-width',
'border-left-color',
'border-radius',
'opacity',
'filter',
'list-style',
'outline',
'visibility',
'box-shadow',
'text-shadow',
'resize',
'transition'
]
}
}
package.json 的 dev 添加如下包:
"devDependencies": {
"stylelint": "^13.13.1",
"stylelint-config-html": "^1.0.0",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-standard": "^22.0.0",
"stylelint-less": "^1.0.3",
"stylelint-order": "^4.1.0",
},
根目录文件lint-staged.config文件做如下修改:
module.exports = {
'*.{js,jsx,ts,tsx,vue}': [
'vue-cli-service lint ./src --fix',
'prettier --write ./src',
'git add'
],
'*.{html,vue,css,sass,scss,less}': ['stylelint --fix', 'git add']
}
重启服务,提交代码,就会自动优化代码
9、根目录添加.stylelintignore文件,忽略某些文件的CSS优化
代码如下
/node_modules
/dist
/src/components/HelloWord.less
# .stylelintignore
# 旧的不需打包的样式库
*.min.css
# 其他类型文件
*.js
*.jpg
*.woff
# 测试和打包目录
/test/
/dist/
/lib/
.stylelint.js 文件添加忽略文件路径属性
ignorePath: '.stylelintignore',
此时重启服务,提交代码,自动忽略所设置的文件代码优化
10、webpack热更新利用.prettierrc.js文件及stylelintrc.js文件配置,保存自动优化代码格式
在package.json中,添加如下包:
"devDependencies": {
"prettier-webpack-plugin": "^1.2.0",
"stylelint-webpack-plugin": "^3.1.1"
},
在vue.config.js文件,添加如下配置:
const { defineConfig } = require('@vue/cli-service')
const StylelintPlugin = require('stylelint-webpack-plugin')
const PrettierPlugin = require('prettier-webpack-plugin')
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
plugins: [
// 实时按照.stylelintrc.js文件格式化代码
new StylelintPlugin({
files: ['**/*.{html,vue,css,less}'], // 按需配置
fix: true,
cache: true,
emitError: true,
failOnError: false
}),
// 实时按照.prettierrc.js文件格式化代码
new PrettierPlugin()
]
}
})
重启服务,在编辑代码保存时,webpack热更新构建,优化代码格式