代碼開發(fā)規(guī)范

背景
隨著項?復雜度提?、團隊成員增多,但編碼的?格不統(tǒng)?,會增加后期維護代碼的成本以及編碼效率。如果制定?套好的規(guī)范,可以解決很多意外的bug、可以規(guī)范??的編碼習慣、可以讓 code Review 更加簡單。

?標

  1. 降低維護代碼的成本、提高多?協(xié)作的效率
  2. 遵守最佳實踐,確保寫出更?效且優(yōu)雅的代碼

Git提交信息規(guī)范

在使? Git 進?代碼的分布式版本控制時,規(guī)范化 commit message 可以幫助開發(fā)人員在多? 開發(fā)協(xié)作中更好的理解他?對代碼的改動信息,避免?家按照各?的理解和習慣(甚?是隨意)書寫,?對他?和??造成困惑,從?增加代碼審查和糾錯的時間成本。

本規(guī)范基于 Conventional 規(guī)范,這是標準的 commit message 的寫法,?較合理和系統(tǒng)化,并且可以搭配?具校驗。

作?

?個規(guī)范化的 commit message ,具有以下作?:

? 提供更多的歷史信息,?便快速瀏覽

? 可以過濾某些 commit (?如?檔改動),便于快速查找信息

? 可以直接從 commit ?成 CHANGELOG.md

格式

使? git commit 可以提交多?,完整的格式包括三個部分:

? Header【必填】

? Body【選填】

? Footer【選填】

<type>(<scope>): <subject> <!-- header -->
 <!-- 空?? -->
<body>
 <!-- 空?? -->
<footer>

任意??都不應(yīng)該超過100字符,這樣的信息在 github 和各種各樣的 git ?具上能有更好的可讀性。

Header 是必填,Body 和 Footer 是選填 ,因此這里只介紹Header的寫法

Header 包括三個字段:

? type(必填)

? scope(選填)

? subject(必填)

<type>(<scope>): <subject>

Type

?于說明 commit 的類別,只允許使?下? 7 個標識:

? feat:新功能(feature)

? fix:修補bug

? docs:?檔(documentation)

? style:格式(不影響代碼運?的變動)

? refactor:重構(gòu)(即不是新增功能,也不是修改bug的代碼變動)

? test:增加測試

? chore:構(gòu)建過程或輔助?具的變動

Scope

?于說明 commit 影響的范圍,?如數(shù)據(jù)層、控制層、視圖層等等

Subject

?于對 commit ?的的簡短描述,不超過50個字符

以動詞開頭,使?第??稱現(xiàn)在時,?如 change ,?不是 changed 或 changes 第?個字??寫
注意:結(jié)尾不需要加句號(.)

# ?例?
 fix(login): 修改登錄賬號加密?式

# ?例?
 fix: 去除登錄??console代碼

配合?具

# Install Husky v6
 npm install husky --save-dev
# or
 yarn add husky --dev

# Active hooks
 npx husky install
# or
 yarn husky install

 # Install and configure if needed
    npm install --save-dev commitizen @commitlint/{cli,config-conventional}
# For Windows:
    npm install --save-dev commitizen @commitlint/config-conventional @commitlint/cli

# Configure commitlint to use conventional config
    echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
 
# Add hook
 npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
# or
 yarn husky add .husky/commit-msg 'yarn commitlint --edit $1'

編碼規(guī)范
ESLint 是?個按照規(guī)則給出報告的代碼檢測?具 ,使?它可以避免低級錯誤和統(tǒng)?代碼?格,這對公司團隊開發(fā)?常實?。

以React / Vue3 Cli項?中配置ESLint為例,?概說明下基本配置以及作?

// 需要安裝 babel-eslint 
// babel-eslint 將不能被常規(guī)linter解析的代碼轉(zhuǎn)換為能被常規(guī)解析的代碼
npm install --save-dev eslint babel-eslint

// 進?初始化,如果選擇airbnb,會?動安裝部分相關(guān)的插件
eslint --init

// 進?初始化后,會在項?根?錄下?成?個 .eslintrc.js ?件

React 版本 安裝完后會 package.json 一般會添加如下?個依賴包

  "eslint": "^7.29.0",
  "babel-eslint": "^10.1.0",  
  "eslint-config-airbnb/react-app": "^18.2.1", 
    // 使用create-react-app創(chuàng)建的 默認將使用 eslint-config-react-app
  "eslint-plugin-import": "^2.23.4",
  "eslint-plugin-jsx-a11y": "^6.4.1",
  "eslint-plugin-react": "^7.24.0",
  "eslint-plugin-react-hooks": "^4.2.0",

Vue 版本 由于是通過vue-cli創(chuàng)建的,所以會額外增加 @vue/cli-plugin-eslint

"eslint": "^7.29.0",
"babel-eslint": "^10.1.0", 
@vue/cli-plugin-eslint
eslint-plugin-vue

通過 eslint --init 后會自動生成 .eslintrc.js

React

module.exports = {
  root: true,
  env: {
    browser: true,
    es6: true,
    node: true,
  },
  extends: ["react-app"],
  globals: {},
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: "module",
    parser: "babel-eslint",
  },
  plugins: [],
  rules: {
    eqeqeq: 1,
    "no-unused-vars": 1,
    "no-var": 2,
    "no-debugger": process.env.NODE_ENV === "production" ? 2 : 1,
  },
};

Vue

module.exports = {
  root: true,
  env: {
    browser: true,
    es6: true,
    node: true
  },
  extends: ['plugin:vue/vue3-essential', 'eslint:recommended'],
  globals: {
    PhotoSwipe: 'readonly',
    PhotoSwipeUI_Default: 'readonly'
  },
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
    parser: 'babel-eslint'
  },
  plugins: ['vue'],
  rules: {
    eqeqeq: 1,
    'no-unused-vars': 1,
    'no-var': 2,
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 1
  }
}

可以看到兩個項目使用的rules規(guī)則相同,只是針對不同語法糖的格式校驗,由于本身項目是通過cli項目創(chuàng)建的,所以使用cli默認封裝的lint插件會更合適。

相關(guān)變量含義

  1. globals :全局變量,如果你的項??到其他?些?定義的全局變量, "fetch": false 這樣配置,true 和 false 代表可不可以被修改。
  2. env : Environments,指定代碼的運?環(huán)境。不同的運?環(huán)境,全局變量不?樣,指明運?環(huán)境 這樣ESLint就能識別特定的全局變量。同時也會開啟對應(yīng)環(huán)境的語法?持,例如:es6。這些環(huán)境不是相互排斥的,因此可以?次定義多個。
  3. extends : ESLint 不需要??定義?量的規(guī)則,因為很多規(guī)則已被分組作為?個規(guī)則配置。
  4. parserOptions : ESLint ?持 ECMAScript 5 語法。你可以覆蓋該設(shè)置,以啟?對 ECMAScript 其它版本和 JSX 的?持。通過使?解析器選項,可以覆蓋該設(shè)置以?持其他ECMAScript版本以及 JSX。
  5. parser : ESLint 默認使? Espree 作為其解析器,但它并不能很好的適應(yīng) React 環(huán)境,所以剛才安裝了 babel-eslint ?來代替默認的解析器,在配置?這么寫 "parser": "babel-eslint"
    https://github.com/eslint/espree
  6. plugins : 顧名思義就是插件,插件是單獨的npm包,命名?般以eslint-plugin開頭,寫的時候?字符串數(shù)組的形式,可以省略eslint-plugin開頭。plugins?般包含?個或多個規(guī)則配置,也可以在 extends 中引?。
  7. rules : 這?可以對規(guī)則進?細致的定義了, 覆蓋之前前?說的extends/plugins中定義的規(guī)則 。規(guī)則等級有三種:

a. "off" / 0: 關(guān)閉規(guī)則

b. "warn" / 1: 打開規(guī)則,作為警告。

c. "error" / 2: 打開規(guī)則,作為錯誤( 錯誤級別的校驗將會中斷提交)

配合 husky 校驗

  1. 在 package.json ?件中加?以下代碼
 "scripts": {
    "lint": "echo 'eslint 檢查開始...'  && eslint ./src --ext  .js .vue --fix"
 }

命令??具, 在根?錄下?動執(zhí)? npm run lint , 即會檢測代碼

  1. 使? pre-commit git hook

pre-commit Hook是在Git提交之前?來?動檢查待提交代碼是否有錯誤的?具。

使?以下命令添加相關(guān)鉤?

npx husky add .husky/pre-commit "npm run lint"

這樣就可以對指定目錄下的文件進行l(wèi)int校驗

添加 Prettier 統(tǒng)?格式化代碼?格
Prettier的中?意思是“漂亮的、機靈的”,也是?個流?的代碼格式化?具的名稱,它能夠解析代碼,使?你??設(shè)定的規(guī)則來重新打印出格式規(guī)范的代碼。eslint 和 prettier 可以配合使?,也可以單獨使?。下?我們主要講eslint和prettier結(jié)合使?

ESLint 已經(jīng)有了代碼格式化的功能,為什么還需要使?Prettier呢?
各種 Linters 是按照規(guī)則(Rules)去檢查代碼的,遇到不符合規(guī)則的代碼就會提?你,有的規(guī)則還能?動幫你解決沖突。

這些規(guī)則分為兩類:

? Formatting rules

例如 ESlint 的 max-len 規(guī)則,設(shè)置單??度不能超過 80 字符。ESLint會提?你去修復。? Prettier 則不會這么?煩,它根本不管你之前符不符合什么規(guī)則,都先把你的代碼解析成 AST,然后 按照它??的?格給你重新輸出代碼。

換句話說,Prettier 對應(yīng)的是各種 Linters 的 Formatting rules 這?類規(guī)則,并且更加豐富和完善。?且你?了 Prettier 之后,就不會再違反這類規(guī)則了!不需要你???動修改代碼。

? Code-quality rules

例如 ESLint 的no-unused-vars規(guī)則,不允許沒?的變量定義出現(xiàn)。這種錯誤只能????去? 動修復。Prettier 對這類規(guī)則束??策。?且這類規(guī)則也正是各種 Linters 的重點,因為它們真的能幫你發(fā)現(xiàn)很多低級的 Bug。

那么既要讓 Prettier 幫你格式化代碼,還想讓 Linters 幫你挑出潛在的 Code-quality 類錯誤,怎么辦?就需要 Prettier 和 Linters 配合使?。

Prettier 和 Linters 的整合需要做的兩件事

  1. 禁? Linters ??的 Formatting rules,讓 Prettier 接管這些職責。
  2. 讓 Linters 執(zhí)?時?先調(diào)? Prettier 格式化,然后再檢查 Code-quality 類規(guī)則。這是 由 Linters 的 Plugin 實現(xiàn)的。

Prettier配置

npm i --D --save-exact prettier

npm i -D eslint-plugin-prettier eslint-config-prettier


// vue 需要額外安裝
npm i -D @vue/eslint-config-prettier
  1. prettier 代碼格式化核?

  2. eslint-plugin-prettier 插件,可以讓eslint使?prettier規(guī)則進?檢查,并使? --fix 選項。像之前的格式不對時,eslint提?的紅線。

  3. eslint-config-prettier 插件,之前說了 eslint 也會檢查代碼的格式,這個插件就是關(guān)閉eslint 所有不必要或可能跟prettier產(chǎn)?沖突的規(guī)則。讓prettier接?代碼的格式校驗

結(jié)合.eslintrc.js配置

// vue 中
extends: [... '@vue/prettier'],

 
 // React 
  
extends: [...  "plugin:prettier/recommended"],  
  
  
 以上配置做如下三件事:

  1. 使eslint-plugin-prettier?效
  2. 不符合prettier/prettier的規(guī)則,會報錯。就是代碼中提?的紅線。
  3. 使eslint-config-prettier?效。就是會覆蓋eslint中與prettier沖突的配置。

配置.prettierrc.json

{
    "tabWidth": 2,   // tab占?的字符數(shù)
    "trailingComma": "none", // 最后?個對象元素加逗號
    "semi": false, // 是否句末加分號
    "singleQuote": true,   // 是否?單引號
    "bracketSpacing": true // 是否對象,數(shù)組加空格
}

使? lint-staged 只校驗暫存區(qū)?件

lint-staged 是?個在git暫存?件上運?linters的?具,如果不使?這個?具的話,不管修改了?個?件在提交的時候會給所有?件執(zhí)??次lint檢查,這樣對于龐?的項?來說會浪費?量的校驗時間。

npx mrm lint-staged

使?以上命令它將根據(jù) package.json 依賴項中的代碼質(zhì)量?具來?動安裝和配置husky和 lint-staged 。

  1. ?動在husky?件下 創(chuàng)建 pre-commit ?件:
  #!/bin/sh
  . "$(dirname "$0")/_/husky.sh"

  npx lint-staged
  1. ?動在package.json?件中添加如下配置:
"lint-staged": {
     "*.js": "eslint --cache --fix"
}

有了以上基礎(chǔ)配置后,在commit的時候就只對修改的?件進?lint和修復 。但上面lint-staged配置還不夠,因此可以擴展如下:

 "lint-staged": {   // lint-staged 配置
      "*.{js,jsx,md,vue}": [
         "prettier --write",
         "eslint --cache --fix",
         "git add"
      ]
}

這? lint-staged 的配置是:
在 git 的待提交的?件中,在所有?錄下的符合的文件都要執(zhí)?三條命令。

? 第?條命令 prettier --write

? --write :默認prettier是直接標準輸出到終端的,這個配置代表直接格式化改寫?件。

? 關(guān)于prettier的還有?些配置參考這? prettier 配置文檔
https://prettier.io/docs/en/options.html

? 第三條命令, 將處理過的代碼重新 add 到 git 中。

最終在使?Git提交代碼的時候,會?動檢測暫存區(qū)里的代碼文件并進?格式化,如果有l(wèi)int錯誤(error)會終?當前的commit push
添加 .editorconfig ?件覆蓋編輯器?格

配置?個 .editorconfig ?件,在其中設(shè)置好要遵守的代碼規(guī)范,放在項?的根?錄下,就能夠 在?乎所有的主流 IDE 和編輯器中復?了,并將 .editorconfig ?件也提交到版本控制系統(tǒng)中, 這樣就不需要針對不同 IDE 和編輯器再單獨進?設(shè)置了。

 // 表?是最頂層的配置?件,發(fā)現(xiàn)設(shè)為true時,才會停?查找.editorconfig?件
  root = true

  // * 表?所有的?件
  [*]
  //  對于所有的?件 始終在?件末尾插??個新?
  insert_final_newline = true
  // 對于所有的?件,設(shè)置?件字符集為utf-8
  charset = utf-8
  // 設(shè)為true表?會去除換???的任意空?字符
  trim_trailing_whitespace = true
  // ?尾?件格式(Unix、DOS、Mac),值為lf、cr和crlf
  end_of_line = lf

  // 對于特定?件
  [*.{js,json,ts,tsx,vue}]
  // 設(shè)置縮進?格(tab是硬縮進,space為軟縮進)
  indent_style = space
  // ??個整數(shù)定義的列數(shù)來設(shè)置縮進的寬度
  indent_size = 2
  // 使?空格替代tab,并且?個tab會被替換為2個空格。

編輯器擴展(VSCode)

? 代碼?格檢查擴展: ESlint ;

? 代碼?格格式化擴展: Prettier ;

? 編輯器設(shè)置擴展: EditorConfig for VS Code ;

關(guān)于 VScode 相關(guān)校驗插件參考
https://juejin.cn/post/6844904099092119565

參考文檔
1、Git提交信息規(guī)范
https://github.com/lingz1/standard/blob/master/code-repository/git-commit-message.md
2、ESlint 官方配置文檔
https://eslint.org/docs/user-guide/configuring/
3、ESlint 中文文檔
https://cn.eslint.org/docs/user-guide/configuring
4、EditorCOnfig 配置屬性介紹
https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties
5、ESlint + prettier 配置及介紹
https://www.cnblogs.com/qiqi715/p/10247598.html
6、Lint _ stagged 使用教程
https://www.cnblogs.com/jiaoshou/p/12250278.html
7、vue+ vetur+eslint + prettier 自動格式化功能
https://juejin.cn/post/6844904099092119565
8、寫React Hooks 前必讀
https://zhuanlan.zhihu.com/p/113216415

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容