xpe 1.0.9 → 1.0.11
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.
- package/dist/host/xpe-host.js +3 -1
- package/dist/kernel/effect.js +25 -8
- package/dist/kernel/entry.js +1 -2
- package/dist/kernel/iframe.js +3 -17
- package/dist/kernel/index.js +10 -6
- package/dist/kernel/runtime-engine.d.ts +0 -2
- package/dist/kernel/template.d.ts +0 -2
- package/dist/kernel/template.js +1 -9
- package/package.json +3 -2
- package/dist/kernel/runtime-fetch.d.ts +0 -2
- package/dist/kernel/runtime-fetch.js +0 -11
package/dist/host/xpe-host.js
CHANGED
|
@@ -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({
|
package/dist/kernel/effect.js
CHANGED
|
@@ -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
|
-
|
|
31
|
+
const hasPropertyHandler = isFunction(element[`on${event}`]);
|
|
32
|
+
if (hasPropertyHandler) {
|
|
28
33
|
element[`on${event}`](patchedEvent);
|
|
29
34
|
}
|
|
30
|
-
|
|
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
|
});
|
package/dist/kernel/entry.js
CHANGED
|
@@ -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
|
-
|
|
195
|
-
return "";
|
|
194
|
+
throw new Error(XPE_TIPS_HTML_ERROR_REQUESTED);
|
|
196
195
|
}
|
|
197
196
|
return response.text();
|
|
198
197
|
})
|
package/dist/kernel/iframe.js
CHANGED
|
@@ -727,11 +727,7 @@ function wrapInlineScriptWithSandbox(code) {
|
|
|
727
727
|
}
|
|
728
728
|
function createExecNextScriptContent() {
|
|
729
729
|
return [
|
|
730
|
-
|
|
731
|
-
// create a global lexical binding and fail on the second queued script
|
|
732
|
-
// (notably when Vite's dev client precedes the app entry). `var` is
|
|
733
|
-
// intentionally used so each queue step remains re-entrant.
|
|
734
|
-
"var sandbox = window.__XPE_INTERNAL_SANDBOX__;",
|
|
730
|
+
"const sandbox = window.__XPE_INTERNAL_SANDBOX__;",
|
|
735
731
|
"if(sandbox.execQueue && sandbox.execQueue.length){ sandbox.execQueue.shift()()}",
|
|
736
732
|
].join("");
|
|
737
733
|
}
|
|
@@ -927,7 +923,7 @@ export function syncIframeUrlToWindow(iframeWindow) {
|
|
|
927
923
|
* @param rawElement 原始的脚本
|
|
928
924
|
*/
|
|
929
925
|
export function insertScriptToIframe(scriptResult, iframeWindow, rawElement) {
|
|
930
|
-
const { src, module,
|
|
926
|
+
const { src, module, content, crossorigin, crossoriginType, async, attrs, callback, onload } = scriptResult;
|
|
931
927
|
const sandbox = getActiveSandbox(iframeWindow);
|
|
932
928
|
const container = rawDocumentQuerySelector.call(iframeWindow.document, "head");
|
|
933
929
|
const execNextScript = () => {
|
|
@@ -1005,19 +1001,9 @@ export function insertScriptToIframe(scriptResult, iframeWindow, rawElement) {
|
|
|
1005
1001
|
scriptElement.onerror = afterExecScript;
|
|
1006
1002
|
}
|
|
1007
1003
|
container.appendChild(scriptElement);
|
|
1008
|
-
|
|
1009
|
-
// development HTML. That client keeps a long-lived websocket and may not
|
|
1010
|
-
// dispatch the module load event in the sandbox, so waiting for it would
|
|
1011
|
-
// prevent the real entry module from ever being inserted. It is not an
|
|
1012
|
-
// application lifecycle module and must not participate in the serial
|
|
1013
|
-
// entry gate.
|
|
1014
|
-
const isViteClientModule = module && /(?:^|\/)@vite\/client(?:$|\?)/.test(src);
|
|
1015
|
-
if (isOutlineScript && module && isEntry && !isViteClientModule) {
|
|
1004
|
+
if (isOutlineScript && module) {
|
|
1016
1005
|
waitForModuleLifecycleReady(iframeWindow, afterExecScript);
|
|
1017
1006
|
}
|
|
1018
|
-
if (isOutlineScript && isViteClientModule) {
|
|
1019
|
-
afterExecScript();
|
|
1020
|
-
}
|
|
1021
1007
|
// 调用回调
|
|
1022
1008
|
callback?.(iframeWindow);
|
|
1023
1009
|
// 执行 hooks
|
package/dist/kernel/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { XpeRuntimeError, } from "../core/index.js";
|
|
2
|
-
import { createRuntimeFetch } from "./runtime-fetch.js";
|
|
3
2
|
let runtimeEngineModule;
|
|
4
3
|
let runtimeEngineModulePromise;
|
|
5
4
|
export function createRuntimeKernel() {
|
|
@@ -27,10 +26,10 @@ function loadRuntimeEngine() {
|
|
|
27
26
|
if (runtimeEngineModule)
|
|
28
27
|
return Promise.resolve(runtimeEngineModule);
|
|
29
28
|
if (!runtimeEngineModulePromise) {
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
// @ts-expect-error Vite/Rollup
|
|
29
|
+
// 保持字面量动态 import:Vite/Rollup 等消费方只有在构建期看见静态 specifier,
|
|
30
|
+
// 才会把懒加载内核生成成可部署 chunk。通过变量 import 会在 npm 消费方产物中
|
|
31
|
+
// 留下 ./runtime-engine.js,并错误解析到 Host 自己的 /assets 目录。
|
|
32
|
+
// @ts-expect-error Vite/Rollup 会解析查询参数并生成独立 chunk,TypeScript 不解析该运行时 specifier。
|
|
34
33
|
runtimeEngineModulePromise = import("./runtime-engine.js?xpe-runtime").then((module) => {
|
|
35
34
|
runtimeEngineModule = module;
|
|
36
35
|
return runtimeEngineModule;
|
|
@@ -47,7 +46,7 @@ function toEnginePreloadOptions(manifest) {
|
|
|
47
46
|
alive: runtime.alive,
|
|
48
47
|
sync: runtime.sync,
|
|
49
48
|
prefix: toRuntimePrefix(runtime),
|
|
50
|
-
fetch:
|
|
49
|
+
fetch: toRuntimeFetch(runtime.credentials),
|
|
51
50
|
props: {
|
|
52
51
|
appCode: manifest.appCode,
|
|
53
52
|
manifest,
|
|
@@ -83,3 +82,8 @@ function toRuntimePrefix(runtime) {
|
|
|
83
82
|
return undefined;
|
|
84
83
|
return { [runtime.name]: runtime.basename };
|
|
85
84
|
}
|
|
85
|
+
function toRuntimeFetch(credentials) {
|
|
86
|
+
if (!credentials)
|
|
87
|
+
return undefined;
|
|
88
|
+
return (input, init) => window.fetch(input, { ...init, credentials: init?.credentials ?? credentials });
|
|
89
|
+
}
|
package/dist/kernel/template.js
CHANGED
|
@@ -212,17 +212,9 @@ export default function processTpl(tpl, baseURI, postProcessTemplate) {
|
|
|
212
212
|
return inlineScriptReplaceSymbol;
|
|
213
213
|
}
|
|
214
214
|
});
|
|
215
|
-
const entrySrc = typeof entry === "string" ? entry : entry?.src;
|
|
216
|
-
const entryIndex = entrySrc
|
|
217
|
-
? scripts.findIndex((script) => script.src === entrySrc)
|
|
218
|
-
: scripts.length - 1;
|
|
219
|
-
const scriptsWithEntry = scripts.map((script, index) => ({
|
|
220
|
-
...script,
|
|
221
|
-
isEntry: index === entryIndex,
|
|
222
|
-
}));
|
|
223
215
|
let tplResult = {
|
|
224
216
|
template,
|
|
225
|
-
scripts
|
|
217
|
+
scripts,
|
|
226
218
|
styles,
|
|
227
219
|
// set the last script as entry if have not set
|
|
228
220
|
entry: entry || scripts[scripts.length - 1],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xpe",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
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",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export function createRuntimeFetch(runtimeCredentials, browserFetch = window.fetch.bind(window)) {
|
|
2
|
-
if (!runtimeCredentials)
|
|
3
|
-
return undefined;
|
|
4
|
-
return (input, init) => {
|
|
5
|
-
const requestCredentials = input instanceof Request ? input.credentials : undefined;
|
|
6
|
-
return browserFetch(input, {
|
|
7
|
-
...init,
|
|
8
|
-
credentials: init?.credentials ?? requestCredentials ?? runtimeCredentials,
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
}
|