添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
首发于 前端笔录
前端团队代码风格统一规范实践

前端团队代码风格统一规范实践

目标

  • 自动格式化前端开发常见文件,实现团队代码风格统一
  • 杜绝因格式问题导致的提交冲突,提高开发效率
  • 统一配置,团队共享,实现同步
  • 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 }