項目eslint從零到一
eslint在項目里并不太陌生,通常在使用腳手架時,會默認讓你安裝執(zhí)行的eslint,當公司項目比較規(guī)范時,常常會配置組內(nèi)統(tǒng)一的eslint規(guī)則,eslint幫助我們在開發(fā)階段檢查代碼是否符合標準規(guī)范,統(tǒng)一了我們組內(nèi)不同項目代碼風格,也可以幫助我們養(yǎng)成良好的代碼習慣,統(tǒng)一eslint對于項目的可維護性必不可少,今天我們一起學(xué)習一下如果改進你項目的規(guī)范。
正文開始...
首先我們還是用之前搭建vue的一個項目從0到1開始配置eslint
安裝eslint
npm i eslint --save-dev
然后我們執(zhí)行初始化eslint命令
npm init @eslint/config
此時會讓我們選擇第三個,并且選擇js modules, vue
當你默認選擇后就會生成一個文件.eslintrc.js,由于我添加了ts所以默認也會添加@typescript-eslint,我們會發(fā)現(xiàn)package.json多了幾個插件@typescript-eslint/eslint-plugin、@typescript-eslint/parser,并且要安裝npm i typescript --save-dev
eslint規(guī)則是自己默認選擇的配置
module.exports = {
env: {
browser: true,
es2021: true
},
extends: ['eslint:recommended', 'plugin:vue/essential', 'plugin:@typescript-eslint/recommended'],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
plugins: ['vue', '@typescript-eslint'],
rules: {
indent: ['error', 'tab'],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'never']
}
};
默認生成的規(guī)則就是以上
我們運行npx eslint ./src/index.js
執(zhí)行該命令就會檢測對于的文件是否符合eslint默認配置的規(guī)則
添加eslint規(guī)則
在.eslintrc.js中,主要有以下5個部分
module.exports = {
env: {
browser: true,
es2021: true
},
extends: ['eslint:recommended', 'plugin:vue/essential', 'plugin:@typescript-eslint/recommended'],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
plugins: ['vue', '@typescript-eslint'],
rules: {
indent: ['error', 'tab'],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'always']
}
};
env 支持的環(huán)境,根據(jù).browserslistrc瀏覽器預(yù)設(shè)的環(huán)境預(yù)設(shè)對應(yīng)的規(guī)則
module.exports = {
env: {
browser: true,
es2021: true,
es6: true
}
}
extends 繼承第三方的規(guī)則
module.exports = {
extends: ['eslint:recommended']
}
parserOptions 指定解析器選項
module.exports = {
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
}
}
plugins 插件
module.exports = {
plugins: ['vue', '@typescript-eslint'],
}
rules 具體對應(yīng)規(guī)則的設(shè)置
module.exports = {
rules: {
semi: 0 // 0 off,1 warn,2 error
},
}
參考一段之前業(yè)務(wù)有用到的統(tǒng)一eslint配置
// eslint配置
module.exports = {
root: true,
env: {
node: true,
},
parserOptions: {
parser: '@typescript-eslint/parser',
},
extends: [
'plugin:vue/essential',
'plugin:prettier/recommended',
'@vue/airbnb',
'@vue/typescript',
],
rules: {
'no-undef': 0, // 由于eslint無法識別.d.ts聲明文件中定義的變量,暫時關(guān)閉
'no-console': process.env.NODE_ENV === 'production' ? 2 : 0,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
indent: 0,
'linebreak-style': 0,
'no-trailing-spaces': 0,
'class-methods-use-this': 0,
'import/prefer-default-export': 0,
'no-restricted-syntax': 0,
'no-tabs': 0,
'import/no-unresolved': 0,
'no-underscore-dangle': 0,
'comma-dangle': 'off',
'max-len': 'off',
camelcase: 'off',
'object-curly-newline': 0,
'operator-linebreak': 0,
'guard-for-in': 0,
'import/no-webpack-loader-syntax': 0,
// 不安全項
'no-param-reassign': 0,
'no-dupe-class-members': 0,
'no-unused-vars': 0, // ts里面有校驗,可以把eslint 的校驗關(guān)閉
// 提示警告
'no-return-await': 1,
'import/no-cycle': 1,
'no-nested-ternary': 1,
'no-new-func': 1,
'vue/no-side-effects-in-computed-properties': 1,
'vue/no-multiple-template-root': 'off', // vue3 模板可以有多個根結(jié)點
'vue/valid-template-root': 'off',
'vue/no-v-for-template-key': 'off', // vue3 v-for 中template 可以設(shè)置key
'vue/no-v-model-argument': 0,
'vue/no-use-v-if-with-v-for': 0,
'import/no-extraneous-dependencies': 1,
'no-continue': 1,
'operator-assignment': 1,
'no-bitwise': 1,
'prefer-destructuring': 2,
'array-callback-return': 2,
'func-names': 2,
'no-plusplus': 2,
'no-shadow': 2,
'no-mixed-operators': 2,
'no-fallthrough': 2,
'default-case': 2,
'no-useless-constructor': 2,
'no-unused-expressions': ["error", { "allowShortCircuit": true }],
// 關(guān)閉iview input組件,col組件個別標簽報錯
'vue/no-parsing-error': [2, { 'x-invalid-end-tag': false }],
// 保證js、ts項目arrow風格一致
'arrow-parens': [2, 'always', { requireForBlockBody: false }],
'implicit-arrow-linebreak': [0, 'beside'],
// ts 任意枚舉報錯問題
'no-shadow': 'off',
'@typescript-eslint/no-shadow': ['error'],
},
overrides: [
{
files: ['**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)'],
env: {
jest: true,
},
},
],
};
選擇Airbnb風格
在自定義自己的rules,也可以執(zhí)行npm init @eslint/config配置社區(qū)比較流行的自定義風格,使用Airbnb
當我們選擇airbnb風格后,執(zhí)行npx eslint ./src/index.js
提示index.js有一個規(guī)則錯誤
Expected 1 empty line after import statement not followed by another import import/newline-after-import我們將第三行換行就行
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
我們看下生成的.eslintrc.js這個一般在你項目中多少有看到也可以是json類型
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'plugin:vue/essential',
'airbnb-base',
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: [
'vue',
],
rules: {
},
};
rules有很多的配置,可以參考官方[1]
運行時檢測eslint
一般正常情況當我們啟動服務(wù)時,如果我們代碼有寫得不規(guī)范,開發(fā)工具就終端就會給我們提示警告,此時我們需要eslint-loader[2],只需要這樣配置即可
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: [
'babel-loader', 'eslint-loader'
]
}
]
}
}
但是官方已經(jīng)不建議這么用了eslint-loader已經(jīng)停止了維護,官方建議使用eslint-webpack-plugin
在webpack.config.js我們可以這么做
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
plugins: [
new ESLintPlugin()
]
}
當我們運行npm run server時就會檢查代碼錯誤
提示在utils/index.js中不能使用console,很顯然,這條規(guī)則并不符合我們的初衷,我只需要在生產(chǎn)環(huán)境環(huán)境不打印console才行
當我們修改.eslintrc.js時,
module.exports = {
rules: {
'no-console': 0,
'import/extensions': ['error', 'always']
}
}
我們將rules規(guī)則的noconsole: 0允許使用console,當我修改完時,再次運行,終端就不會報錯了
我們再加個規(guī)則,max-params:2,函數(shù)形參不能到過三個,如果超過三個就會報錯
module.exports = {
rules: {
'no-console': 0,
'import/extensions': ['error', 'always'],
'max-params': 2
}
}
// utils/index.js
function test(a, b, c, d) {
console.log('hello', a, b, c, d);
}
test(1, 2, 3, 4);
因為默認max-params默認最多就是3個參數(shù),所以在運行時就提示報錯了。于是你改成下面這樣就可以了
// utils/index.js
function test(a, ...rest) {
console.log('hello', ...rest);
}
test(1, 2, 3, 4);
vscode的eslint插件
除了eslint-webpack-plugin的插件幫我們在代碼運行時就可以檢測出代碼的一些不規(guī)范問題,我們通??梢越Y(jié)合vscode插件幫我更友好的提示,我們需要在寫代碼的時候,編輯器就已經(jīng)給我們提示錯誤。
安裝完后,打開對應(yīng)文件,就會有對應(yīng)的提示
并且你可以通過提示跳轉(zhuǎn)到對應(yīng)的eslint
.prettierrc自動格式化代碼
在vscode中裝上插件Prettier code formatter
然后在根目錄下創(chuàng)建.prettierrc.json文件
{
"singleQuote": true,
"printWidth": 150
}
設(shè)置編輯器的代碼長度printWidth是150,設(shè)置singleQuote單引號。
我們也需要設(shè)置一下vscode的settings.json,主要設(shè)置參照如下
然后添加一行自動保存功能,這樣我們就可以保存時,自動格式化自己的代碼
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
}
因為eslint既檢查了代碼又可以根據(jù).eslintrc.js美化代碼,但是prettierrc有時會與eslint的配置格式有沖突,所以此時vscode格式化的狀態(tài)就是混亂的,因此有時候很奇怪,所以你需要改settings.json默認改成eslint,具體可以參考知乎這篇文章prettierrc[3]
網(wǎng)上關(guān)于prettierrc的配置有很多,具體上還是看組內(nèi)統(tǒng)一的規(guī)范,這里我貼一份之前項目格式化所用的,估計不同團隊的配置絕大數(shù)是大同小異。
// .prettierrc.json
{
"eslintIntegration": true,
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"proseWrap": "preserve",
"arrowParens": "avoid",
"bracketSpacing": true,
"disableLanguages": [
"vue"
],
"endOfLine": "auto",
"htmlWhitespaceSensitivity": "ignore",
"ignorePath": ".prettierignore",
"jsxBracketSameLine": false,
"jsxSingleQuote": false,
"requireConfig": false,
"trailingComma": "es5"
}
總結(jié)
eslint在項目中的配置,主要利用npm init @eslint/config快速初始化一份eslint配置,在試用前先進行安裝npm i eslint --save-dev
開發(fā)環(huán)境使用eslint-loader,現(xiàn)在采用更多的是eslint-webpack-plugins
采用Airbnb風格格式校驗代碼
.prettierrc.json格式化代碼,不過注意與eslint格式?jīng)_突的問題。
本文示例code example[4]
參考資料
[1]
參考官方: https://eslint.org/docs/rules/
[2]
eslint-loader: https://www.npmjs.com/package/eslint-loader
[3]
prettierrc: https://zhuanlan.zhihu.com/p/347339865
[4]
code example: https://github.com/maicFir/lessonNote/tree/master/webpack/webpack-06-eslint
作者:Maic
歡迎關(guān)注微信公眾號 :web技術(shù)學(xué)苑