在用nodejs开发web程序过程中, 每次修改都需要重新启动一下服务, 虽然有pm2,forever等解决方案。
在fex上看见一个比较另类的解决方案——Node.js Web应用代码热更新的另类思路
在这里简单实现一下来解决开发过程中热启动的问题。
首先需要重新包装一下nodejs提供的require
方法。在require自己写的代码时,同时需要监听文件变化,当文件发生变化时,重新加载模块。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| const chokidar = require('chokidar');
function cleanCache(modulePath) { var module = require.cache[modulePath]; if (module.parent) { module.parent.children.splice(module.parent.children.indexOf(module), 1); } require.cache[modulePath] = null; }
function watchFile(obj) { let absModulePath = require.resolve(obj.modulePath); chokidar.watch(absModulePath).on('all', (event, path) => { cleanCache(absModulePath); console.log(`file [${path}] --> [${event}]`); try { obj.name = require(obj.modulePath); } catch (ex) { console.error('module update failed'); } }); }
module.exports = function (obj) { !obj.ignore && watchFile(obj); obj.name = require(obj.modulePath); return obj; };
|
由于使用node原生的fs.watch会出现文件变化监听不到的情况(其他一些问题见chokidar readme),
所以这里使用chokidar
来实现对文件的监听。
使用wrapperRequire.js
1 2 3 4 5 6 7 8
| const wrapperRequire = require('./require'); let code = wrapperRequire({modulePath: './code', 'name': ''}); setInterval(function () { console.log(code.name); }, 1000);
|
测试文件 code.js
1
| module.exports = 'hello world';
|
执行main.js
然后更改code.js
后也可以展示正确的结果。
总结一下,以上实现的基础是:
- nodejs可以对require缓存的文件进行清空
- 监听文件变化,然后重新require文件
- js函数中传递的Object参数是引用传递
参考:
1.Node.js Web应用代码热更新的另类思路
2.chokidar