加载、entries 与预加载
从 wu.json 到模块执行:路径解析、策略、缓存与网络诊断。
从 URL 到生命周期
注册的 URL 指向应用的公共目录。注册时请求 <url>/wu.json。挂载期间,如果尚无定义,WU 会解析 entry,按照 sandbox 模式执行它,并等待通过 wu.define 完成注册。
发布指向真实文件的 manifest。Vite 构建可能生成带哈希的文件;部署的 manifest 必须更新为指向同一次构建的 entry。框架不会在客户端转换 TypeScript 或 JSX。
{
"name": "reports",
"entry": "assets/reports-C4z8m.js",
"styleMode": "own-only"
}
entry 解析
resolveModulePath 使用 manifest 的 entry,缺失时内部回退到 main.js。这与遇到 404 时生成的 manifest 不同,后者的 entry 为 index.js。
- 如果 entry 以
src/、dist/、public/、build/、assets/、lib/或es/开头,则直接与 base 拼接使用。 - 其他情况下,先检查声明的原始路径。
- 如果不存在,则并行尝试这些常见目录,选择结果时保留优先顺序。
- 如果全部没有响应,返回声明路径,使错误指向作者配置的文件。
检查使用 HEAD,并通过 content type 区分 JavaScript 与 SPA 的 HTML 回退页面。如果服务器不支持 HEAD 并返回 405,则允许带范围的 GET。成功的解析按 base 和 entry 缓存;能够生成正确 manifest 时,无需依赖这些启发式查找。
选择策略
宿主配置中的 strategy |
行为 |
|---|---|
lazy |
不预加载;挂载时加载 |
eager |
init 期间执行 import() |
preload |
插入 link rel="prefetch" 资源 |
speculate |
委托给 prefetcher |
idle |
策略可将加载入队;没有 shouldPreload,因此仅声明它不会自动让 init 的 preloader 调度它 |
要从 shell 控制加载,请使用 lazy,并在适当时机调用 mount 或 prefetch。Astro 类型中有 manual,但它不是 core 注册的策略;未知策略会使用 lazy 并发出警告。
Eager 会执行代码,并且在挂载前通过宿主 realm 中的直接 import 执行。它不等同于下载字节,也不等同于使用 strict sandbox 挂载。要提前下载,保留 lazy 并使用 prefetch API;检查项目的 CSP 策略和浏览器兼容性。
显式 prefetch
await wu.prefetch(['reports', 'catalog']);
const cancelHover = wu.prefetch('reports', {
on: 'hover',
target: '#reports-link',
});
const cancelVisible = wu.prefetch('catalog', {
on: 'visible',
target: '#catalog-slot',
});
// Cuando esos elementos abandonen el shell:
cancelHover();
cancelVisible();
immediate 返回 Promise。hover、visible 和 idle 同步返回取消函数。如果之后要将它们作为 cleanup 调用,不要将所有返回值一律转为 Promise。触发器会按情况安装监听器、IntersectionObserver 或 idle 回调。
实现会检测 Speculation Rules、modulepreload 和 prefetch 作为备选。这是向浏览器提出请求,不保证执行、速度或离线可用性。
应用导出的组件
除生命周期 entry 外,manifest 还可在 wu.exports 中声明可共享模块。使用方应用在 wu.imports 中声明 catalog.ProductCard 等依赖;所有应用注册完成后,全局预检验证这些名称。
{
"name": "catalog",
"entry": "assets/catalog.js",
"wu": {
"exports": { "ProductCard": "components/product-card.js" },
"imports": []
}
}
const ProductCard = await wu.use('catalog.ProductCard');
use 严格要求 app.component 格式,检查应用和导出项,并通过延迟 loader 加载模块。如果存在 module.default 则返回它,否则返回模块命名空间。文件必须兼容使用方 renderer;WU 不会自动将 React 组件转换为 Vue 组件。
此方法存在于运行时中,但未列入 WuCore 的公开声明;在类型化代码中使用时,参阅 TypeScript 说明。
loader 将路径限制在应用 base 下,拒绝路径穿越和组件绝对 URL,并使用原生 import。这种模块共享不同于 provide/consume 契约:它本身不包含方法版本管理,也没有与 RPC 相同的作用域模型。
依赖与 CORS
浏览器还需要解析 entry 的全部传递性 imports。如果发布的 bundle 保留 react 或 vue 这样的 bare imports,请提供一致的 import map,或将这些依赖打包。也应将 dist 作为静态文件提供并测试,以发现依赖 Vite 开发服务器的 imports 或路径。
对于跨源 URL,manifest、entry、chunks 和样式都必须符合 CORS 与 CSP 的访问要求。返回 HTML 的 HTTP 200 仍然是错误路径,即使网络面板显示绿色也一样。除 status 外,还要验证内容和 MIME。
实现参考
解析器:src/core/wu-core.js;HEAD 验证:src/core/wu-core.js;import:src/core/wu-core.js;组件:src/core/wu-core.js 和 src/core/wu-loader.js;等待 define:src/core/wu-core.js;策略:src/core/wu-strategies.js;prefetch:src/core/wu-prefetch.js。测试:tests/unit/entry-path-resolution.test.js、tests/unit/prefetch.test.js、tests/unit/dist-bundler-directives.test.js、tests/unit/abort-timeout.test.js。