DEBUG.WIKI
晚安云;香港 CN2 ¥15/月
PanstarCloud:部署应用,接入 AI,云服务器与 AI 网关
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →

Vitest vmThreads 导入 ESM JSON 报 ERR_VM_MODULE_DIFFERENT_CONTEXT

测试文件未加载就失败,真正触发点可能是外置 ESM 依赖内部的 JSON import。可对确认的包局部 inline,或评估非 VM pool。

测试文件还没进入断言,就报 Linked modules must use the same context,序列化错误码为 ERR_VM_MODULE_DIFFERENT_CONTEXT。如果只有 vmThreads 失败,forks、threads 能运行,检查外置 ESM 依赖内部是否导入了 JSON。

明确触发组合是 Vitest 3.2.7、Vite 7.3.6、Node 22.23.3。外置 ESM 本身未必有问题:同样的包去掉 JSON import 后可以链接;加入 import data from './data.json' with { type: 'json' } 才触发跨 VM context 的错误。

报错文件未必是带入 JSON 的包

保留完整错误、pool、实际安装版本和依赖入口。测试文件只是导入失败的边界,不能看到它的文件名就断定测试代码用了多个 vm 实例。

检查失败依赖是否真的作为 external 执行。工作区 file: 链接包可能被当源码内联,而安装到 node_modules 的发布包或归档包走另一条路径;用链接包做对照正常,不能推翻外置包的故障。

在受影响实现中,外置 ESM 模块使用测试自己的 VM context,JSON 模块却可能进入另一个 context,两者不能直接链接。它与 JSON 内容不合法或缺少 import attribute 不同:后两者有自己的语法与类型错误,不应套用本处理。

对确认的 ESM 包局部 inline

短期需保留 Vitest 3.2.7 时,可把真正持有 JSON import 的包加入原配置:

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    pool: 'vmThreads',
    server: {
      deps: {
        inline: ['esm-json-dep'],
      },
    },
  },
});

esm-json-dep 是示例,替换为实际失败包。保留现有环境、setup 和其他依赖规则;如果 JSON import 在更深的外置包中,继续按实际依赖图核对。不要直接设 inline: true 来绕过全部边界,那会扩大转换范围。

deps.optimizer.ssr.include 不等于 server.deps.inline。预构建不保证输出一定按测试 VM 内联执行,所以不能把“优化器已包含包”当成跨 context 已消除。

另一条选择是评估切到 forks 或普通 threads。它会改变隔离和运行资源模型,需覆盖原有测试环境与原生依赖;不能只为了一个文件切换后,就认定整套测试仍等价。

检查测试真的被收集并执行

沿原失败文件验证 JSON 导出的数据能被读取,断言数量符合预期,原有 mock 和清理仍运行。再运行相关测试组,防止只有控制文件成功而原文件仍未加载。

Vitest 3.2 线不应被当成仍接收所有新修复的版本;升级到后续主版本需核对迁移与 Node 支持,不能凭一个关闭状态推断旧版已修。保存原锁文件和局部 inline 配置,升级后先用外置 ESM 加 JSON 的原组合回归,再决定是否移除绕行。