?實現思路:將啟動檔案中的 router、proxy 檔案分離出主檔案,對分離出去的檔案實現熱更新。關鍵問題點:
- 如何更新模組程式碼
- 如何使用新模組處理請求
- 如何釋放老模組的資源
如何更新模組程式碼
引入 chokidar
當監聽檔案修改時,清除該模組快取,delete require.cache[path]
如何使用新模組處理請求
使用koa框架,app.use 操作會儲存舊的 router.js 模組,因此模組更新了,請求依然會使用老模組
// 利用閉包的特性獲取最新的router物件,避免app.use快取router物件
app.use((ctx, next) => router.routes()(ctx, next)).use(router.allowedMethods())
// 監聽檔案修改重新載入程式碼
const watcher = chokidar.watch(path.resolve(__dirname, '../www'), { ignored: /index\.js/ })
watcher.on('ready', () => {
logger.info(`will watching at '${path.resolve(__dirname, '../www')}`)
watcher.on('all', (event, file) => {
logger.info(`server-side hot-reload due to: ${file}`)
Object.keys(require.cache).forEach((id) => {
if (/\/www\//.test(id)) {
cleanCache(id)
try {
if (file.endsWith('router.js')) {
router = require('./router')
}
if (file.endsWith('proxies.js')) {
proxies = require('./proxies')
}
} catch (ex) {
console.error(`module ${file} update failed`)
}
}
})
})
})
function cleanCache (module) {
var path = require.resolve(module);
delete require.cache[path];
}
複製程式碼
如何釋放老模組的資源
讓老模組的程式碼更新後,確保沒有物件保持了模組的引用 ,Node.js 會自動為所有模組新增一個引用
function cleanCache(modulePath) {
var module = require.cache[modulePath];
// remove reference in module.parent
if (module.parent) {
module.parent.children.splice(module.parent.children.indexOf(module), 1);
}
require.cache[modulePath] = null;
}
複製程式碼
解決了 koa 熱更新問題。
附上github: github.com/Jarryxin/mp…