前端codeLint-- 爲項目集成ESLint、StyleLint、commitLint實戰和原理

導讀

Code Lint是前端工程化中的一個重要環節(what is code lint?),它能夠幫助咱們在部署代碼到生產環境以前及時發現錯誤並糾正它們,也能夠規範咱們的編碼習慣,讓團隊的代碼風格保持統一。css

Code Lint的工做原理是藉助一些lint工具對代碼進行靜態分析,並在合適的時機觸發校驗,提示錯誤。html

Note:本文可能沒法覆蓋全部知識點,如有知識盲區請主動查閱補齊,也能夠在文章下方留言交流。前端

1、都有哪些Lint?

隨着nodejs和前端工程化的發展,前端圈內產出了不少成熟的Lint工具,主要包括:vue

  • eslint 規範並校驗 ECMAScript/JavaScript code的編寫
  • tslint 規範並校驗 TypeScript code的編寫
  • stylelint 規範並校驗css/scss/less code的編寫
  • commitlint 負責校驗commit msg是否符合規範
  • prettierbeautifyjs 統一代碼排版格式

除此以外,咱們還須要一些輔助的工具:node

  • husky 可以監聽git hooks的nodejs包,讓nodejs開發者處理git hooks任務變得更加容易
  • lint-staged 能夠將git「已暫存(staged)」的文件做爲參數傳入你要執行的shell script之中

讀到此處,你可能對這些工具的做用和用法仍然心存疑惑,不過不要緊,你們暫且只須要知道咱們將用這些工具對咱們的代碼進行各環節的嚴格的校驗便可,接下來讓咱們深刻了解它們。react

2、集成commit lint

相信你們對Git並不陌生,不知你們是否有過這種經歷,本身提交git commit msg本身卻看不懂。在小的團隊裏,可能咱們更注重的是業務產出,並不在意這些細節。隨着團隊的壯大,commit msg規範化相當重要,他意味着咱們是否清楚本身和同事對代碼幹了什麼,在代碼排錯、回滾甚至是甩鍋時起到了關鍵性做用。linux

本着「工具比人更可靠」的原則,咱們指望經過在項目中集成一些工具,從而實如今執行git commit -m 'msg'時可以自動的對msg內容進行校驗,無需額外執行其餘命令,huskycommitlint剛好能解決咱們這個痛點。webpack

2.一、理解git hooks 和 husky

在正式集成commitlint以前,先要介紹一下git hooks, 顧名思義hooks爲「鉤子」之意,它是「發佈訂閱模式」的一種實現,和前端中的DOM事件(click、hover等)類似,Git也預先定義了一些「事件鉤子」如「commit-msg」、「pre-commit」等,當咱們執行對應的Git操做時會觸發它們,從而通知訂閱該事件的shell script文件處理咱們要進行的任務,這些shell腳本文件存放在項目根目錄下的.git/hooks 目錄中,如圖所示:


git

image

咱們能夠經過編寫這些shell script文件定製咱們的校驗任務,但前端工程師大多對linux/windows shell並不擅長,這和咱們平時的工做重心有關, 所以咱們經過編寫git hooks腳原本優化前端工做流的這條道路十分艱難。Nodejs改變了這一切,它讓JavaScript擁有了控制「操做系統」的能力,你只須要安裝nodejs包husky,它會幫咱們自動生成.git/hooks目錄下的shell script,咱們即可以很輕鬆的使用更熟悉的Nodejs處理git hooks任務,而無需關注shell script的實現細節。es6

執行下面命令, 在開發環境中安裝husky,以下所示:

npm install husky --save-dev

在項目根目錄下package.json文件中添加以下配置,並在hooks字段下添加git hooks監放任務配置, 以下:

// 這是NPM原生支持的腳本執行定義,當執行「npm run 腳本名」時執行
"scripts": {
    "test": "node test.js"
},
// 這是husky擴展的腳本執行的定義方式,當對應git hooks觸發時執行
"husky": {
    "hooks": {
      // 能夠執行一個js文件,將控制權轉移給咱們更熟悉的nodejs
      "pre-commit": "node heihei.js", 
      // 也能夠調用其餘腳本或者執行一段原生shell命令
      "commit-msg": "npm run test && echo succeed" 
    }
}

上面的配置只做爲測試例子之用,無需真正集成到項目中,你們能夠先寫一個小demo嘗試一下,加深一下對git hookshusky的理解。

2.二、安裝配置commitlint

固然不要忘記咱們今天的主角commitlint,咱們須要利用它的cli(command-line interface)能力,配置一套屬於咱們本身的git commit msg 校驗規則, 首先安裝 @commitlint/cli@commitlint/config-conventional ,以下:

npm install @commitlint/cli --save-dev  
npm install @commitlint/config-conventional --save-dev
  • @commitlint/cli 是commitlint提供的命令行工具,安裝後會將cli腳本放置在./node_modules/.bin/目錄下
  • @commitlint/config-conventional是社區中一些共享的配置,咱們能夠擴展這些配置,也能夠不安裝這個包自定義配置

接下來是初始化@commitlint/cli的配置文件,在項目根目錄建立名爲commitlint.config.js的文件,代碼以下:

/**
* feature:新功能
* update:更新某功能
* fixbug:修補某功能的bug
* refactor:重構某個功能
* optimize: 優化構建工具或運行時性能
* style:僅樣式改動
* docs:僅文檔新增/改動
* chore:構建過程或輔助工具的變更
*/
module.exports = {
  extends: [
    '@commitlint/config-conventional'
  ],
  rules: {
    'type-enum': [2, 'always', [
      'feature', 'update', 'fixbug', 'refactor', 'optimize', 'style', 'docs', 'chore'
    ]],
    'type-case': [0],
    'type-empty': [0],
    'scope-empty': [0],
    'scope-case': [0],
    'subject-full-stop': [0, 'never'],
    'subject-case': [0, 'never'],
    'header-max-length': [0, 'always', 72]
  }
};
// 這些配置是什麼意思?請自行查閱commitlint文檔

最後咱們須要在package.json中配置上咱們的husky的選項,代碼片斷以下:

"scripts": {
    // 忽略
    "build": "node build/build.js" 
},
"husky": {
    "hooks": {
      // 重點
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 
    }
}

這段配置告訴了git hooks ,當咱們在當前項目中執行 git commit -m '測試提交' 時將觸發commit-msg事件鉤子並通知husky,從而執行 commitlint -E HUSKY_GIT_PARAMS命令,也就是咱們剛開始安裝的./node_modules/.bin/commitlint,它將讀取commitlint.config.js配置規則並對咱們剛剛提交的測試提交這串文字進行校驗,若校驗不經過,則在終端輸出錯誤,commit終止。

2.三、commitlint工做原理

簡單閱讀了一遍huskycommitlint的源碼,大概的執行過程是這樣的,如圖所示:

image

若是上面這張圖看不太懂,這不要緊,但你至少要看懂下面這張圖:

image

上面咱們闡述了git hooks, huskycommitlint的工做流程, 理解husky的工做原理很是重要, 後面還會用到它,請你們務必理解。

3、集成ESLint

你們知道JavaScript語法存在一些設計缺陷,編碼風格也能夠各不相同,舉一個最簡單的例子,在定義一個string時小A同窗喜歡用雙引號,小B同窗習慣用單引號,咱們不討論誰的風格更加合理,但咱們至少應該統一它,這將減小咱們代碼的管理成本。

在咱們的項目中集成eslint已經成爲解決這個問題的成熟方案,能夠說任何中大型項目都應該使用ESlint來約束咱們的JavaScript代碼,接下來看一下咱們如何在webpack構建的vue項目中集成eslint

3.一、安裝配置eslint-cli

首先在開發環境下安裝eslint, 代碼以下所示:

npm install --save-dev eslint

commitlint同樣, 這會在./node_modules/.bin/目錄下建立一個名爲eslint.cmd的執行腳本(在windows系統下生成的是cmd腳本,在linux下就是sh腳本咯,這由nodejs自動幫你處理),eslint.cmd是eslint包提供的cli工具。

在項目根目錄建立名爲.eslintrc.js的文件,eslint.cmd執行時會默認讀取該文件中的配置,初始配置以下:

module.exports = {
  root: true,
  env: {
    es6: true,
    node: true
  },
  plugin:[],
  extends: [],
  rules:[]
}

完成上面配置,咱們就可使用eslint的cli功能對咱們的js代碼進行校驗咯,在根目錄終端輸入下面命令,校驗當前目錄下全部js文件,並修其中復可自動修復的錯誤,代碼以下:

./node_modules/.bin/eslint ./** --fix

若是你的npm版本在5.2版本以上,可使用npx來執行./node_modules/.bin下面的腳本更,這樣加方便,以下:

npx eslint ./** --fix

從下圖能夠看出,eslint已經生效:

image

3.二、爲eslint擴展配置和規則

固然僅僅是這些還不夠,咱們須要個性化的集成一些其餘輔助的包或者本身配置一套屬於本身的eslint環境,讓它更符合咱們項目的須要。

npm上有很多社區提供的共享配置,咱們能夠選擇一種適合咱們的配置,直接集成過來,好比咱們在Github中搜索「eslint-config-」 則會發現有不少這種開源的共享配置可選,如圖:

image

你們能夠根據項目的須要,選擇適合的配置,此處咱們採用eslint-config-standard這個共享配置,執行安裝:

npm install --save-dev eslint-config-standard

修改配置文件以下:

module.exports = {
  root: true,
  env: {
    es6: true,
    node: true
  },
  extends: [
    'standard'
  ]
}

讓咱們深刻 eslint-config-standard包內部一探究竟,看它到底作了什麼,下面爲它內部的部分代碼段:

image

經過上圖,咱們能夠發現,eslint-config-standard 內部同時擴展了eslint-plugin-importeslint-plugin-nodeeslint-plugin-promise等插件,它們的做用分別是:

  • eslint-plugin-import 使eslint支持對import/export 的識別和校驗
  • eslint-plugin-node 使eslin支持對nodejs原生模塊的識別和校驗
  • eslint-plugin-promise 使支持對promise最佳實踐的校驗

Note: 若是你們沒有使用 eslint-config-standard, 但還想支持上面的這些功能,請本身安裝集成, 此處就再也不展現自定義集成的代碼。

3.三、讓eslint支持vue的識別和校驗

若是你是vue項目,還須要安裝下面這個包:

npm install --save-dev eslint-plugin-vue

官網對eslint-plugin-vue的介紹「 This plugin allows us to check the <template> and <script> of .vue files with ESLint.」集成這個插件,將使eslint擁有處理.vue文件的能力。

此外咱們還須要安裝 babel-eslint 包,安裝命令以下:

npm install --save-dev babel-eslint

babel-eslint是一款es語法解析器,使用它解析代碼能夠提供一些es實驗階段語法的校驗支持, 最後咱們完整的eslint配置以下:

module.exports = {
  root: true,
  env: {
    es6: true,
    node: true
  },
  parserOptions: {
    parser: 'babel-eslint'
  },
  extends: [
    'plugin:vue/essential',// 識別vue語法,並提供vue默認校驗規則
    'standard'
  ],
  rules:[]// 你要覆蓋的一些規則
}

若是你們還須要修改配置或者須要其餘包的集成,請本身去完成擴展哦,這是對你們動手能力的小小考驗。

4、集成StyleLint

stylelint和eslint有類似的做用和原理,只不過校驗對象不一樣,它主要用來校驗你的樣式代碼,如css、scss、less等,這裏就不作過多介紹,相信聰明的你能夠從剛剛eslint的文章中作到觸類旁通,直接上代碼:

npm install --save-dev stylelint
npm install --save-dev stylelint-config-standard

在本地建立名爲.stylelintrc.js的配置文件,配置以下:

"use strict";
module.exports = {
  ignoreFiles: [
    "./**",
    "!./client/views/**/*.vue",
    "!./client/views/**/*.scss",
    "!./client/styles/**/*.scss",
    "!./client/plugin/**/*.vue",
    "!./client/plugin/**/*.scss"
  ],
  extends: ["stylelint-config-standard"],
  rules: {
      // 這裏能夠覆蓋一些配置
  }
};

測試一下校驗能力,項目根目錄輸入代碼:

npx stylelint ./ --fix

上面代碼會默認讀取.stylelintrc.js的配置,忽略你不須要校驗的目錄。

5、格式化代碼是否要加hard Lint?

咱們知道eslint能夠約束JavaScript的用法,可是它約束代碼排版格式的能力卻很是有限,同時它不能約束css、scss、html等,若想爲咱們的代碼格式化加上強約束,咱們還須要像相似prettierbeautify這樣的工具, 特別是prettier它能夠配合eslint使用。

prettierreactjsx支持的很好,但遺憾的是prettier格式化vue的能力並無那麼強大,可配置項也是少的可憐,阿三沒有采用,而且考慮到工具鏈的調整須要漸進完善,阿三我也不太想立刻就作格式化的強校驗,感興趣的同窗能夠本身研究一下。

外部連接:prettier對vue的格式化能力有限

6、執行Lint的時機有哪些?

上面咱們講了,如何爲咱們的項目集成commitlinteslintstylelint, 最終實現了,當咱們執行git commit -m '測試提交'時,會對commit-msg的規範性進行校驗校驗,也能夠在咱們的項目根目錄執行npx eslint ./ --fixnpx stylelint ./ --fix來校驗和修復咱們的代碼。

但實際上除了commit-msg的校驗, 已經知足了咱們真實的場景,後面的cli手動校驗還不能知足咱們項目的需求,咱們指望的是自動化的完成這一切。

那什麼時機進行自動lint更適合呢?這取決於你的需求,下面是我總結的一些常見的校驗時機。

6.一、在編輯器中進行 soft lint

Soft lint是阿三我本身起的名字,也就是 「軟校驗」的意思,顧名思義它並非必須的,但它是很是必要的,它的使命是在開發環境下提醒開發者哪裏出現了錯誤,請提早修正它們,是一種工具加持,有利於提高你排錯的效率。

Soft lint通常是指在開發者的編輯器上完成的校驗,屬於「本地校驗」 ,同時它也是 「增量校驗」,由於大多數狀況下編輯器都只會校驗你已經打開過的文件,固然也能夠配置爲「全量」的,可是這將會十分消耗電腦性能。

讓咱們以vscode爲例,看一下如何利用vscdoe的插件實現對項目代碼的soft lint。

首先打開vscode的插件選項,搜索並安裝ESLint插件和stylelint插件,安裝完成後,重啓你vscode, 打開你項目中的.vue或.js文件,發現已經能夠進行校驗了,就這麼簡單,咱們不須要再進行多餘的配置。

爲何能夠無需配置?咱們以vscode plugin Eslint爲例,打開該插件的官方介紹,能夠看到這樣一段話,「If you have installed ESLint locally then run .node_modules.bineslint --init under Windows and ./node_modules/.bin/eslint --init under Linux and Mac.」, 這看起來彷佛很熟悉,它正是執行了咱們上面經過npm安裝的eslintstylelint這兩個包的cli腳本,你剛剛已經配置好了,所以能夠安裝即用,是否是很簡單。

6.二、在本地 git commit 時進行 hard lint

雖然說咱們已經在本地編輯器中安裝了 vscode plugin Eslintvscode plugin stylelint,可是這仍然不太到位,它只是一種輔助加持,並不能作到真正的「硬限制」,咱們但願經過一種方式,新人下載項目代碼後便可自帶校驗功能(npm install一下開箱即用),無需再手動配置任何東西。咱們嘗試和commitlint同樣在commit環節同時完成eslintstylelint的校驗,若校驗不經過,則沒法提交代碼,阿三稱之爲「hard lint」。

咱們仍然指望它是一種「增量校驗」,由於若是每次執行git commit -m 都要執行npx eslint ./** --fix對項目中全部文件作一次校驗,老闆都要等破產了,實在是太慢了,咱們只需對Git中處於 staged狀態(git add的文件)的文件進行校驗便可。

前面咱們講過,想要在執行 git commit時進行一些自定義的操做, 咱們能夠藉助husky監聽git hooks的能力,此時,咱們能夠監聽pre-commit鉤子,也就是說它會比commit-msg鉤子先觸發,優先進行eslintstylelint的校驗,校驗經過後再進行commitlint的校驗。

前面咱們之前安裝了husky, 那麼咱們如何實現只對staged的文件進行「增量校驗」呢?此時須要藉助另一個包lint-staged ,執行下面命令:

npm install --save-dev lint-staged

而後在package.json文件中,增長下面配置(注意這裏只是增長配置,別傻乎乎的把本身的原有配置給覆蓋了):

{
  "scripts": {
    "eslint:fix": "eslint --fix --ext \".js,.vue\"",
    "eslint:lint": "eslint --ext \".js,.vue\"",
    "stylelint:fix": "stylelint \"./**\" --fix"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "lint-staged": {
    "linters": {
      "*.{scss,css}":[
        "npm run stylelint:fix",
        "git add"
      ],
      "*.vue": [
        "npm run stylelint:fix",
        "npm run eslint:fix",
        "git add"
      ],
      "*.{js}": [
        "npm run eslint:fix",
        "git add"
      ]
    },
    "ignore": [
      "**/test/**"
      // 你要忽略的其餘目錄...
    ]
  }
}

注意"lint-staged"這個配置,它會匹配Git中處於staged狀態的文件名,並針對這些匹配到的文件執行相對應的腳本,以vue文件爲例,它會你在執行git commit -m 'test'時,依次執行npm run stylelint:fixnpm run eslint:fixgit add,若是沒有錯誤或者錯誤能被自動修復(--fix), 則會將改動自動add 將修復後的代碼加入 git staged, 繼續進行commitlint的校驗,若所有經過,纔會生成一個新的commit,它的流程以下圖:

image

6.三、其餘lint時機

除了上面講的在編輯器中進行「soft lint」 和在commit階段進行「hard lint」以外,咱們還能夠在「webpack的loader階段」或「CI持續集成遠端」進行校驗,但這不必定是必須的,須要看大家公司的是否須要這種校驗,感興趣的同窗能夠本身研究一下。

結束語

若是你們在閱讀過程當中遇到難以理解的問題,必定要嘗試主動去尋找答案,培養本身獨立解決問題的能力,歡迎留言評論。

相關文章
相關標籤/搜索