前端团队代码风格统一规范实践
目标
-
自动格式化前端开发常见文件,实现团队代码风格统一
-
杜绝因格式问题导致的提交冲突,提高开发效率
-
统一配置,团队共享,实现同步
-
vscode会在每次文件保存同时自动格式化
-
ESLint 并不推荐任何编码风格,规则是自由的
通过 eslint + prettier + vetur + editorConfig 配合实现以下文件格式完全一致格式化
- vue-template、html
- vue-style、css/less/scss/stylus(todo)
- vue-script、js/ts/jsx/json
IDE推荐: Visual Studio Code
相关npm插件
- eslint
- eslint-config-airbnb-base
- eslint-config-prettier
- eslint-plugin-import
- eslint-plugin-prettier
- eslint-plugin-vue
- prettier
相关vscode插件
- ESLint
- Vetur
- Prettier - Code formatter
简单说下思路
- eslint 主要负责 vue/js 的格式化[预检测]
- prettier 主要负责 html/css/less/scss… 的格式化
- editorConfig 在不同的IDE之间定义和维护一致的代码风格
- Vetur 格式化vue 也可以不用 [此插件需vscode本地安装]
- prettier Vetur 本身也可以格式化vue文件 只不过我们把它交给eslint来做
格式化优先级editorconfig>prettier>eslint>vetur
//因为prettier配合eslint使用(本项目采用方案) eslint继承了prettier插件
//.eslintrc.js
"extends": ["plugin:prettier/recommended"]
}
故 editorconfig>prettier>eslint>vetur【因电脑系统原因配置项会有重复】
自动检测/修复命令【package.json】文件目录
* npm run lint eslint检测
* npm run pre prettier检测
* npm run lint:fix eslint修复
* npm run pre:check prettier修复
npm i eslint eslint-config-airbnb-base eslint-config-prettier eslint-plugin-import eslint-plugin-prettier eslint-plugin-vue prettier -D
vscode推荐安装插件
- Search node_modules
- Open in node_modules
- Trailing Spaces
相关配置文件如下
- .vscode/setting.json (in git)
- .editorconfig (in git)
- .eslintrc.js (in git)
- .eslintignore (in git)
- .prettierrc.js (in git)
- .prettierignore (in git)
vscode settings.json配置
{
"eslint.alwaysShowStatus": true,
"eslint.provideLintTask": true,
"eslint.autoFixOnSave": true,
"eslint.quiet": true,
"eslint.validate": [
"language": "javascript",
"autoFix": true
"language": "javascriptreact",
"autoFix": true
"language": "vue",
"autoFix": true
"language": "html",
"autoFix": true
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.detectIndentation": false,
"prettier.semi": false,
"prettier.singleQuote": true,
"prettier.stylelintIntegration": true,
"vetur.format.defaultFormatter.html": "none",
"vetur.format.defaultFormatter.js": "prettier",
"vetur.format.defaultFormatter.less": "prettier",
"vetur.validation.template": false,
"vetur.format.options.tabSize": 4,
"vetur.format.defaultFormatterOptions": {
"prettier": {
"semi": false,
"singleQuote": true
"prettyhtml": {
"printWidth": 200,
"singleQuote": true
"javascript.preferences.quoteStyle": "single",
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
"files.autoSave": "afterDelay",
"search.exclude": {
"**/bower_components": true,
"**/node_modules": false
"quokka.compactMessageOutput": true,
"quokka.suppressExpirationNotifications": true,
"breadcrumbs.enabled": true,
"liveServer.settings.donotShowInfoMsg": true,
"search.quickOpen.includeSymbols": true,
"diffEditor.ignoreTrimWhitespace": false,
"editor.mouseWheelZoom": true,
"editor.lineHeight": 22,
"vetur.experimental.templateInterpolationService": false,
"vetur.format.enable": true,
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
.editorconfig配置
# 安装此插件在编辑.editorconfig时可自带提示功能 【EditorConfig for VS Code】
root = true # 表明是最顶层的配置文件,发现设为true时,才会停止查找.editorconfig文件
[*] # 对所有文件生效
charset = utf-8 # 设置默认编码为utf-8
indent_style = space # space为soft-tabs,tab为hard-tabs
indent_size =4 # 设置整数表示规定每级缩进的列数和soft-tabs的宽度(译注:空格数)。如果设定为tab,则会使用tab_width的值(如果已指定)
end_of_line = lf # 定义换行符,支持lf、cr和crlf
insert_final_newline = true # 设为true表明使文件以一个空白行结尾,false反之
trim_trailing_whitespace = true # 设为true表示会除去换行行首的任意空白字符,false反之
[*.md]
insert_final_newline = false # 设为true表明使文件以一个空白行结尾,false反之
trim_trailing_whitespace = false # 设为true表示会除去换行行首的任意空白字符,false反之
.eslintrc.js配置【可插拔】
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint', //指定babel-eslint 作为解析器 babel-eslint一个对Babel解析器的包装,使其能够与 ESLint 兼容
ecmaVersion: 6 //指定你想要使用的 ECMAScript 版本
env: {
browser: true,
es6: true,
node: true
extends: [
'plugin:vue/essential', //插件说明 https://vue-loader-v14.vuejs.org/zh-cn/workflow/linting.html
'eslint:recommended', //来用启用推荐的规则,报告一些常见的问题,在eslint的规则中都带有一个'对号'的图标
'standard',
'plugin:prettier/recommended' // 注意 只有设置了这个属性 格式化才能正确 因为eslint 和 prettier 的配置可能会冲突,所以使用以上两个插件让 prettier 采用 eslint 的配置,实现格式化
plugins: ['vue'], //使用eslint-plugin-vue插件 是为了检测.vue文件中 <template> 和 <script> 中的js代码
rules: {
'vue/attribute-hyphenation': [2, 'always'], //eslint-plugin-vue插件规则
'vue/no-parsing-error': [2, { 'x-invalid-end-tag': false }],
// 'vue/require-valid-default-prop': 2, //props验证
// 'quotes': [1, 'single'],
'vue/require-v-for-key': 2, // 当v-for写在自定义组件上时,它需要同时使用v-bind:key。在其他元素上,v-bind:key也最好写。
'no-extend-native': 2, // 禁止扩展原生类型
'no-undef': 2, // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到. e.g. /* global Stomp SockJS */ in .vue file's <scrpit>
'no-return-assign': 2, // 禁止在 return 语句中使用赋值语句
'generator-star-spacing': 'off', // 强制 generator 函数中 * 号周围使用一致的空格
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, //禁用debugger
'import/order': 0, // 执行模块导入顺序中的约定
'import/no-extraneous-dependencies': 0, // 禁止导入未在package.json的依赖项,devDependencies,optionalDependencies或peerDependencies中声明的外部模块。将使用最接近的父package.json。
'import/no-dynamic-require': 1, // CommonJS的require方法用于从不同文件导入模块。与ES6导入语法不同,可以为其提供将在运行时解析的表达式。虽然这有时是必要且有用的,但在大多数情况下并非如此。使用(例如,连接路径和变量)作为参数使得工具更难以进行静态代码分析,或者在代码库中找到使用模块的位置。
'import/extensions': 0, // 某些文件解析算法允许您在导入源路径中省略文件扩展名。例如,节点解析器可以将./foo/bar解析为绝对路径/User/someone/foo/bar.js,因为默认情况下会自动解析.js扩展名。根据序,您可以配置更多扩展程序以自动解决。
'import/no-unresolved': 0, // 确保导入的模块可以解析为本地文件系统上的模块,如标准Node require.resolve行为所定义。
'import/prefer-default-export': 0, // 当模块中只有一个导出时,更喜欢使用默认导出而不是命名导出。
'vue/no-async-in-computed-properties': 1, // 计算属性应该是同步的。其中的异步操作可能无法按预期工作,并可能导致意外行为,这就是您应该避免它们的原因。如果您需要异步计算属性,可能需要考虑使用其[vue-async-computed]
'vue/no-side-effects-in-computed-properties': 1, // 在计算属性中引入副作用被认为是一种非常糟糕的做法。它使代码无法预测且难以理解。
'vue/no-reserved-keys': 1, // 此规则阻止使用保留名称以避免冲突和意外行为。
'vue/require-valid-default-prop': 1, // 此规则检查每个prop的默认值是否对给定类型有效。当使用函数未返回类型Array或Object的默认值时,它应报告错误
'no-unused-vars': 2, // 禁止出现未使用过的变量
'no-plusplus': 0, // 禁用一元操作符 ++ 和 --
'func-names': 0, // 要求或禁止使用命名的 function 表达式
'no-console': 0, //禁用 console
'no-control-regex': 0, // 禁止在正则表达式中使用控制字符
'no-continue': 0, // 禁用 continue 语句
'no-param-reassign': 0, // 禁止对 function 的参数进行重新赋值
'no-underscore-dangle': 0, // 禁止标识符中有悬空下划线"_"
'global-require': 1, // 要求 require() 出现在顶层模块作用域中
'no-var': 1, // 要求使用 let 或 const 而不是 var
'vars-on-top': 1, // 要求所有的 var 声明出现在它们所在的作用域顶部
'prefer-destructuring': 0, // 优先使用数组和对象解构
'no-useless-concat': 1, // 禁止不必要的字符串字面量或模板字面量的连接
'no-shadow': 1, // 禁止变量声明与外层作用域的变量同名
'guard-for-in': 1, // 要求 for-in 循环中有一个 if 语句,旨在防止使用for in循环而不过滤循环中的结果时可能出现的意外行为。
'no-restricted-syntax': 1, // 禁用特定的语法
'global-require': 1, // 要求 require() 出现在顶层模块作用域中
'consistent-return': 0, // 要求 return 语句要么总是指定返回的值,要么不指定
'no-unused-expressions': 1, // 禁止出现未使用过的表达式
'block-scoped-var': 1, // 强制把变量的使用限制在其定义的作用域范围内,旨在减少绑定上下文之外的变量的使用,并从其他语言模拟传统的块范围。这是为了帮助语言新手避免变量提升的难题。
'no-redeclare': 1, // 禁止多次声明同一变量
'prefer-arrow-callback': 1, // 要求回调函数使用箭头函数
'array-callback-return': 1, // 强制数组方法的回调函数中有 return 语句,Array有几种过滤,映射和折叠的方法。如果我们忘记return在这些回调中写入语句,那可能是一个错误。
'default-case': 0, // 要求 switch 语句中有 default 分支
'no-loop-func': 1, // 禁止在循环中出现 function 声明和表达式
'no-fallthrough': 2, // 禁止 case 语句落空
'no-multi-assign': 2, // 禁止连续赋值
'no-lonely-if': 2, // 禁止 if 作为唯一的语句出现在 else 语句中.如果一个if陈述是该else块中唯一的陈述,那么使用一个else if表格通常会更清晰。
'no-irregular-whitespace': 2, // 禁止在字符串和注释之外不规则的空白
'prefer-const': 2, // 要求使用 const 声明那些声明后不再被修改的变量.如果一个变量从不重新分配,使用const声明更好。const 声明告诉读者,“这个变量永远不会被重新分配,”减少认知负荷并提高可维护性。
'no-use-before-define': 2, // 禁止在变量定义之前使用它们
'no-useless-escape': 0, // 禁用不必要的转义字符
'no-array-constructor': 2, // 禁用 Array 构造函数,由于单参数的缺陷以及Array全局可能被重新定义,所以通常不鼓励使用构造函数来构造新Array数组,而是倾向于使用数组文字符号。例外情况是Array构造函数过给构造函数一个数字参数有意创建指定大小的稀疏数组。
'object-shorthand': 1, // 要求或禁止对象字面量中方法和属性使用简写语法
'no-prototype-builtins': 1, // 禁止直接调用 Object.prototypes 的内置属性.当假定对象将具有属性时,这可能导致错误Object.prototype。此规则可防止Object.prototype直接从对象调用方法。
'no-nested-ternary': 1, // 禁用嵌套的三元表达式.嵌套三元表达式会使代码更难理解。
'no-new-wrappers': 1, // 禁止对 String,Number 和 Boolean 使用 new 操作符.没有任何理由将这些基本包装用作构造函数
'prefer-promise-reject-errors': 1, // 要求使用 Error 对象作为 Promise 拒绝的原因
'no-labels': 1 // 禁用标签语句
说明
- "off" 或 0 - 关闭规则
- "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出)
- "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
.eslintignore
# 默认不检测node_modules
/dist/
/config/
/build/
/static/
.prettierrc.js
module.exports = {
printWidth: 1000, //一行的字符数,如果超过会进行换行,默认为80
tabWidth: 4, //一个tab代表几个空格数
useTabs: false, //是否使用tab进行缩进,默认为false,表示用空格进行缩减
singleQuote: true, //字符串是否使用单引号,默认为false,使用双引号
semi: false, //行位是否使用分号,默认为true
bracketSpacing: true, //对象大括号直接是否有空格,默认为true,效果:{ foo: bar }