Rollup CLI在插件中使用closeBundle钩子后进程无法正常退出如何解决
Rollup 插件调用 spawn 后进程挂起问题原因及解决方案
问题诱因
- 错误监听子进程退出事件:你当前监听的是
exit事件而非close事件。exit事件触发仅代表子进程本身的执行线程已终止,但它关联的标准输入输出流可能还未完全关闭,这些活跃的IO句柄会保留在Node.js事件循环中,导致Rollup主进程判定仍有未完成任务,不会主动退出。 shell: true配置的进程链残留:开启该配置后,你实际启动的是一个中间shell进程,由它再执行npm run make命令。如果npm run make内部又启动了其他子进程,即便中间shell本身已退出,这些后代子进程可能还持有继承来的stdio句柄,阻塞主进程退出。
修复方案
- 将子进程的监听事件从
exit替换为close,close事件会在子进程完全终止、所有关联IO流都关闭后才触发,此时再resolve Promise即可确保无残留句柄。 - 如果不需要保留子进程的输出继承,可将
stdio设置为ignore,避免子进程流持有父进程句柄;如果需要保留输出,可在close事件触发后主动调用unref()解除对子进程的引用。 - 可选添加
detached: true配置,切断父子进程的引用关联,避免子进程残留任务影响父进程退出。
修正后的代码示例:
function make() { return { closeBundle() { let elMake = require('child_process').spawn('npm', ['run', 'make'], { stdio: ['ignore', 'inherit', 'inherit'], shell: true, detached: true // 可选配置,切断父子进程引用 }); return new Promise((resolve, reject) => { elMake.on('error', reject) // 将exit事件替换为close事件 elMake.on('close', code => { elMake.unref() // 主动解除对子进程的引用 if (code === 0) { console.log("make done...."); resolve() } else { const err = new Error(`make exited with code ${code}`) reject(err) } }) }) } }; }
内容的提问来源于stack exchange,提问作者kibudude
相关产品推荐
相关产品推荐

