標籤:

Egg中實現Webpack動態編譯

1.背景

因打算開發一個Egg+Vue+Webpack的應用,在開發過程中需要使用到webpack的HMR功能,koa有提供這麼一個中間件koa-webpack,我們可以直接在egg應用中使用,但是當我們在修改egg伺服器代碼的時候會觸發Worker銷毀,並重新載入整個應用,間接導致所有中間件重新載入,也就是每次koa-webpack都需要重新編譯一次。我們需要解決以下問題:

  • 如何實現修改egg伺服器代碼不觸發koa-webpack重編譯(為內置插件egg-development添加忽略監聽的目錄);
  • 如何實現當瀏覽器訪問靜態資源的時候,從koa-webpack中的內存文件系統中讀取對應編譯好的文件數據。

2.Worker與Agent

在Egg的多進程模型中,我們把koa-webpack功能交給唯一的Agent進程就能解決第一個問題,因為Agent是不會進行重啟操作的;然後當應用需求請求靜態資源的時候,Worker通過IPC發送需要訪問的文件路徑信息給Agent,Agent詢問koa-webpack是否存在此文件(內存文件系統),有則從內存獲取其數據並通過IPC返回給Worker,無得返回「文件不存在」的信息。

3.設置egg-development配置

// config.default.js// 忽略以下文件目錄的監聽...config.development = { ignoreDirs: [app/web]}...

4.在Agent中開啟koa-webpack

// agent.js// 只在local環境啟用// ...if (agent.config.env === local) { const koaWebpack = require(koa-webpack); const { dev } = koaWebpack(); // 監聽Worker發來的文件請求消息 agent.messenger.on(MemoryFileEvent.REQUEST_FILE, filePath => { // 從koa-webpack的內存文件系統memory-fs中查找文件數據 // 注意filePath是相對路徑,而memory-fs中記錄的文件都是絕對路徑 // ... agent.messenger.sendToApp( fileData ? MemoryFileEvent.FILE_FOUND : MemoryFileEvent.FILE_NOT_FOUND, { filePath, fileData }); });}// ...

5.在Worker中添加中間件notfound-handler

// app/middleware/notfound-handler.js// 當找不到靜態資源的時候,訪問koa-webpack是否在內存文件系統中存在// ...if (ctx.status === 404) { const currentEnv = app.config.env; let msg; switch (currentEnv) { case local: // 獲取文件數據 try { const filePath = ctx.request.path; let fileData = await app.memoryFileBuilder.requestFile(filePath); // ... msg = fileData; catch (err) { msg = err; } break; default: msg = sorry, resource not found...; break; } ctx.body = msg;}// ...

項目地址:egg-webpack-dynamic-compile

思路來自:Egg + Webpack 熱更新實現

小弟第一次寫文章,如有問題請指出,謝謝。

推薦閱讀:

node相比傳統服務端技術棧差在哪裡?
如何進行nodejs非同步編程?
如何理解 Ryan Dahl 最近專訪中的言論「Node 也許不是構建大型服務的最佳選擇」?
Object.create Reflect.setPrototypeOf 哪個比較好?
package-lock.json 需要寫進 .gitignore 嗎?

TAG:Nodejs | webpack | koa |