DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
雨云;给项目一台云服务器
RackNerd;$21.99/年 · 1GB KVM

Vite 开发时缺少 default 导出:链接的 CommonJS 包没有进入预构建

链接的 CommonJS 包在 Vite 开发模式中缺少 default 导出时,核对实际入口、显式预构建和缓存,并单独验收正式构建。

Vite 开发服务器能启动,浏览器却报 does not provide an export named 'default',错误指向 monorepo 链接包中的 CommonJS 文件。文件确实有 module.exports 时,先确认这个入口是否经过依赖预构建;把它当普通 ESM 源码直接交给浏览器,浏览器并不会自动理解 CommonJS 导出。

这条处理路径适用于开发模式中链接的 CommonJS 包或其嵌套依赖。真正的 ESM 文件没有声明 default 导出时,需要修正导入方式或包的导出契约,不能靠预构建配置给它补造一个导出。

从浏览器请求找到实际入口

保留完整错误中的模块地址,查看开发者工具 Network 中对应响应。若响应仍包含 CommonJS 的 module.exports、exports 或 require,再对照项目的 import、包清单的 exports 和文件位置,确认 Vite 实际解析到了哪个入口。

不要仅凭包名判断格式。同一个库可能同时提供 CommonJS 和 ESM,主入口与某个子路径也可能不同。链接包的目录在仓库源码中,与普通 node_modules 中的已发布依赖,可能经过不同的处理路径。

Vite 会把未从 node_modules 解析出的链接依赖视为源码,不默认为它预构建;这种路径要求链接依赖提供 ESM。开发模式的依赖预构建可以转换 CommonJS 或 UMD,因此链接包仍提供 CommonJS 时,可以将所需入口显式加入 optimizeDeps.include。

若文件本来就是 ESM,检查它是否只有命名导出。需要把 import value from 'pkg' 改为对应的命名导入时,应按实际包 API 修改调用方,并检查其他使用点。

将缺失的 CommonJS 入口加入 include

下面假设项目确实导入了 linked-tools/mod.js,而且该子路径可以合法解析。这是需合并到现有 vite.config.js 的局部示例:

import { defineConfig } from 'vite';

export default defineConfig({
  optimizeDeps: {
    include: ['linked-tools/mod.js']
  }
});

用实际失败入口替换示例。报错落在子路径时,不能保证只加入另一个包的顶层名称就覆盖了它;也不要把浏览器中的 /@fs/ 地址直接当成依赖包标识。项目已有 include、插件或别名时,保留原配置并核对解析结果。

另一种情况是被排除预构建的 ESM 包内部依赖 CommonJS 包。当前配置支持用依赖链表达嵌套入口,例如:

export default defineConfig({
  optimizeDeps: {
    include: ['esm-dep > cjs-dep']
  }
});

这里的两个名称也只是示例。只有实际依赖链符合这个场景才使用;不要把所有默认导出错误都套成嵌套依赖问题。CommonJS 依赖本身不应被随意加入 optimizeDeps.exclude,否则仍可能绕开所需转换。

更新配置后重新生成开发缓存

记录当前 Vite 版本、包清单、锁文件和配置。修改链接包或 include 后,停止原开发服务,再通过项目既有入口传入 Vite 的 --force 参数,强制重新预构建。

若项目的 dev 脚本直接调用 Vite,npm 参数透传可写为:

npm run dev -- --force

脚本还套了其他工具时,先确认参数确实交给 Vite。该操作会重启开发服务并更新预构建缓存,不会修复源码中不匹配的 ESM 导出。

浏览器也可能保留先前的依赖响应。调试时可暂时在 Network 中禁用缓存并重新加载,核对新请求的内容;完成后恢复浏览器设置。无需因此删除整个 node_modules、锁文件或所有包管理器缓存。

开发恢复后,单独检查正式构建

这项配置控制开发依赖优化。Vite 5.1 起已移除构建期间的依赖预构建,不能把开发页恢复视为生产构建也已通过。原项目仍在旧版 Vite 上时,也要按对应版本核对构建链,不能直接照搬当前底层打包器选项。

从原开发入口重新访问页面,确认同一模块不再报缺少 default 导出,并执行依赖该包的功能。随后运行项目正常的正式构建和预览流程,检查产物中的模块及关键页面。预构建配置有效、包的实际 API 可用和生产产物正确,需要分别确认。

若回退这次配置,恢复保存的配置与相关包版本、锁文件,再重启开发服务并重建缓存。不要留下只在某台机器旧缓存中可工作的结果。