背景
前端规范管理,eslint、stylelint辅助管理。
ESLint、Stylelint、Prettier、EditorConfig这些检测工具的工作原理都比较类似,不外乎对象实例化-编译Javascript-遍历AST检测-输出检测结果这四步流程
- ESLint:检测代码质量和代码风格;
- StyleLint:检测样式代码质量和代码风格;
- Prettier:检测代码风格;(ESLint、StyleLint调和剂,解决重复的规则【Error Loop】)
- EditorConfig:统一不同IDE之间的配置差异,例如一个编辑器行缩进使用的是Tab,另一个编辑器使用的则是空格Space;
规范配置步骤
- vue项目完整的规范配置,分为以下四步:
- 核心规则配置:各检测工具必要的规则配置文件,没有它们检测工具无法执行,如.eslintrc文件。
- 命令行脚本配置:package.json的script属性配置执行脚本,开发人员手动执行命令,如npm run lint。
- 开发环境配置:webpack开发环境构建配置中,添加开发环境运行时检测插件,类似于启动器,运行时自动执行各自的检测工具进行检测。
- 编辑器配置:VSCode编辑器安装插件并配置属性,实时进行检测。
第一步:
1. eslint配置 - .eslintrc.js
module.exports = {
root: true,
env: {
node: true,
browser: true,
},
extends: ['plugin:vue/essential', 'airbnb-base', 'plugin:prettier/recommended'],
parserOptions: {
parser: 'babel-eslint',
ecmaFeatures: {
jsx: true,
},
},
plugins: ['import'],
settings: {
// 别名
'import/resolver': {
alias: {
map: [['@', './src/']],
extensions: ['.js', '.vue'],
},
},
},
rules: {
'func-names': 0,
'import/extensions': 0,
'no-unused-expressions': 0,
/**
* 导入语句前不允许有任何非导入语句
*/
'import/first': 'error',
/**
* 禁止重复导入模块
*/
'import/no-duplicates': 'error',
/**
* 禁止使用 let 导出
*/
'import/no-mutable-exports': 'warn',
/**
* 禁用导入的模块时使用 webpack 特有的语法(感叹号)
*/
'import/no-webpack-loader-syntax': 'warn',
/**
* 当只有一个导出时,必须使用 export default 来导出
*/
'import/prefer-default-export': 'off',
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: true,
},
],
'no-plusplus': [
'error',
{
allowForLoopAfterthoughts: true,
},
],
'import/no-dynamic-require': 0,
'global-require': 0,
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
},
};
1.1eslint忽略文件 .eslintignore
dist/**
es/**
lib/**
**/node_modules
2. stylelint配置
module.exports = {
// processors: ['stylelint-processor-html'],
// extends: ['stylelint-config-tx 替换tx','css-properties-sorting', 'stylelint-config-prettier'],
extends: ['css-properties-sorting', 'stylelint-config-prettier'],
plugins: ['stylelint-order'], // stylelint-order是CSS属性排序插件
rules: {
// "color-hex-case": "lower", // 颜色值为小写字母(stylelint-config-standard)
// "color-no-invalid-hex": true, // 颜色值不能为无效值(stylelint-config-standard)
'font-family-name-quotes': 'always-where-recommended', // 字体系列中命名时带引号
'function-url-quotes': 'always', // 地址一定要写引号
// 'number-leading-zero': 'never', // 或分数低于1的数字是否需要前导零
'number-no-trailing-zeros': true, // 禁止在数量尾随零
// 'string-quotes': 'double', // 指定字串
'length-zero-no-unit': true, // 禁止单位零长度。
'value-keyword-case': 'lower', // 指定小写关键字的值
'value-list-comma-newline-after': 'always-multi-line', // 在值列表的逗号后指定一个换行符或禁止留有空格
'shorthand-property-no-redundant-values': true, // 不允许在简写属性冗余值
// "property-case": "lower", // 为属性指定小写(stylelint-config-standard)
'keyframe-declaration-no-important': true, // 不允许!important在关键帧声明
// "block-closing-brace-empty-line-before": "never", // 不允许关闭括号前空一行(stylelint-config-standard)
// "block-closing-brace-newline-after": "always", // 需要一个换行符关闭括号后的空白(stylelint-config-standard)
// "block-opening-brace-newline-after": "always-multi-line", // 开括号的块之后需要新的一行(stylelint-config-standard)
'selector-class-pattern': "^[a-z]+([a-z0-9]?|[a-z0-9(-_'% ]*[a-z0-9)])$", // 兼容stylelint的bug(less的mixin没处理好), 暂时先这样处理~~~指定一个模式类选择符,限制选择器名称写法
'selector-id-pattern': "^[a-z]+([a-z0-9]?|[a-z0-9(-_'% ]*[a-z0-9)])$", // 兼容stylelint的bug(less的mixin没处理好), 暂时先这样处理~~~指定一个模式,id选择器,限制选择器名称写法
'no-empty-source': null, // 不允许空的来源
'at-rule-no-unknown': null, // 不允许at-rules不明
// "indentation": 2, // 指定缩进(stylelint-config-standard)
'max-nesting-depth': [5, { severity: 'warning' }], // 允许嵌套的深度为5
'no-duplicate-selectors': true, // 不允许重复的选择器
// "no-eol-whitespace": true, // 不允许行尾空白(stylelint-config-standard)
// "no-invalid-double-slash-comments": true // 不允许双斜杠注释(/ /…)不支持CSS(stylelint-config-standard)
'order/order': [
// 指定声明块内的内容顺序
['custom-properties', 'declarations'],
],
// "declaration-block-properties-order": "alphabetical",
'order/properties-order': [
// 指定声明块内属性的字母顺序
'position',
'top',
'right',
'bottom',
'left',
'z-index',
'display',
'float',
'width',
'height',
'max-width',
'max-height',
'min-width',
'min-height',
'padding',
'padding-top',
'padding-right',
'padding-bottom',
'padding-left',
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'margin-collapse',
'margin-top-collapse',
'margin-right-collapse',
'margin-bottom-collapse',
'margin-left-collapse',
'overflow',
'overflow-x',
'overflow-y',
'clip',
'clear',
'font',
'font-family',
'font-size',
'font-smoothing',
'osx-font-smoothing',
'font-style',
'font-weight',
'hyphens',
'src',
'line-height',
'letter-spacing',
'word-spacing',
'color',
'text-align',
'text-decoration',
'text-indent',
'text-overflow',
'text-rendering',
'text-size-adjust',
'text-shadow',
'text-transform',
'word-break',
'word-wrap',
'white-space',
'vertical-align',
'list-style',
'list-style-type',
'list-style-position',
'list-style-image',
'pointer-events',
'cursor',
'background',
'background-attachment',
'background-color',
'background-image',
'background-position',
'background-repeat',
'background-size',
'border',
'border-collapse',
'border-top',
'border-right',
'border-bottom',
'border-left',
'border-color',
'border-image',
'border-top-color',
'border-right-color',
'border-bottom-color',
'border-left-color',
'border-spacing',
'border-style',
'border-top-style',
'border-right-style',
'border-bottom-style',
'border-left-style',
'border-width',
'border-top-width',
'border-right-width',
'border-bottom-width',
'border-left-width',
'border-radius',
'border-top-right-radius',
'border-bottom-right-radius',
'border-bottom-left-radius',
'border-top-left-radius',
'border-radius-topright',
'border-radius-bottomright',
'border-radius-bottomleft',
'border-radius-topleft',
'content',
'quotes',
'outline',
'outline-offset',
'opacity',
'filter',
'visibility',
'size',
'zoom',
'transform',
'box-align',
'box-flex',
'box-orient',
'box-pack',
'box-shadow',
'box-sizing',
'table-layout',
'animation',
'animation-delay',
'animation-duration',
'animation-iteration-count',
'animation-name',
'animation-play-state',
'animation-timing-function',
'animation-fill-mode',
'transition',
'transition-delay',
'transition-duration',
'transition-property',
'transition-timing-function',
'background-clip',
'backface-visibility',
'resize',
'appearance',
'user-select',
'interpolation-mode',
'direction',
'marks',
'page',
'set-link-source',
'unicode-bidi',
'speak',
],
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep'],
},
],
},
};
3. prettier配置 - prettier.config.js
module.exports = {
// 一行最多 120 字符
printWidth: 120,
// 使用 2 个空格缩进
tabWidth: 2,
// 不使用缩进符,而使用空格
useTabs: false,
// 行尾需要有分号
semi: true,
// 使用单引号
singleQuote: true,
// 对象的 key 仅在必要时用引号
quoteProps: 'as-needed',
// jsx 不使用单引号,而使用双引号
jsxSingleQuote: false,
// 末尾需要有逗号
trailingComma: 'all',
// 大括号内的首尾需要空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 箭头函数,只有一个参数的时候,也需要括号
arrowParens: 'always',
// 每个文件格式化的范围是文件的全部内容
rangeStart: 0,
rangeEnd: Infinity,
// 不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准
proseWrap: 'preserve',
// 根据显示样式决定 html 要不要折行
htmlWhitespaceSensitivity: 'css',
// vue 文件中的 script 和 style 内不用缩进
vueIndentScriptAndStyle: false,
// 换行符使用 lf
endOfLine: 'lf',
};
4. EditorConfig部分:
editorConfig的作用是专门抹平不同编辑器同一配置之间差异。比较神奇的是它并不需要项目配依赖且配置及其简单,只需要编辑器安装指定扩展插件以及项目配置文件.editorConfig即可。
- VSCode中安装插件:EditorConfig for VS Code
- 项目根目录下创建并配置.editorConfig:
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
依赖清单
// 依赖清单
[
// ESLint
eslint,
babel-eslint,
eslint-plugin-vue,
eslint-webpack-plugin, // 开发环境实时检测(可选
// StyleLint(可选)
stylelint,
stylelint-webpack-plugin, // 开发环境实时检测
stylelint-config-standard,
// Prettier(可选)
prettier,
eslint-config-prettier,
eslint-plugin-prettier,
stylelint-config-prettier
]
完整示例
// ESLint
"eslint": "^6.7.2",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-vue": "^6.2.2",
// StyleLint(可选)
"stylelint": "^13.12.0",
"stylelint-order": "^4.1.0",
// Prettier(可选)
"prettier": "^2.3.2",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.3.1",
"stylelint-config-prettier": "^8.0.2",
第二步 - 命令行脚本配置
在package.json文件的script脚本中配置
{
// 省略其余属性...
"script": {
"eslint-lint": "eslint --ext .js,.vue --fix src",
"stylelint-lint": "stylelint src/**/.css src/**/.vue src/**/.less --fix"
}
}
【有待争议的规则点】
vue相关
1、vue/html-self-closing 自关闭标签 2、vue/attributes-order 属性顺序 3、vue/attribute-hyphenation 属性需用连字符分割单词,(这里不建议,父子组件使用时,无法直接搜索)