eslint+prettier+husky+lint-staged 統一前端程式碼規範

eslint+prettier+husky+lint-staged 統一前端程式碼規範

遵循編碼規範和使用語法檢測,可以很好的提高程式碼的可讀性,可維護性,並有效的減少一些編碼錯誤。

1、終極目標

團隊中的所有開發人員用一套程式碼規範規則,並且無需我們花太大的精力去為了格式而格式。希望有一套自動化工具,幫我們檢測程式碼是否規範,如果不規範,則自動能夠幫我們按照既定規範格式化。

實現這一目標需解決的問題:

1、程式碼規範落地難:面對開發規範經常面臨的現狀是很難落地,總是「拆東牆補西牆」,歸根結底在於需要工具去強行保證程式碼必須經過程式碼開發規範的掃描;

2、低品質程式碼帶入線上應用:在開發現狀中開發人員可以簡單的執行git push操作將本地程式碼帶入遠程分支上,如果程式碼品質低下就很容易對線上應用品質埋下隱患,最好的方式本地進行commit的時候,最起碼需要保證當前程式碼能夠滿足團隊制定的開發規範,如果不通過,commit都無法成功,這樣能夠從最源頭保證程式碼品質;

3、程式碼格式難統一:現狀團隊開發成員程式碼格式都有很大的不同,有些人字元串喜歡用雙引號,有的人喜歡使用單引號等等問題,如果程式碼格式化問題不統一,互相查看其它人程式碼很累,甚至程式碼格式錯亂,嚴重影響程式碼可讀性,無疑也增加了團隊內的溝通成本,針對這樣情況,需要一種工具能夠保證團隊內程式碼的格式是一致;

4、程式碼品質文化難落地:過引入程式碼品質工具,在開發過程中能夠時刻對自身程式碼品質進行約束,逐漸培養自身對程式碼品質有「潔癖」的開發觀念,同時也會成為團隊乃至自身對品質文化落地的一個抓手;

面對以上問題,eslint+prettier+husky+lint-staged 這幾個工具能夠有效解決上述問題。

2、eslint 配置

ESLint 是一個Javascript Linter,幫助我們規範程式碼品質,提高團隊開發效率。

避免程式碼錯誤、寫出最佳實踐、規範變數使用方式、規範程式碼格式;

社區比較知名的程式碼規範,eslint 配合這些程式碼規範,能夠檢測出程式碼潛在問題,從而提高程式碼品質。

官方提供了3種規範:

eslint-config-google:Google標準

eslint-config-airbnb:Airbnb標準,它依賴eslint, eslint-plugin-import, eslint-plugin-react, and eslint-plugin-jsx-a11y等插件,並且對各個插件的版本有所要求

eslint-config-standard:Standard標準,它是一些前端工程師自定的標準,

目前來看,公認的最好的標準是Airbnb標準。

2.1 默認配置

使用 Create React App 創建的 React 應用,默認安裝了ESLint依賴,package.json文件中的 eslintConfig 屬性只提供了用於發現常見錯誤的最小規則集。

 "eslintConfig": {
       "extends": "react-app"
  }

2.2 自定義配置

2.2.1 在根目錄下創建 .eslintrc.json 文件,完成一些基礎配置,程式碼如下:
{
   // env:你的腳本將要運行在什麼環境中
   "env": {
       "browser": true,
       "es6": true,
       "jquery":true
  },
   // globals:腳本在執行期間訪問的額外的全局變數
   "globals": {
       "$": true,
       "process": true,
       "__dirname": true
  },
   // 指定ESLint使用的解析器,默認是Espree
   "parser": "babel-eslint",
    // 指定想要支援的 JavaScript 語言選項
   "parserOptions": {
       "ecmaFeatures": {
           "experimentalObjectRestSpread": true,
           "jsx": true,
           "modules": true
      },
       "sourceType": "module",
       "ecmaVersion": 7
  },
    //讓eslint支援 JSX start
   "plugins": ["react"],
   // 繼承已啟用的規則
   "extends": ["eslint:recommended"],
   // 啟用的規則及其各自的錯誤級別。自定義啟用或關閉一些規則
   "rules": {
       "react/jsx-uses-react": 1,
       "no-unused-vars": 0, //變數聲明未被使用校驗
       "no-empty": 0,
       "quotes": 0, //單引號
       "no-console": 0 //不禁用console
  }
}

想具體了解各個配置什麼意思的,請參考官網://eslint.cn/docs/user-guide/configuring

2.2.2 配置完成,測試效果

完成上述配置之後,只會影響編輯器和 IDE 檢測與規則不符的程式碼(比如在vscode中與規則不符的程式碼有紅色的下劃波浪線),不會在控制台和瀏覽器中出現相關提示。

image-20200730155438109

2.3 擴展 ESLint 配置

因我們項目使用react-app-rewired 對 Create React App 進行了自定義配置,所以需要修改config-overrides.js,修改後的程式碼如下:

const { override, fixBabelImports, addWebpackAlias,useEslintRc } = require('customize-cra')
const path = require('path')

//重寫配置
module.exports = override(
 // 配置路徑別名
 addWebpackAlias({
   '@': path.resolve(__dirname, 'src')
}),
 // antd按需載入
 fixBabelImports('import', {
   libraryName: 'antd',
   libraryDirectory: 'es',
   style: 'css'
}),
 //啟用eslintrc配置文件
 useEslintRc()
)

經過上述配置後,eslint 生效,npm start 會在控制台和瀏覽器中出現相關錯誤提示:

控制台報錯:

image-20200730161551116

瀏覽器報錯:

image-20200730162908826

2.4 忽略特定的文件或目錄

在項目根目錄創建一個 .eslintignore 文件告訴 ESLint 去忽略特定的文件和目錄。.eslintignore 文件是一個純文本文件,其中的每一行都是一個 glob 模式表明哪些路徑應該忽略檢測。例如:

build/*.js
public
dist
node_modules
config
config-overrides.js
src/serviceWorker.js
prettierrc
.DS_Store
.eslintrc.json
node_modules

2.5 eslint fix自動修復

eslint –fix 可以根據規範對程式碼的部分低級問題進行更正,如:缺少/多餘分號,縮進格式等。

能夠修復的規範問題比較有限,需要較大變動才能修復的規範問題,eslint 無法自動修復。如:單行不能超過 80 個字元。

自動修復src文件夾下.js文件和.jsx文件部分規範問題,命令如下:

eslint --fix --ext .js --ext .jsx src/

3、eslint集成prettier

prettier 是一個「武斷的」(官網用詞: opinionated )程式碼格式化工具。(只關心程式碼格式,統一程式碼風格)

根據規範,自動格式化程式碼,具有比 eslint auto-fix 更加強大的程式碼規範性修復能力。

官網://prettier.io/

3.1 安裝prettier

根據 prettier官方建議,Prettier 版本升級後可能會有風格變化,故應當鎖定 Prettier 的版本號。

npm install prettier --save-dev

3.2 安裝eslint-plugin-prettier

ESLint插件,eslint-plugin-prettier 作為一個 ESLint的規則運行,並報告不同的單個ESLint問題。

將 prettier 的能力集成到 eslint 中。按照 prettier 的規則檢查程式碼規範性,並進行修復。

npm install eslint-plugin-prettier --save-dev

修改.eslintrc.json文件:

第一種方式:

//插件增加prettier
"plugins": ["react","prettier"],
//繼承規則增加prettier
"extends": ["eslint:recommended","prettier"],
// 不符合 prettier 規則的程式碼,要進行錯誤提示(紅線)
"rules":{
 "prettier/prettier":"error"
},

第二種方式:

//相當於上面三個操作
{
   "extends": ["eslint:recommended","plugin:prettier/recommended"]
}

註:extends的含義

告訴 eslint,根據指定的規範,去檢查指定類型的文件。如上例:

根據 eslint:recommended + prettier 規範,去檢查 js 程式碼。

當某一類型的文件,被制定了不止1個規範,存在某些規範衝突時,後面的會覆蓋掉前面的。

3.3 安裝eslint-config-prettier解決衝突(如果存在衝突)

npm install  eslint-config-prettier --save-dev

作用:解決衝突,讓所有可能會與 prettier 規則存在衝突的 eslint rule 失效,並使用 prettier 的規則進行程式碼檢查。相當於用 prettier 的規則,覆蓋掉 eslint:recommended 的部分規則。

後面 prettier 格式化,也會根據這個規則來。因此,不會再有衝突。

3.4 prettier自動格式化

自動格式化src目錄下的文件,命令如下:

prettier --write 'src/**/*.{js,css,jsx,html}'

3.5 自定義配置

根目錄下新建.prettierrc文件,可根據需要進行一些自定義配置,示例如下:

{
  "printWidth": 100,
  "singleQuote": true,
  "trailingComma": "es5",
  "tabWidth": 4,
  "semi": true,
  "jsxBracketSameLine": false,
  "jsxSingleQuote": true,
  "useTabs": false
}

【注】這裡的 .prettierrc,具有格式化規則的最高優先順序。

3.6 忽略特定的文件或目錄

在根目錄下新建.prettierignore文件,直接添加文件名和目錄名,與.eslintignore類似,示例如下:

build/*.js
public
dist
node_modules
config
config-overrides.js
src/serviceWorker.js
prettierrc
.DS_Store
.eslintrc.json
node_modules

prettier格式化的時候會忽略該配置文件中的文件或目錄

4、編輯器自動格式化程式碼

4.1 使用編輯器快捷鍵,格式化程式碼

以 vscode 為例:shift + option + f,默認格式化規則選擇 prettier,即可完成程式碼格式化。

4.2 保存程式碼自動格式化

同樣以 vscode 為例,打開你的 settings.json,添加下面這句話:

"editor.formatOnSave": true

至此jsx,js、json、scss等文件,均可實現自動格式化。文件格式化規則,遵從我們在 .eslintrc.json 里的配置。也就是,使用我們的 prettier 插件規則去格式化。

5、規範檢查增強(husky + lint-staged)

在 git commit 之前,先強制執行prettier格式化(防止某些成員開發期間不開啟編輯器格式化)、再檢查程式碼規範,如果檢查不通過、阻止提交。

5.1 安裝 husky

npm install husky --save-dev

husky: git hook工具。這裡主要用它防止不規範程式碼被commit、push、merge等等。

5.2 安裝 lint-staged

npm install lint-staged --save-dev

Lint-staged提供了一個關鍵的功能,它能找到所有被git staged的文件,而不是工程下面所有的文件,然後通過管道交給Prettier做格式化。

5.3 配置husky和lint-staged

在package.json新增配置,如下:

    "husky": {
       "hooks": {
           "pre-commit": "lint-staged"
      }
  },
   "lint-staged": {
       "*.{js,jsx}": [
           "prettier --write",
           "eslint",
           "git add ."
      ]
  },

precommit由Husky處理,它會依照配置在把程式碼提交到倉庫前運行lint-staged(也可以配置其他命令)。

Lint-staged再找到屬於它自己的配置部分,即lint-staged鍵下面的配置。

上面的配置,git commit 之前,所有staged狀態的,且擴展名是.js和.jsx的文件都會自動使用 prettier 格式化。格式化後,自動檢查所有文件,是否全部符合 eslint 規範。

存在不符合規範的程式碼,git commit 將被終止。

修改程式碼,進行測試,結果如下:

image-20200731105406379

與預期完全一致,如果有不符合程式碼規範或語法錯誤的程式碼提交不了。輸出錯誤資訊,點擊可定位到錯誤位置。

為何一定要用lint-staged?

為什麼一定要用lint-staged,用Husky直接調用npm腳本不更簡單么。配置如下:

 "scripts": {
       "start": "react-app-rewired start",
       "build": "react-app-rewired build",
       "test": "react-app-rewired test",
       "fix": "eslint --fix --ext .js --ext .jsx src/",
       "format": "prettier --write 'src/**/*.{js,css,jsx,html}'"
  },
 "husky": {
       "hooks": {
           "pre-commit": "npm run format && npm run fix"
      }
  },

如果是這樣配置的話,就沒有必要用lint-staged了。因為,這樣的配置會把prettier,eslint應用到所有匹配.js,.jsx的文件上,而不是僅staged狀態的文件。

5.4 husky擴展

5.4.1、單元測試檢測

把單元測試加入到預提交檢查中,保證只有通過了單元測試才正式提交程式碼到倉庫。

配置如下:

 "husky": {
       "hooks": {
           "pre-commit": "lint-staged && npm test"
      }
  },

只是配上這個命令是不能跑的,還是要集成Jest單元測試框架,編寫單元測試程式碼。

5.4.2、commit messages規範與約束

git每次提交程式碼,都必須寫commit message(提交說明),用來說明本次提交的目的,否則不允許提交。

commit message的寫法規範有許多,目前使用最廣的,比較合理和系統化的一種規範:Angular 規範。

工具commitizen/cz-cli會產生規範性的提示語句,幫助我們形成規範的commit message。

工具commitlint用於檢查我們的commit message是否符合提交規範,如果不符合,則直接拒絕提交。

huskey配置如下:

 "husky": {
   "hooks": {
     "commit-msg": "commitlint -e $GIT_PARAMS"
  }
}

5.5 husky不起作用怎麼辦

配置完成後 git commit 不起作用。

解決方案:確認 .git/hooks/* 下的文件,刪除對應命令的文件,重新執行安裝即可。

6、總結

規範僅僅通過人為的培訓或者文檔來約束,是不可靠的。

能通過工具約束的盡量通過工具約束,而不要依靠默契和口頭約定。

通過使用這些工具能夠在一定程度上保證應用的品質問題,並能達到事半功倍的效果。

至此我們開頭的終極目標已實現~~!

7、引用

//www.jianshu.com/p/56bee5bf1568

//www.jianshu.com/p/f0d31f92bfab

//segmentfault.com/a/1190000009546913

//www.cnblogs.com/zhoumingjie/p/11582862.html

//www.cnblogs.com/jiaoshou/p/12222665.html

還有引用其它文章一些內容,不再一一列舉了。。。。