一步一步,統一專案中的編碼規範(vue, vscode, vetur, prettier, eslint)

wfz發表於2019-04-24

團隊開發中,多人開發同一個專案,由於個人編碼習慣不同,一個專案中最終的程式碼風格可能差別很大,所以需要通過工具進行約束來保證程式碼風格的統一。同時也希望通過工具儘可能的減少低階錯誤出現,並且能幫助修正,所以有了各種各樣的 lint 和 formatter。

本篇的目標是使用 vscode 編輯器,使用 prettier 外掛,結合使用 eslint 對程式碼進行校驗和修正,並使用 eslint-config-airbnb-base 規則來實現程式碼風格的統一。

一般情況下,我們小公司、小 team 可能沒有能力和精力來制訂一套詳盡規則,那麼採用大廠已經制訂好的規則就是很自然的選擇(同時也必要爭論你的好還是我的好了,人家大廠都這麼幹了,我們就按人家來吧!:))

名詞解釋

  • vscode

一個文字編輯器 code.visualstudio.com/

  • prettier

vscode 外掛,官方的說明是:Opinionated Code Formatter

  • eslint

程式碼校驗和修復工具,官方說明是:The pluggable linting utility for JavaScript and JSX

  • eslint-config-airbnb-base

一組預先定義好的 eslint 規則,官方說明是:This package provides Airbnb's base JS .eslintrc (without React plugins) as an extensible shared config.

下面一步一步,通過 vscode 的格式化的使用,到和 prettier 的結合,eslint 使用, prettier 結合 eslint 對 js 和 vue 檔案校驗,完成對專案程式碼校驗和 fix,力求能以最簡潔的方式把問題說清楚。

vscode 開箱即用的 code formatter 功能

vscode 提供開箱即用的程式碼樣式化功能(沒有 css 格式化功能),下面在當前資料夾下建立測試檔案:./src/demo.html./src/fun.js./src/style.css,格式化程式碼的快捷鍵是(win):alt + shift + f

HTML 格式化前:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Demo page</title>
</head>
<body><h1>This is a test page</h1>
<p>Page content</p>
</body>
</html>
複製程式碼

格式化後:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Demo page</title>
</head>

<body>
    <h1>This is a test page</h1>
    <p>Page content</p>
</body>

</html>
複製程式碼

JS 格式化前:

function getUserInfo(name) {let HelloStr = "Hello, your name is: "
return HelloStr + name
}
複製程式碼

格式化後:

function getUserInfo(name) {
    let HelloStr = "Hello, your name is: "
    return HelloStr + name
}
複製程式碼

CSS:

CSS 檔案的格式化

可以看到,CSS 檔案預設情況下是不能被格式化的,這個時間輪到 prettier 登場~

用 prettier 對程式碼進行格式化

prettier 的官方解釋是:

  • An opinionated code formatter
  • Supports many languages
  • Integrates with most editors
  • Has few options

它能和多種編輯器結合,對多種語言進行 format,所以 css 也不是話下。

由於 vscode 預設有格式化的功能,安裝了 prettier 外掛後,prettier 也有格式化的功能以會造成衝突(對於html, js),這裡編輯器會提示你,可以進行配置。

Prettier 格式化 html

需要注意的是,vscode 和 prettier 會有很多預設配置,可以通過 CTRL + , 快捷鍵進入配置介面進行管理,所有修改後的結果會儲存在 settings.json 檔案裡。

剛剛由於 vscode 預設的格式化程式和 prettier 衝突,經過選擇後形成配置檔案並寫入 settings.json,如下:

{
    "[html]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[jsonc]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    }
}
複製程式碼

上面是指標不同型別的檔案,分別指定 formatter,當然你也可以一次性指定所有型別檔案的 formatter,修改後的配置檔案 settings.json 如下:

{
    "editor.defaultFormatter": "esbenp.prettier-vscode"
}
複製程式碼

經過如上配置, css 及其他型別的檔案,擁有了通過 prettier 進行格式化的能力。

用 eslint 對 javascript 程式碼進行校驗

經過如上配置,可以對程式碼進行格式化了,但是如果要想去程式碼風格進行校驗和修復,就要用到 eslint 了,下面分兩步將 eslint 功能整合了專案中:

  1. 在專案內安裝 eslint 及相關的包
  2. 給 vscode 安裝 eslint 外掛

下面分別來說

在專案內安裝 eslint 及相關的包

安裝 eslint

經過上面的操作,將 eslint 及相關的包安裝到專案裡了 package.json如下:

{
  ...
  "dependencies": {
    "eslint-plugin-vue": "^5.2.2"
  },
  "devDependencies": {
    "eslint": "^5.16.0"
  }
  ...
}
複製程式碼

專案目錄下多了一個 eslint 的配置檔案 .eslintrc.js :

module.exports = {
    "env": {
        "browser": true,
        "es6": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:vue/essential"
    ],
    "globals": {
        "Atomics": "readonly",
        "SharedArrayBuffer": "readonly"
    },
    "parserOptions": {
        "ecmaVersion": 2018,
        "sourceType": "module"
    },
    "plugins": [
        "vue"
    ],
    "rules": {
    }
};
複製程式碼

這個配置檔案的內容,是通過 npx eslint --init 自動生成的,當然你也可以手動配置,所有的選項這裡都有中文說明:eslint.cn/docs/user-g…

接下來就可以手動執行校驗了:

eslint lint

在執行的時候可能會有包未安裝的提示

Failed to load plugin vue: Cannot find module 'eslint-plugin-vue'

手動安裝一下就好了,從執行結果來看,funs.js 檔案有一個錯誤提示,說明校驗程式已經能正常跑進來了。

現在採用的規則是 eslint:recommended ,我們的目標是採用 'eslint-config-airbnb-base',所以再安裝相應的包:

npm i -D eslint-config-airbnb-base eslint-plugin-import
複製程式碼

然後對 .eslintrc.js 進行配置:

module.exports = {
  env: {
    browser: true,
    es6: true,
  },
  extends: 'airbnb-base',
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly',
  },
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
  },
  plugins: [
    'vue',
  ],
  rules: {
    'linebreak-style': ["error", "windows"]
  },
};
複製程式碼

再進行校驗:

D:\works\secoo\test\code-formatter> npx eslint .\src\funs.js

D:\works\secoo\test\code-formatter\src\funs.js
  1:10  error  'getUserInfo' is defined but never used              no-unused-vars
  2:7   error  'HelloStr' is never reassigned. Use 'const' instead  prefer-const
  3:7   error  'age' is assigned a value but never used             no-unused-vars
  3:7   error  'age' is never reassigned. Use 'const' instead       prefer-const
  3:15  error  Missing semicolon                                    semi

✖ 5 problems (5 errors, 0 warnings)
  3 errors and 0 warnings potentially fixable with the `--fix` option.
複製程式碼

可以看到明顯比之前的錯誤要多,Aribnb 的規則相對較為嚴格,可以規避很多低階錯誤。

這裡要重點說一下的是,我們在 .eslintrc.jsrules 里加了 'linebreak-style': ["error", "windows"],是由於不同系統間對換行的處理不同導致的,加這個規則來處理這個問題。

給 vscode 安裝 eslint 外掛

走到這裡我們已經可以校驗 js 檔案了,通過校驗也發現了很多問題,但在 vscode裡並沒有錯誤提示,這就用到了 vscode 的另一個外掛 eslint,安裝完外掛以後,在 vscode 裡可以看到錯誤提示了:

eslint lint

走到這裡,我們離成功已經很近啦!

讓 pretter 根據 eslint 校驗結果,對程式碼進行樣式化

到目前為上,已經可以對 js 檔案進行校驗,甚至可以對 js 檔案按規則進行修復了:

D:\works\secoo\test\code-formatter> npx eslint --fix .\src\funs.js

D:\works\secoo\test\code-formatter\src\funs.js
  1:10  error  'getUserInfo' is defined but never used   no-unused-vars
  3:9   error  'age' is assigned a value but never used  no-unused-vars

✖ 2 problems (2 errors, 0 warnings)
複製程式碼

但是如果你用 vscode(如前述,vscode 使用 prettier) 進行修復,發現並沒有應用 Airbnb 的規則,這裡需要手動配置一下:

  • CTRL + , 開啟配置介面
  • 擴充套件 -> Prettier 裡打到 Eslint Integration 並勾選 得到 vscode 的配置檔案 settings.json 如下
{
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "prettier.eslintIntegration": true
}
複製程式碼

這時再對 js 檔案進行格式化,就能按照指定的規則執行了,具體操作如下:

prettier format follow eslint

校驗並且格式化 vue 程式碼

這部分是最麻煩的,很多同學都在這裡翻車......

首先,要想 vscode 認識 vue 檔案,需要安裝外掛 vetur,基本上安裝好此外掛後就可以開心的擼 vue 程式碼了,vetur 的預設配置如下:

{
  "vetur.format.defaultFormatter.html": "prettyhtml",
  "vetur.format.defaultFormatter.css": "prettier",
  "vetur.format.defaultFormatter.postcss": "prettier",
  "vetur.format.defaultFormatter.scss": "prettier",
  "vetur.format.defaultFormatter.less": "prettier",
  "vetur.format.defaultFormatter.stylus": "stylus-supremacy",
  "vetur.format.defaultFormatter.js": "prettier",
  "vetur.format.defaultFormatter.ts": "prettier"
}
複製程式碼

以上是預設配置,看著很開以的以為可以按著如下方式對程式碼進行格式化:

發出格式化命令
    |
    | next
    |
vetur 收到命令 將格式化任務轉交給 prettier
    |
    | next
    |
prettier 收到命令 將格式化任務轉交給 eslint
    |
    | next
    |
eslint 收到命令,將程式碼格式化
複製程式碼

看似美好的結局被現實打破,當我們對 vue 檔案進行格式化的時候,發它參考的規則是 prettier 規則,而非 eslint 規則。

如果想按著上述規則對 vue 進行格式化需要做兩個事: settings.json

  • 將 vetur 中 js 的 formatter 設定為 prettier-eslint
{
  ...
  "vetur.format.defaultFormatter.js": "prettier-eslint"
  ...
}
複製程式碼
  • 安裝 prettier-eslint 包
npm i -D prettier-eslint
複製程式碼

對於這個問題,prettier-eslint 官網上說的很清楚:

This formats your code via prettier, and then passes the result of that to eslint --fix. This way you can get the benefits of prettier's superior formatting capabilities, but also benefit from the configuration capabilities of eslint.

但就是這麼一個問題,我在網上看把無數的同學繞進去了,確實直線理解的話會有兩個坑:

  1. prettier 不是已經按著 eslint 來格式化 js 了嗎,vetur 指給 prettier 按說沒問題啊!現實是需要傳遞給 prettier-eslint
  2. 很多同學跨過了第一道坎,但不曾想 prettier-eslint 需要手動安裝一個包啊!

所以導致在最後一步走不下去了。

至此配置基本已經完成,效果如下:

eslint-vue-fix

最後總結

最後總結一下,總共需要做那些工作

  1. 安裝 vscode 外掛 eslintprettiervetur
  2. 配置 eslint 規則
  3. 配置 prettier ,使其按著 eslint 工作
  4. 配置 vetur

最終的配置檔案如下: settings.json

{
  "extensions.autoUpdate": false,
  "eslint.validate": ["javascript", "javascriptreact", "vue"],
  "prettier.eslintIntegration": true,
  "vetur.format.defaultFormatterOptions": {
    "prettier": {
      "eslintIntegration": true
    }
  },
  "vetur.format.defaultFormatter.js": "prettier-eslint",
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[jsonc]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "vetur.format.defaultFormatter.html": "prettier"
}

複製程式碼

.eslintrc.js

module.exports = {
  env: {
    browser: true,
    es6: true
  },
  extends: ['airbnb-base', 'plugin:vue/recommended'],
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly'
  },
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module'
  },
  plugins: ['vue'],
  rules: {
    'linebreak-style': ['error', 'windows'],
    'comma-dangle': ['error', 'never'], // 修正 eslint-plugin-vue 帶來的問題
  }
};
複製程式碼

原始碼在 這裡

參考文章:

Tips

相關文章