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 写得很直白:

    • “To keep track of import map state, **es-module-shims provides importShim.getImportMap … only in shim mode.”

    • “To set the import map state, **importShim.addImportMap … only in shim mode.”
      也就是只有 shim-mode 下,调用它们才等同于真正“驱动”解析器的那份状态。

 

posted @ 2025-09-02 09:33  PEAR2020  阅读(4)  评论(0)    收藏  举报