Vite 预构建后把 #imports 的开发分支选成了生产分支
Vite 8.3.4 的依赖预构建可能让包内 #imports 丢失 development 条件。对照优化与非优化入口,按 ESM 边界局部排除,或明确对齐 Rolldown 解析条件。
同一个包在普通开发导入时返回开发实现,加入 optimizeDeps.include 后却变成生产实现。若包的 package.json 用 #imports 按 development 条件分支,应比较预构建前后的解析条件。
Vite 8.3.4 有这条具体表现:包内 #mode 的 development 分支没有在依赖优化中命中,最后选了 default。问题不在应用把 NODE_ENV 写错,也不能由此推断所有条件导出都失效。
包内分支在哪一步被选中
例如依赖包内部约定:
{
"imports": {
"#mode": {
"development": "./dev.js",
"default": "./prod.js"
}
}
}
先确认是哪一份包清单在控制这个 #mode,实际导入是否发生于包内部,以及浏览器最终拿到了哪一分支。应用根目录的 imports 不会自动覆盖所有依赖包的私有映射。
这条路径中,Vite 的依赖解析插件对输入标识符有过滤,# 开头的映射不走普通包名那条处理;回退到 Rolldown 原生解析时,没有完整沿用所需的环境条件。8.3.5 的正式源码仍有相关过滤形状,不能因为更新了一个小版本就认定已得到修复。
仅对适合直接加载的 ESM 包绕过优化
如果该依赖本身是浏览器可直接处理的 ESM,可以在现有配置中对它局部使用 optimizeDeps.exclude,再重新启动开发服务验证。包名必须换成项目实际受影响的依赖,不要把整个依赖列表都排除。
CommonJS 包通常需要预构建转换,不能照搬排除方法。ESM 包内部若依赖 CommonJS,也需按原工具要求保留相应子依赖的优化,否则可能把分支问题换成缺少 default 导出或浏览器无法执行 require。
另一条处理是通过 optimizeDeps.rolldownOptions.resolve.conditionNames 明确对齐优化阶段的条件。采用这条路径时,要保留项目原有的 browser、module 和自定义条件,不能只填一个 development 就覆盖所有默认行为。还需分别核对客户端与 SSR 的环境条件,不应把客户端列表原样复制给服务端。
刷新预构建后再看实际分支
保留原配置和优化产物以便对照,修改后通过 Vite 正常的强制重新优化入口重建依赖缓存。不要同时删除锁文件并升级多个依赖,那会让是否由条件解析恢复变得难以判断。
验证应执行受影响包的真实功能,并确认最终导入路径或导出值来自 dev 分支;只看到开发服务启动没有报错并不够。随后检查原生产构建仍选择预期的生产分支,SSR 若存在也应单独验证。
局部排除或显式条件是对具体优化路径的处理,不应演变成全局修改包私有映射或把 default 文件改名成开发实现。


