xpe 1.0.10 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,9 @@ export function createHost(options) {
10
10
  onHostNavigate: options.onHostNavigate,
11
11
  onRouteChange(event) {
12
12
  options.onNavigate?.(event);
13
- void router.navigate(event.appCode, event.target);
13
+ void router.navigate(event.appCode, event.target).catch((error) => {
14
+ options.onError?.(error);
15
+ });
14
16
  },
15
17
  });
16
18
  const router = createAppPathRouter({
@@ -21,13 +21,30 @@ function patchCustomEvent(e, elementGetter) {
21
21
  /**
22
22
  * 手动触发事件回调
23
23
  */
24
- function manualInvokeElementEvent(element, event) {
24
+ function manualInvokeElementEvent(element, event, sandboxId) {
25
+ // 动态 link/script 节点由子应用 realm 创建,但被 XPE 转发到宿主
26
+ // shadowRoot。此时节点上的原生 dispatchEvent 可能无法命中由子应用
27
+ // Node.prototype.addEventListener 注册的回调。事件代理已经把回调保存在
28
+ // sandbox 的缓存中,优先从缓存派发,保证 Vite 的 load/error Promise 收敛。
25
29
  const customEvent = new CustomEvent(event);
26
30
  const patchedEvent = patchCustomEvent(customEvent, () => element);
27
- if (isFunction(element[`on${event}`])) {
31
+ const hasPropertyHandler = isFunction(element[`on${event}`]);
32
+ if (hasPropertyHandler) {
28
33
  element[`on${event}`](patchedEvent);
29
34
  }
30
- else {
35
+ const listeners = sandboxId
36
+ ? getSandboxById(sandboxId)?.elementEventCacheMap.get(element)
37
+ : undefined;
38
+ const cachedListeners = listeners?.filter((listener) => listener.type === event) ?? [];
39
+ if (cachedListeners.length) {
40
+ cachedListeners.forEach((listener) => {
41
+ if (typeof listener.callback === "function")
42
+ listener.callback.call(element, patchedEvent);
43
+ else
44
+ listener.callback.handleEvent(patchedEvent);
45
+ });
46
+ }
47
+ else if (!hasPropertyHandler) {
31
48
  element.dispatchEvent(patchedEvent);
32
49
  }
33
50
  }
@@ -235,7 +252,7 @@ export function deferStyleSheetByHref(opts) {
235
252
  const target = element;
236
253
  finalize();
237
254
  if (target)
238
- manualInvokeElementEvent(target, "error");
255
+ manualInvokeElementEvent(target, "error", sandboxId);
239
256
  }, DEFER_STYLE_HREF_TIMEOUT);
240
257
  }
241
258
  function rewriteAppendOrInsertChild(opts) {
@@ -296,12 +313,12 @@ function rewriteAppendOrInsertChild(opts) {
296
313
  rawDOMAppendOrInsertBefore.call(this, stylesheetElement, refChild);
297
314
  // 处理样式补丁
298
315
  handleStylesheetElementPatch(stylesheetElement, latestContext.sandbox);
299
- manualInvokeElementEvent(linkElement, "load");
316
+ manualInvokeElementEvent(linkElement, "load", sandboxId);
300
317
  }
301
318
  if (element === linkElement)
302
319
  element = null;
303
320
  }, () => {
304
- manualInvokeElementEvent(linkElement, "error");
321
+ manualInvokeElementEvent(linkElement, "error", sandboxId);
305
322
  if (element === linkElement)
306
323
  element = null;
307
324
  }));
@@ -346,7 +363,7 @@ function rewriteAppendOrInsertChild(opts) {
346
363
  if (!latestContext)
347
364
  return warn(XPE_TIPS_REPEAT_RENDER);
348
365
  const onload = () => {
349
- manualInvokeElementEvent(element, "load");
366
+ manualInvokeElementEvent(element, "load", sandboxId);
350
367
  element = null;
351
368
  };
352
369
  insertScriptToIframe({ ...scriptResult, onload }, latestContext.iframeWindow, element);
@@ -373,7 +390,7 @@ function rewriteAppendOrInsertChild(opts) {
373
390
  if (!execQueueLength)
374
391
  sandbox.execQueue.shift()();
375
392
  }, () => {
376
- manualInvokeElementEvent(element, "error");
393
+ manualInvokeElementEvent(element, "error", sandboxId);
377
394
  element = null;
378
395
  }));
379
396
  });
@@ -191,8 +191,7 @@ export default function importHTML(params) {
191
191
  .then((response) => {
192
192
  if (response.status >= 400) {
193
193
  error(XPE_TIPS_HTML_ERROR_REQUESTED, { url, response });
194
- loadError?.(url, new Error(XPE_TIPS_HTML_ERROR_REQUESTED));
195
- return "";
194
+ throw new Error(XPE_TIPS_HTML_ERROR_REQUESTED);
196
195
  }
197
196
  return response.text();
198
197
  })
@@ -27,10 +27,10 @@ function loadRuntimeEngine() {
27
27
  if (runtimeEngineModule)
28
28
  return Promise.resolve(runtimeEngineModule);
29
29
  if (!runtimeEngineModulePromise) {
30
- // Keep a literal dynamic import so Vite/Rollup bundles the runtime engine
31
- // into a deployable child chunk instead of leaving a missing relative URL
32
- // in the host's optimized dependency directory.
33
- // @ts-expect-error Vite/Rollup resolves the query-suffixed runtime chunk at build time.
30
+ // 保持字面量动态 import:Vite/Rollup 等消费方只有在构建期看见静态 specifier,
31
+ // 才会把懒加载内核生成成可部署 chunk。通过变量 import 会在 npm 消费方产物中
32
+ // 留下 ./runtime-engine.js,并错误解析到 Host 自己的 /assets 目录。
33
+ // @ts-expect-error Vite/Rollup 会解析查询参数并生成独立 chunk,TypeScript 不解析该运行时 specifier。
34
34
  runtimeEngineModulePromise = import("./runtime-engine.js?xpe-runtime").then((module) => {
35
35
  runtimeEngineModule = module;
36
36
  return runtimeEngineModule;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xpe",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "下一代微前端应用运行底座",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -46,11 +46,12 @@
46
46
  "check:example-build": "pnpm run typecheck:browser-smoke && pnpm run build:example",
47
47
  "check:host-child-smoke": "node scripts/check-host-child-smoke.mjs",
48
48
  "check:dist-surface": "node scripts/check-dist-surface.mjs",
49
+ "check:vite-consumer-build": "node scripts/check-vite-consumer-build.mjs",
49
50
  "check:kernel-surface": "node scripts/check-kernel-surface.mjs",
50
51
  "check:pack": "pnpm pack --dry-run",
51
52
  "check:public-surface": "node scripts/check-public-surface.mjs",
52
53
  "check:release-metadata": "node scripts/check-release-metadata.mjs",
53
- "verify": "pnpm run check:release-metadata && pnpm run typecheck && pnpm test && pnpm run build && pnpm run check:pack",
54
+ "verify": "pnpm run check:release-metadata && pnpm run typecheck && pnpm test && pnpm run build && pnpm run check:vite-consumer-build && pnpm run check:pack",
54
55
  "prepack": "pnpm run build",
55
56
  "prepublishOnly": "pnpm run verify",
56
57
  "test": "vitest run",