軟件工程師做的事情基本都是在實現自動化,比如各種業務系統是為了業務運轉的自動化,部署系統是為了運維的自動化,對于開發者本身,自動化也是提升效率的關鍵環節,在實際開發過程中也有不少事情是可以自動化的。
擁抱現代前端工作流的同學都會有代碼風格檢查、單元測試等環節,這樣就很需要在代碼變更之后立即得到反饋,如代碼改動導致了那個 Case 失敗,哪塊不符合團隊的編碼規范等。
使用 gulp、grunt 的同學,可能對這種功能非常熟悉,不就是 watch 么?確實是,使用 npm script 我們也可以實現類似的功能。下面詳細介紹如何改造我們的項目實現單測、代碼檢查的自動化。
## 單元測試自動化
幸運的是,mocha 本身支持 `--watch` 參數,即在代碼變化時自動重跑所有的測試,我們只需要在 scripts 對象中新增一條命令即可:
```
"test": "cross-env NODE_ENV=test mocha tests/",
+ "watch:test": "npm t -- --watch",
"cover": "node scripts/cover.js",
```
嘗試運行 npm run watch:test,我們會發現進程并沒有退出,接下來嘗試去修改測試代碼,測試是不是自動重跑了呢?自己試試看。
## 代碼檢查自動化
我們使用的代碼檢查工具 [stylelint](https://stylelint.io)、[eslint](https://eslint.org)、[jsonlint](https://github.com/zaach/jsonlint) 不全支持 watch 模式,這里我們需要借助 [onchange](https://github.com/Qard/onchange) 工具包來實現,onchange 可以方便的讓我們在文件被修改、添加、刪除時運行需要的命令。
### 1\. 安裝項目依賴
使用如下命令安裝 onchange 到項目依賴中:
```
npm i onchange -D
# npm install onchange --save-dev
# yarn add onchange -D
```
### 2\. 添加 npm script
按照如下提示添加 watch:lint 和 watch 兩個子命令:
```
+ "watch": "npm-run-all --parallel watch:*",
+ "watch:lint": "onchange -i \"**/*.js\" \"**/*.less\" -- npm run lint",
"watch:test": "npm t -- --watch",
```
關于改動的幾點說明:
* `watch:lint` 里面的文件匹配模式可以使用通配符,但是模式兩邊使用了轉義的雙引號,這樣是跨平臺兼容的;
* `watch:lint` 里面的 `-i` 參數是讓 onchange 在啟動時就運行一次 `--` 之后的命令,即代碼沒變化的時候,變化前后的對比大多數時候還是有價值的;
* watch 命令實際上是使用了 npm-run-all 來運行所有的 watch 子命令;
> **TIP#15**:有沒有好奇過 onchange 是怎么實現文件系統監聽的?所有的魔法都藏在它的源代碼里面,實際上它使用了跨平臺的文件系統監聽包 [chokidar](https://github.com/paulmillr/chokidar),基于它,你能做點什么有意思的事情呢?
onchange 有個不太醒目的特性是,文件系統發生變化之后,他在運行指定命令之前輸出哪個文件發生了哪些變化,如下圖紅框中的內容:

讀到這里,有沒有覺得 onchange 可以和 gulp、grunt 的 watch 一樣強大。
> 除了上面的單測重跑和代碼檢查之外,你還有什么需求需要放在 onchange 里面?歡迎留言討論。
* * *
> 本節用到的代碼見 [GitHub](https://github.com/wangshijun/automated-workflow-with-npm-script/tree/09-run-npm-script-with-onchange),想邊看邊動手練習的同學可以拉下來自己改,注意切換到正確的分支 `09-run-npm-script-with-onchange`。
* * *
- 為什么選擇 npm script
- 入門篇 01:創建并運行 npm script 命令
- 入門篇 02:運行多個 npm script 的各種姿勢
- 入門篇 03:給 npm script 傳遞參數和添加注釋
- 進階篇 01:使用 npm script 的鉤子
- 進階篇 02:在 npm script 中使用環境變量
- 進階篇 03:實現 npm script 命令自動補全
- 高階篇 01:實現 npm script 跨平臺兼容
- 高階篇 02:把龐大的 npm script 拆到單獨文件中
- 高階篇 03:用 node.js 腳本替代復雜的 npm script
- 實戰篇 01:監聽文件變化并自動運行 npm script
- 實戰篇 02:結合 live-reload 實現自動刷新
- 實戰篇 03:在 git hooks 中運行 npm script
- 實戰篇 04:用 npm script 實現構建流水線
- 實戰篇 05:用 npm script 實現服務自動化運維