公司團(tuán)隊目前前端開發(fā)人員快速增長,為了保證每個成員代碼編寫的統(tǒng)一規(guī)范,我們都會對代碼編寫做一些規(guī)范。
1.想法
- 使用vscode + vetur + eslint + prettier 實現(xiàn)團(tuán)隊代碼風(fēng)格統(tǒng)一
- eslint 主要負(fù)責(zé)語法錯誤檢測,并提示
- prettier 主要負(fù)責(zé) html/css/less/scss… 的格式化
- vetur 主要負(fù)責(zé)高亮vue里面template的代碼,不做其他操作
2. 使用
- IDE: vsCode
- npm:
eslint
babel-eslint:eslint 支持不同的解析器(parser),而 babel-eslint 就是 babel 為 eslint 開發(fā)的語法解析器,使 eslint 可以支持 es6 語法
eslint-plugin-vue:對vue代碼語法進(jìn)行提示
eslint-config-prettier:它會默認(rèn)關(guān)閉所有不必要的或eslint可能與 prettier沖突的規(guī)則(本例不打算安裝)
eslint-plugin-prettier:它會將 prettier 作為 eslint 的規(guī)則來使用,相當(dāng)于代碼不符合 prettier 的標(biāo)準(zhǔn)時,會報一個 eslint 錯誤,同時也可以通過 eslint --fix 來進(jìn)行格式化(本例不打算安裝)
3.相關(guān)配置如下
- .eslintrc.js
/**
*
* 規(guī)則說明見 https://cn.eslint.org/docs/rules/
* eslint-plugin-vue 規(guī)則見 https://github.com/vuejs/eslint-plugin-vue
*
* "off" 或 0 - 關(guān)閉規(guī)則
* "warn" 或 1 - 開啟規(guī)則,使用警告級別的錯誤:warn (不會導(dǎo)致程序退出)
* "error" 或 2 - 開啟規(guī)則,使用錯誤級別的錯誤:error (當(dāng)被觸發(fā)的時候,程序會退出)
*
*/
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: ['plugin:vue/recommended', 'eslint:recommended'],
// add your custom rules here
rules: {
'vue/max-attributes-per-line': [2, {
'singleline': 10,
'multiline': {
'max': 1,
'allowFirstLine': false
}
}],
'vue/html-self-closing': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/no-template-shadow': "off",
'vue/name-property-casing': ['error', 'PascalCase'],
'vue/no-v-html': 'off',
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'always-multiline'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ["error", "always", {"null": "ignore"}],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'always'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': 0,
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
}
- .eslintignore
# 忽略build目錄下類型為js的文件的語法檢查
build/*.js
# 忽略src/assets目錄下文件的語法檢查
src/assets
# 忽略public目錄下文件的語法檢查
public
# 忽略當(dāng)前目錄下為js的文件的語法檢查
/*.js
- .prettierrc.js
module.exports = {
printWidth: 220,
singleQuote: true, // 使用單引號而不是雙引號
semi: true, // 句尾是否加;
proseWrap: 'preserve',
tabWidth: 2,
trailingComma: 'es5', // 在對象或數(shù)組最后一個元素后面是否加逗號(在ES5中加尾逗號)
bracketSpacing: true, // 在對象,數(shù)組括號與文字之間加空格 "{ foo: bar }"
htmlWhitespaceSensitivity: 'ignore', // > 不亂換行
};
- .prettierignore
.eslintrc.js
/dist/
/node_modules/**
/public/*
- .vscode/settings.json
{
"editor.formatOnSave": true, //保存自動格式化
"editor.defaultFormatter": "esbenp.prettier-vscode", // 設(shè)置默認(rèn)格式工具為prettier
"eslint.enable": true, // 開啟eslint檢查
"eslint.probe": ["javascript", "javascriptreact", "vue", "html"] // 打開對vue的lint,并自動fix
}
4.總結(jié)
接下來就說說所有遇到的坑吧,后面大神們可以接下面的討論或者繼續(xù)探索。
1、找了很多eslint + prettier 搭配實現(xiàn)代碼格式化的教程也好,案例也罷。其中都用到eslint-config-prettier、eslint-config-prettier兩個插件,在.eslintrc.js文件中加上"extends": ["plugin:prettier/recommended"],就可以解決eslint 和 prettier 的規(guī)則沖突,我加上了,是解決了,但是eslint卻無法提升了,我的目的就是要讓eslint提示,prettier格式化,所以我只能放棄加載這兩個插件(希望后面的大神可以繼續(xù)探索)
2、vue里面的template代碼我也默認(rèn)使用prettier格式化,但是出現(xiàn)一個問題就是格式化后html會亂換行,表現(xiàn)為“>”符號自動換行,找了很多方案都說設(shè)置prettier的jsxBracketSameLine(新的是bracketSameLine)禁止>單獨一行,可惜都失敗了,最好用了htmlWhitespaceSensitivity: 'ignore', 解決。