「徹底理解」如何統一項目中的代碼風格

image

對代碼進行格式化,是程序員的平常。格式化很爽,可是配置相關的規則、安裝對應插件卻很煩。與其每次碰到問題再慢慢排查,不如一次性融會貫通。javascript

1、代碼風格是什麼(Code Conventions)

咱們能夠按照修改後是否會影響程序運行結果來把風格分爲兩個部分。例以下面的代碼css

var a= 1;
if (a=='1') console.log(true )

1. Format 格式 -> format 格式化(首字母大小寫以便區分)

格式,簡單來講就是變量後面是否須要空格,語句後面是否須要分號等,這一類不管如何改動,都不會影響代碼運行結果的部分。對格式進行改變叫格式化前端

使用以下規則對代碼進行 format:java

  • 語句以後必須接分號
  • 括號頭尾須要 1 個空格
  • 運算符先後須要 1 個空格
var a = 1;
if ( a == '1' ) console.log( true );

2. Source 源碼 -> (source action 源動做)

源碼,與格式相對的,是被修改以後會切實影響代碼運行結果的部分。對源碼進行改變叫源動做node

使用以下規則對代碼進行 source action:webpack

  • 未發生改變的變量必須使用 const 定義
  • 必須使用 ===,禁止使用 ==
const a = 1;
if ( a === '1' ) console.log( true );

格式加源碼,構成了代碼風格git

定義來源: vscode 任意選中一段代碼以後右鍵

image.png

2、風格工具

風格固然是有各類各樣的,有的工具能夠設定本身的風格,有的工具強制使用特定風格。爲了便於理解,本文只介紹業界最主流的工具(也不多有人用其餘的)程序員

Prettier

image.png

Prettier 專一於 Format,基本支持了前端項目相關的全部文件類型,包括但不限於es6

  • JavaScript
  • JSX
  • Vue
  • TypeScript
  • CSS、Less、SCSS
  • HTML
  • JSON
  • Markdown

Prettier 最大的特色是獨裁,在自身規定的幾百上千條 Format 規則中,可配置的僅有 20 條。這也致使其餘工具與 Prettier 並存時,都須要遷就 Prettier 的規則github

ESLint

image.png

ESLint 是目前全部 Lint 工具中使用最普遍的(前端範圍內)。

計算機科學中, lint 是一種工具程序的名稱,它用來標記 源代碼中,某些可疑的、不具結構性(可能形成bug)的段落。它是一種 靜態程序分析工具,最先適用於 C語言,在 UNIX平臺上開發出來。後來它成爲通用術語,可用於描述在任何一種計算機程序語言中,用來標記源代碼中有疑義段落的工具。
—— wiki

ESlint 可配置的範圍,包括 Format 和 Source,可是僅限於能夠被轉換成 AST 的代碼,對於 CSS、HTML 等都無能爲力(這也是爲何須要同時使用 ESLint 和 Prettier 的緣由)

stylelint

image.png

前端開發基本等同於 HTML、JavaScript 和 CSS 開發。經過 Prettier + ESLint,對於風格中的 Format 已經徹底統一,JavaScript 中的 Source 也被統一。因此如今還剩下基本能夠忽略的 HTML 和 CSS 中的 Source 部分

咱們選擇使用 stylelint 來處理 CSS 相關 Source

這樣基本能夠限定前端開發過程當中的全部風格

HTML JavaScript CSS
Format prettier prettier prettier
Source ESlint stylelint

3、使用說明

一般項目中使用風格工具,有三種途徑

  • A - 編譯器引入相關插件
  • B - webpack 引入相關 loader、plugin
  • C - 命令行直接執行

先模擬一下項目中開發需求的流程

  1. 拉取項目代碼,安裝依賴,初始化項目配置風格設置,命令行格式化全部代碼(C)
  2. 使用 webpack 編譯項目

    1. 窗口中及時提示風格問題並自動修復(A)
    2. 控制檯及時提示風格問題,不修正狀況下打包失敗(B)
  3. 使用 git 提交,觸發鉤子,檢查風格經過以後才容許提交(C)

任何流程沒有控制住,都有可能形成設定之外的代碼風格

不管是經過函數、命令行或者插件來使用,風格化的過程基本均可以抽象爲以下公式。

Result = format(sourceAction(src, config)) = Tool(src, config)
// 最終風格 = 格式化(源動做(源碼,配置)) = 工具(源碼,配置)

源碼爲常量。只要保證工具版本統一,配置相同,則不一樣途徑均也能夠得出相同的結果。規則和工具的選擇歷來不是難點,難點在於保證工具、配置的統一

接下來介紹如何保證 A、B、C 三種途徑的統一

A - 編譯器引入相關插件

工具

ESlint: The extension uses the ESLint library installed in the opened workspace folder. If the folder doesn't provide one the extension looks for a global install version.
Prettier: This extension will use prettier from your project's local dependencies (recommended)...
stylelint: The extension uses the stylelint library installed in the opened workspace folder...

根據各個工具的官方插件文檔說明,插件會優先使用項目中的對應庫 node_modules  ,若是不存在則使用全局庫。

配置

ESLint

ESLint 插件目前能夠指定配置文件,若是不指定會讀取 package.json 同級的配置文件

eslint.options: options to configure how ESLint is started using the ESLint CLI Engine API. Defaults to an empty option bag. An example to point to a custom .eslintrc.json file is:
{
  "eslint.options": { "configFile": "C:/mydirectory/.eslintrc.json" }
}

Prettier

Prettier 的配置能夠來源於三處,按優先級排列

  1. Prettier configuration file
  2. .editorconfig
  3. Visual Studio Code Settings (Ignored if any other configuration is present)

實際使用中,使用第一個  package.json 同級的配置文件便可

stylelint

與 Prettier 相似

B - webpack 引入相關 loader、plugin

const StyleLintPluginfrom = require('stylelint-webpack-plugin');
//...  
{
    test: /\.(j|t)sx?$/,
        use: [
          {
            loader: 'babel-loader',
          },
          {
            loader: 'eslint-loader',
            options: {
                            configFile: getWorkSpacePath('.eslintrc.js'),
            }
          },
        ],
  }
//...
plugins: [
    new StyleLintPluginfrom({
      configFile: getWorkSpacePath('.stylelintrc.js'),
    })
]
//...

工具

全部庫都須要安裝在項目的 node_modules 中, eslint-loader 同時依賴於 eslint 庫(stylelint-webpack-plugin 相似)

配置

全部工具基本均可以在 option 中指定配置文件

C - 命令行直接執行

工具

首先須要在 node_modules 中安裝有對應的庫,而後在 package.json 中設置對應腳本

{
  //...
    "scripts": {
        "eslint": "eslint",
        "prettier": "prettier",
        "stylelint": "stylelint",
    },
  //...
}

以後能夠在命令行中使用

yarn eslint --fix
-c, --config path::String      Use this configuration, overriding .eslintrc.* config options if present

yarn prettier --write
--config ./my/.prettierrc

yarn stylelint --fix
--config ./my/.stylelintrc

配置

全部工具在使用都可以指定配置文件

因此

  • 工具統一等價於把相關依賴所有安裝到項目 **node_modules**,保證不使用全局依賴
  • 配置統一等價於使用統一的配置文件。因爲部分插件不能指定路徑,只會默認讀取 node_modules 同級,因此建議因此配置文件都放在這一層

4、實戰

首先引入 Prettier,咱們全部的 format 都使用 Prettier 來完成。

在項目中接入 Prettier

yarn add prettier -D

1. 安裝插件

安裝官方推薦的編譯器插件 Prettier - Code formatter(此處只考慮 VSCode),設置工做區的 .vscode/setting.json

切記必定要關閉其餘帶有格式化功能的插件,不然會發生衝突。特別是使用 VUE 框架時,記得關閉 vetur 的格式化。同時記得檢查一下全局範圍的 setting.json,註釋掉全部 format 相關的配置

{ 
    // 保存時自動 Format
  "editor.formatOnSave": true,
    // 關閉 vetur 格式化
  "vetur.format.enable": false,
}

2. 推薦插件

爲了告訴其餘協同開發的同事,安裝正確的 Prettier 插件,添加插件名在 .vscode/extensions.json 中,同時把其餘容易干擾格式化的插件設置爲不推薦。

這樣其餘人在首次安裝項目的同時也會收到對應的提示了。

{
  "recommendations": [
    "esbenp.prettier-vscode",
  ],
  "unwantedRecommendations": ["hookyqr.beautify"]
}

 

3. 配置文件

package.json 同級建立 Prettier 的配置文件

// prettier.config.js or .prettierrc.js
module.exports = {
  trailingComma: "es5",
  tabWidth: 4,
  semi: false,
  singleQuote: true,
};

git 提交本次修改(尤爲是 .vscode 文件夾)。以後任何人開發這個項目,只要安裝了正確的插件,寫出來的代碼風格確定都是統一的了

4. 限制提交

假設有一個同事頭鐵,就是不正確安裝插件和配置編譯器。他提交代碼的風格就沒法獲得統一,因此須要再增長一層保險,在 git commit 時候須要校驗全部改動過的文件,對這些文件使用 prettier --write 。

git commit 時觸發、校驗全部改動過的文件。這兩個功能分別是兩個插件

  • husky 

它能運行Githooks諸如 Pre-commit、pre-receive 和 post-receive。

用以在各個階段觸發不一樣校驗,通常配合各類 lint 使用

  • lint-staged 

當項目文件比較多的時候,若是每次改動都對全部文件進行校驗。勢必致使等待時間變長。 解決上面的痛點就須要使用 lint-staged。它只會校驗你提交或者說你修改的部份內容。

yarn add husky lint-staged -D

package.json 中添加字段

"husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    // src 目錄下任意文件有改動,都使用 prettier --write 格式化以後再提交
    "src/**/*.*": [
      "prettier --write",
      "git add"
    ]
  }

這樣基本就能保證項目的萬無一失了(一失在於開發者刪除 husky、lint-stage 配置🤦‍♂️)

在項目中接入 ESLint、stylelint

Prettier 只提供了風格中 Format 的部分,對於 Source,還須要接入其餘工具。

  • ESLint:處理 JavaScript 相關(TypeScript、JSX ...)的 Source action
  • stylelint:處理 CSS 相關 (Less、SCSS) 的 Source action

流程基本和接入 Prettier 同樣

1. 安裝、推薦插件

安裝 ESLint stylelint,並修改 setting.json

yarn add eslint stylelint -D

注意 formatOnSavecodeActionsOnSave 二者的區別。以前說過,由 Prettier 進行全部的 format,而後再針對不一樣類型的文件使用各類的 Soruce action

相關討論: https://github.com/microsoft/vscode/issues/87096#issuecomment-567750791
{ 
  // 保存時自動 Format
  "editor.formatOnSave": true,
    
  // 保存時自動 Source action
  "editor.codeActionsOnSave": {
    "source.fixAll": true, // 開啓全部工具的 source action
    //"source.fixAll.eslint": true, // 開啓 ESLint 的 source action
    //"source.fixAll.stylelint": true, // 開啓 stylelint 的 source action
  },
  "vetur.format.enable": false,
}

修改 extensions.json

{
  "recommendations": [
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "stylelint.vscode-stylelint"
  ],
  "unwantedRecommendations": ["hookyqr.beautify"]
}

2. 配置文件

package.json 同級建立 ESlint、stylelint 的配置文件,具體如何設置此處就不說明了。要注意的就是必定要給 Prettier 的設置讓位
**
給 ESLint、stylelint 安裝兼容 prettier 的插件 

yarn add eslint-config-prettier stylelint-config-prettier -D
// .eslintrc.js
module.exports = {
  //...
  env: {
    browser: true,
    es6: true,
  },
  
  extends: ["eslint:recommended", "prettier"],
  plugins: [],
  rules: {},
  //...
};
// .stylelintrc.js
module.exports = {
  //...
  extends: ["stylelint-config-prettier"],
  plugins: [],
  rules: {},
  //...
};

3. 編譯校驗

不少 Source 問題會要求用戶手動更改,因此須要及時提示。插件雖然會提示,但不會影響代碼編譯結果,因此須要在編譯過程當中校驗

詳見以前的 B - webpack 引入相關 loader、plugin 段落

4. 限制提交

修改 package.json

"husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    // src 目錄下任意文件有改動,都使用 prettier --write 格式化以後再提交
    "src/**/*.js": [
      "eslint --fix",
      "prettier --write",
      "git add"
    ],
    "src/**/*.css":[
      "stylelint --fix",
      "prettier --write",
      "git add"
    ]
  }

至此,風格統一相關的全部流程都已經覆蓋到了!

附錄

相關文章
相關標籤/搜索