Template-system 之 解决后退难题
背景与表象
-
远程加载组件在正常硬跳转时可用;
-
点击 后退 后,组件内部
import 'react/jsx-runtime'报错:TypeError: Failed to resolve module specifier "react/jsx-runtime"。
🧠技术关键词
-
es-module-shims -
importmap-shim -
BFCache -
dynamic import -
module resolution -
memory snapshot
实验
场景1:原先是使用 <script type="importmap" dangerouslySetInnerHTML={{ __html: importMapJson }} />和 await import( /* webpackIgnore: true */ /* @vite-ignore */ url);
结果
-
首次进入:✅ 正常
-
后退(BFCache 恢复):❌ 报错(无法解析
react/jsx-runtime)
观察:BFCache 恢复不会重新执行 <script type="importmap">;某些实现/时序下,动态 import() 的解析上下文没有重新“挂”到那份映射上。
场景2: 现在换成了 <script type="importmap-shim" dangerouslySetInnerHTML={{ __html: importMapJson }} /> <script async src="https://ga.jspm.io/npm:es-module-shims@2.6.2/dist/es-module-shims.js"></script> 和 await importShim( /* webpackIgnore: true */ /* @vite-ignore */ url);
结果
-
首次进入:✅ 正常
-
后退(BFCache 恢复):✅ 仍正常(无需手动
addImportMap)
观察:进入 shim mode 后,解析权由 polyfill 接管;import map 解析结果 + module registry 保存在 JS 内存中,BFCache 是“带内存复活”,所以后退后状态仍可用。
场景3: <script type="importmap" dangerouslySetInnerHTML={{ __html: importMapJson }} /> <script async src="https://ga.jspm.io/npm:es-module-shims@2.6.2/dist/es-module-shims.js"></script> 和 await importShim( /* webpackIgnore: true */ /* @vite-ignore */ url);
结果
-
后退:❌ 报错
-
此时
window.importShim.getImportMap()看起来有react/jsx-runtime,但解析仍失败
观察:这是“双 loader 分权”导致的错位:
-
getImportMap()是 shim 维护的快照; -
实际解析很可能仍走原生 import()(esms 的 native passthrough 行为);
-
BFCache 恢复后,原生路径没重新挂到 import map 上,于是出现“有快照、却解析失败”的幻觉。
关键突破口
es-module-shims 的 GitHub 仓库:
👉 https://github.com/guybedford/es-module-shims
README 写得很直白:

浙公网安备 33010602011771号