You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rollup CLI在插件中使用closeBundle钩子后进程无法正常退出如何解决

Rollup 插件调用 spawn 后进程挂起问题原因及解决方案

问题诱因

  • 错误监听子进程退出事件:你当前监听的是exit事件而非close事件。exit事件触发仅代表子进程本身的执行线程已终止,但它关联的标准输入输出流可能还未完全关闭,这些活跃的IO句柄会保留在Node.js事件循环中,导致Rollup主进程判定仍有未完成任务,不会主动退出。
  • shell: true配置的进程链残留:开启该配置后,你实际启动的是一个中间shell进程,由它再执行npm run make命令。如果npm run make内部又启动了其他子进程,即便中间shell本身已退出,这些后代子进程可能还持有继承来的stdio句柄,阻塞主进程退出。

修复方案

  1. 将子进程的监听事件从exit替换为close,close事件会在子进程完全终止、所有关联IO流都关闭后才触发,此时再resolve Promise即可确保无残留句柄。
  2. 如果不需要保留子进程的输出继承,可将stdio设置为ignore,避免子进程流持有父进程句柄;如果需要保留输出,可在close事件触发后主动调用unref()解除对子进程的引用。
  3. 可选添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 08:06:05