Node.js不使用Nodemon如何实现输入rs命令重启通过require启动的进程
问题原因分析
- 逻辑顺序错误:你在代码中先执行了
process.exit(),当前Node进程会直接终止,后续的require("./path/to/file")代码完全不会执行,自然没有重启效果。 - 模块缓存问题:就算调整顺序去掉
process.exit()直接重新require目标文件,Node.js默认会对已经加载的模块做缓存,重复require不会重新执行目标文件的代码,只会返回缓存的导出结果。 - 资源残留问题:如果不清理原有业务代码占用的资源(比如端口监听、定时器、事件监听等),直接重新运行业务代码会出现端口占用、事件重复触发等冲突问题。
推荐实现方案(子进程模式,无第三方依赖)
推荐通过主进程托管业务子进程的方式实现,逻辑更稳定,和nodemon的核心实现逻辑一致,不需要额外清理业务资源:
// 把这段代码作为你的启动入口文件,替换原有启动逻辑 const { fork } = require('child_process'); const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); let childProcess; // 启动业务子进程的方法 function startChild() { // 传入启动参数-dev,和你原启动逻辑一致 childProcess = fork('./path/to/file', ['-dev']); // 把子进程的输出同步到主进程控制台 childProcess.stdout.pipe(process.stdout); childProcess.stderr.pipe(process.stderr); // 子进程意外退出时自动重启 childProcess.on('exit', (code) => { if (code !== 0) startChild(); }); } // 首次启动业务进程 startChild(); // 监听控制台输入 rl.on('line', (input) => { if (input.trim() === 'rs') { console.log('正在重启进程...'); // 杀掉旧的业务子进程 childProcess.kill(); // 启动新的业务子进程 startChild(); } });
可选方案(单进程模式)
如果不想用子进程,可以参考以下实现,需要注意手动清理业务代码占用的资源:
const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const targetModulePath = require.resolve('./path/to/file'); // 业务代码启动方法 function startApp() { // 清除目标模块的缓存 delete require.cache[targetModulePath]; // 重新引入执行业务代码 require(targetModulePath); } // 首次启动 startApp(); rl.on('line', (input) => { if (input.trim() === 'rs') { console.log('正在重启进程...'); // --- 此处需要补充你业务代码的资源清理逻辑,比如关闭监听端口、清除定时器等 --- // 重新启动业务代码 startApp(); } });
注意:单进程模式如果资源清理不全,会出现端口占用、重复事件监听等异常,优先使用子进程方案。
内容的提问来源于stack exchange,提问作者DarkInk
相关产品推荐
相关产品推荐

