前端工程師日常開發最頻繁(實際上最浪費時間)的操作是什么?可能你已經想到了,就是刷新頁面,要讓變更生效,需要重新加載,刷新頁面的操作就變成了重復低效的操作。
于是社區里出現了 [LiveReload](https://www.npmjs.com/package/livereload) 來把這個過程自動化,react 種子項目生成工具 [create-react-app](https://github.com/facebookincubator/create-react-app) 中就使用了這種技術。
但隨著技術的演化,在單頁應用中刷新頁面意味著客戶端狀態的全部丟失,特別是復雜的單頁應用刷新意味著更大量的重復工作才能回到刷新前的狀態,于是社區又搗鼓出了 [Hot Module Replacement,簡稱為 HMR](https://webpack.js.org/concepts/hot-module-replacement/),比如使用 [vue-cli](https://github.com/vuejs/vue-cli) 創建的 [webpack](https://github.com/vuejs-templates/webpack) 種子項目中就包含這種特性,[react-native](https://facebook.github.io/react-native/blog/2016/03/24/introducing-hot-reloading.html) 也內置了這種特性,來幫助開發者提高效率。
讀到這里,你可能會嘀咕,看起來 LiveReload 并不是最新的技術,還討論它干啥,實際上它是自動刷新技術的鼻祖,后續的 HMR、HR 等都是它的改良版,動手配置下自動刷新,也能讓你對這些技術的基本原理略知一二。
下面介紹如何在經典的前端項目中(引用了 css、js 的 html 頁面)接入 LiveReload 的詳細步驟:
### 1\. 安裝項目依賴
使用如下命令安裝 [livereload](https://www.npmjs.com/package/livereload) 和 [http-server](https://www.npmjs.com/package/http-server) 到項目依賴中:
```
npm i livereload http-server -D
# npm install livereload http-server --save-dev
# yarn add livereload http-server -D
```
### 2\. 添加 npm script
按如下提示添加命令,方便我們啟動 LiveReload 服務器和通過 HTTP 的方式訪問頁面:
```
- "cover:open": "scripty"
+ "cover:open": "scripty",
+ "client": "npm-run-all --parallel client:*",
+ "client:reload-server": "livereload client/",
+ "client:static-server": "http-server client/"
```
其中 client 命令能同時啟動 livereload 服務、靜態文件服務。
> **TIP#16**:可能有同學會問,為什么需要啟動兩個服務,其中 http-server 啟動的是靜態文件服務器,該服務啟動后可以通過 http 的方式訪問文件系統上的文件,而 livereload 是啟動了自動刷新服務,該服務負責監聽文件系統變化,并在文件系統變化時通知所有連接的客戶端,在 `client/index.html` 中嵌入的那段 js 實際上是和 livereload-server 連接的一個 livereload-client。
### 3\. 在頁面中嵌入 livereload 腳本
修改 client/index.html 嵌入 livereload 腳本(能夠連接我們的 livereload 服務),diff 如下:
```
<body>
<h2>LiveReload Demo</h2>
+ <script>
+ document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] +
+ ':35729/livereload.js?snipver=1"></' + 'script>')
+ </script>
</body>
```
> **TIP#17**:livereload 是支持在啟動時自定義端口的,如果你使用了自定義端口,在頁面中嵌入的這段 js 里面的 `35729` 也需要替換成對應的端口。
### 4\. 啟動服務并測試
最后,運行 npm run client 之后,截圖如下,注意兩個紅框里面的輸出表示服務啟動成功:

然后,打開瀏覽器訪問:http://localhost:8080,接著修改 client/main.css 并保存(**別忘了保存**),你會發現瀏覽器自動刷新了。如果沒有刷新,歡迎留言交流。
> **TIP#18**:有代碼潔癖的同學可能會問,在頁面中嵌入的那段 js 在線上環境咋辦?實際上在嵌入這段腳本的時候可以通過簡單的手段(比如判斷 location.hostname)去檢查當前頁面運行環境,如果是線上環境就不嵌入了,或者使用打包工具處理 html 文件,上線前直接去掉即可。
* * *
> 本節用到的代碼見 [GitHub](https://github.com/wangshijun/automated-workflow-with-npm-script/tree/10-livereload-with-npm-script),想邊看邊動手練習的同學可以拉下來自己改,注意切換到正確的分支 `10-livereload-with-npm-script`。
* * *
- 為什么選擇 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 實現服務自動化運維