標籤:

Egg + Webpack 熱更新實現

1. 背景

在用 Node.js + Webpack 構建的方式進行開發時, 我們希望能實現修改代碼能實時刷新頁面 UI的效果. 這個特性 Webpack 本身是支持的, 而且基於koa也有現成的 koa-webpack-hot-middleware 和 koa-webpack-dev-middleware 封裝好的組件支持.

不過這裡如果需要支持Node.js伺服器端修改代碼自動重啟webpack自動編譯功能該如何實現呢, 主要存在以下幾個問題:

  • 如何解決 Node.js 伺服器端代碼修改應用重啟避免Webpack重新編譯.
  • 如何訪問 js,css,image等靜態資源.
  • 服務端渲染時, Node 層如何讀取 Webpack 內存編譯的內容
  • 如何處理本地開發 Webpack 熱更新內存存儲讀取和線上應用本機文件讀取邏輯分離.2. 前端渲染和服務端渲染構建熱更新實現

2. 前端渲染和服務端渲染構建熱更新實現

在 koa 項目中, 通過 koa-webpack-dev-middleware 和 koa-webpack-hot-middleware 可以實現 webpack 編譯內存存儲和熱更新功能, 代碼如下:

const compiler = webpack(webpackConfig);nconst devMiddleware = require(koa-webpack-dev-middleware)(compiler, options);nconst hotMiddleware = require(koa-webpack-hot-middleware)(compiler, options);napp.use(devMiddleware);napp.use(hotMiddleware);n

如果按照上面實現, 可以滿足修改修改客戶端代碼實現webpack自動變編譯和UI界面熱更新的功能.但如果是修改 Node.js 伺服器端代碼重啟後就會發現webpack會重新編譯, 這不是我們要的效果.原因是因為middleware是依賴app的生命周期, 當app銷毀時, 對應webpack compiler實例也就沒有了, 重啟時會重新執行middleware初始化工作.

那有沒有辦法保持 Webpack 編譯實例呢? 針對這個我們可以通過 Egg 框架已經內置了 Worker 和 Agent 機制來實現 Webpack 內存編譯功能和通信功能。

3. Egg Worker 和 Agent 通信

  • Egg worker和agent通信機制
  • 實現 Egg 項目伺服器代碼修改項目自動重啟的功能可以使用 egg-development 插件.

3.1 Worker 與 Agent 通信

  • 通過app.messenger.sendToAgent 向agent發送消息
  • 通過app.messenger.on 監聽agent發送過來的消息

// app.webpack.fileSystem.readWebpackMemoryFile 方法實現nthis.app.messenger.sendToAgent(Constant.EVENT_WEBPACK_FILE_MEMORY, n{ filepath });nnthis.app.messenger.on(Constant.EVENT_WEBPACK_READ_FILE_MEMORY_CONTENT, ndata => { // 因為消息是非同步,必須是發過去的文件名與收到的文件名相同n if (filepath === data.filepath) { n resolve(data.fileContent);n }n});n

3.2 Agent 與 Worker 通信

  • 通過 agent.messenger.sendToApp 向app發送消息
  • 通過 app.messenger.on 監聽agent發送過來的消息

Agent 監聽到 Worker 發過來的 filepath, 從 Webpack 內存中讀取文件內容, 然後通過 agent.messenger.sendToApp 把內容發送給 Worker。

agent.messenger.on(Constant.EVENT_WEBPACK_READ_FILE_MEMORY, data => {n const fileContent = Utils.readWebpackMemoryFile(compiler, data.filepath);n agent.messenger.sendToApp(Constant.EVENT_WEBPACK_READ_FILE_MEMORY_CONTENT, {n fileContent,n });n});n

4. Egg框架中Webpack構建

  • 我們利用本地開發修改 Node 層代碼修復重啟時, 只會重啟 Worker 進程, 不會重啟 Agent進程的機制, 我們可以在Agent裡面啟動 Webpack 編譯服務解決 Webpack compiler 實例問題.
  • 因為 Egg App 進程 和 Agent 進程是兩個進程, 當 url 訪問時, 我們通過 Worker 發送消息給 Agen t進程, 獲取服務端渲染的文件內容, 然後 Agent 再發送消息給 Worker 解決文件讀取問題.
  • 本地開發 Webpack 熱更新內存存儲讀取和線上應用本機文件讀取邏輯分離功能, 我們通過本地開發模式時, 通過讀取 Webpack 內存內容覆蓋本地文件讀取的邏輯, 這樣在開發模式和發布模式可以無縫對接.

4.1 Egg + Webpack 項目本地開發模式

  • 首先執行node index.js 或者 npm start 啟動 Egg應用
  • 在Egg Agent 裡面啟動koa服務, 同時在koa服務裡面啟動Webpack編譯服務
  • 掛載Webpack內存文件讀取方法覆蓋本地文件讀取的邏輯

const filePath = path.isAbsolute(name) ? name : path.join(app.config.view.root[0], name);nconst promise = app.webpack.fileSystem.readWebpackMemoryFile(filepath);nreturn co(function* () {n const content = yield promise;n return render(content, data)n});n

  • Worker 監聽 Webpack 編譯狀態, 檢測 Webpack 編譯是否完成, 如果未完成, 顯示Webpack 編譯 Loading, 如果編譯完成, 自動打開瀏覽器。
  • Webpack 編譯完成, Agent 發送消息給 Worker, Worker 檢測到編譯完成, 自動打開瀏覽器, Egg服務正式可用。

Egg + Webpack 熱更新實現插件: egg-webpack 可以用於 Node 服務端或者前端項目開發。


推薦閱讀:

iKcamp|基於Koa2搭建Node.js實戰(含視頻)? HTTP請求
Koa 請求日誌打點工具(三)—— OpenTracing + Jaeger
Koa 請求日誌打點工具
為什麼Node的web端框架express和Koa的生態環境差距還是巨大(2017.11)?

TAG:webpack | eggjs | koa |