remote-components 0.0.22 → 0.0.24
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/html/host.cjs +345 -80
- package/dist/html/host.cjs.map +1 -1
- package/dist/html/host.js +347 -79
- package/dist/html/host.js.map +1 -1
- package/dist/internal/next/host/app-router-client.cjs +205 -58
- package/dist/internal/next/host/app-router-client.cjs.map +1 -1
- package/dist/internal/next/host/app-router-client.d.ts +2 -2
- package/dist/internal/next/host/app-router-client.js +213 -59
- package/dist/internal/next/host/app-router-client.js.map +1 -1
- package/dist/internal/next/host/app-router-compat.cjs +114 -0
- package/dist/internal/next/host/app-router-compat.cjs.map +1 -0
- package/dist/internal/next/host/app-router-compat.d.ts +31 -0
- package/dist/internal/next/host/app-router-compat.js +79 -0
- package/dist/internal/next/host/app-router-compat.js.map +1 -0
- package/dist/internal/next/remote/render-client.cjs +10 -2
- package/dist/internal/next/remote/render-client.cjs.map +1 -1
- package/dist/internal/next/remote/render-client.js +10 -2
- package/dist/internal/next/remote/render-client.js.map +1 -1
- package/dist/internal/shared/client/apply-origin.cjs +61 -0
- package/dist/internal/shared/client/apply-origin.cjs.map +1 -0
- package/dist/internal/shared/client/apply-origin.d.ts +3 -0
- package/dist/internal/shared/client/apply-origin.js +37 -0
- package/dist/internal/shared/client/apply-origin.js.map +1 -0
- package/dist/internal/shared/client/polyfill.cjs +149 -0
- package/dist/internal/shared/client/polyfill.cjs.map +1 -0
- package/dist/internal/shared/client/polyfill.d.ts +6 -0
- package/dist/internal/shared/client/polyfill.js +124 -0
- package/dist/internal/shared/client/polyfill.js.map +1 -0
- package/dist/internal/shared/client/remote-component.cjs +3 -3
- package/dist/internal/shared/client/remote-component.cjs.map +1 -1
- package/dist/internal/shared/client/remote-component.d.ts +3 -1
- package/dist/internal/shared/client/remote-component.js +3 -3
- package/dist/internal/shared/client/remote-component.js.map +1 -1
- package/dist/internal/shared/ssr/dom-flight.cjs +49 -17
- package/dist/internal/shared/ssr/dom-flight.cjs.map +1 -1
- package/dist/internal/shared/ssr/dom-flight.js +49 -17
- package/dist/internal/shared/ssr/dom-flight.js.map +1 -1
- package/dist/internal/shared/ssr/fetch-remote-component.cjs +3 -2
- package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
- package/dist/internal/shared/ssr/fetch-remote-component.d.ts +6 -0
- package/dist/internal/shared/ssr/fetch-remote-component.js +3 -2
- package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
- package/dist/next/config.cjs +50 -28
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.js +50 -28
- package/dist/next/config.js.map +1 -1
- package/dist/next/host/app-router-server.cjs +4 -0
- package/dist/next/host/app-router-server.cjs.map +1 -1
- package/dist/next/host/app-router-server.d.ts +5 -1
- package/dist/next/host/app-router-server.js +4 -0
- package/dist/next/host/app-router-server.js.map +1 -1
- package/dist/next/host/client/index.cjs +16 -1
- package/dist/next/host/client/index.cjs.map +1 -1
- package/dist/next/host/client/index.d.ts +1 -1
- package/dist/next/host/client/index.js +16 -1
- package/dist/next/host/client/index.js.map +1 -1
- package/dist/next/host/pages-router-server.cjs +37 -16
- package/dist/next/host/pages-router-server.cjs.map +1 -1
- package/dist/next/host/pages-router-server.d.ts +3 -0
- package/dist/next/host/pages-router-server.js +37 -16
- package/dist/next/host/pages-router-server.js.map +1 -1
- package/dist/next/middleware.cjs +5 -2
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.d.ts +1 -0
- package/dist/next/middleware.js +5 -2
- package/dist/next/middleware.js.map +1 -1
- package/dist/next/remote/pages-router.cjs +3 -1
- package/dist/next/remote/pages-router.cjs.map +1 -1
- package/dist/next/remote/pages-router.d.ts +1 -0
- package/dist/next/remote/pages-router.js +3 -1
- package/dist/next/remote/pages-router.js.map +1 -1
- package/dist/react/index.cjs +235 -156
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +7 -3
- package/dist/react/index.js +225 -146
- package/dist/react/index.js.map +1 -1
- package/dist/{types-7425dfe1.d.ts → types-b8210fd3.d.ts} +2 -0
- package/package.json +1 -1
package/dist/html/host.cjs
CHANGED
|
@@ -395,7 +395,7 @@ function initializeSharedModules(bundle, shared = {}, remoteShared = {}) {
|
|
|
395
395
|
Object.entries(remoteShared).map(async ([id, module2]) => {
|
|
396
396
|
if (self.__remote_shared_modules__?.[bundle]) {
|
|
397
397
|
if (shared[module2]) {
|
|
398
|
-
self.__remote_shared_modules__[bundle][id.replace("[app-ssr]", "[app-client]")] = await shared[module2]();
|
|
398
|
+
self.__remote_shared_modules__[bundle][id.replace("[app-ssr]", "[app-client]")] = await shared[module2](bundle);
|
|
399
399
|
} else {
|
|
400
400
|
console.error(`Shared module "${module2}" not found for "${bundle}".`);
|
|
401
401
|
}
|
|
@@ -408,7 +408,7 @@ function getSharedModule(bundle, id) {
|
|
|
408
408
|
for (const [key, value] of Object.entries(
|
|
409
409
|
self.__remote_shared_modules__?.[bundle] ?? {}
|
|
410
410
|
)) {
|
|
411
|
-
if (typeof id === "string" && id.includes(key) || id === key) {
|
|
411
|
+
if (typeof value !== "undefined" && (typeof id === "string" && id.includes(key) || id === key)) {
|
|
412
412
|
return value;
|
|
413
413
|
}
|
|
414
414
|
}
|
|
@@ -541,6 +541,24 @@ var init_webpack_adapter = __esm({
|
|
|
541
541
|
});
|
|
542
542
|
|
|
543
543
|
// src/shared/client/polyfill.tsx
|
|
544
|
+
function applyBundleUrlToSrc(bundle, src) {
|
|
545
|
+
const self = globalThis;
|
|
546
|
+
if (self.__remote_bundle_url__?.[bundle]?.origin === location.origin) {
|
|
547
|
+
return src;
|
|
548
|
+
}
|
|
549
|
+
const { assetPrefix, path } = /^(?<assetPrefix>.*?)\/_next\/(?<path>.*)/.exec(src)?.groups ?? {};
|
|
550
|
+
if (!path) {
|
|
551
|
+
return new URL(src, self.__remote_bundle_url__?.[bundle]?.origin).href;
|
|
552
|
+
}
|
|
553
|
+
return `${self.__remote_bundle_url__?.[bundle]?.origin ?? ""}${assetPrefix}/_next/${path}`;
|
|
554
|
+
}
|
|
555
|
+
function applyBundleUrlToImagePropsSrc(bundle, src) {
|
|
556
|
+
if (typeof src === "string") {
|
|
557
|
+
return applyBundleUrlToSrc(bundle, src);
|
|
558
|
+
}
|
|
559
|
+
const propSrc = src;
|
|
560
|
+
return applyBundleUrlToSrc(bundle, propSrc.src);
|
|
561
|
+
}
|
|
544
562
|
function sharedPolyfills(shared) {
|
|
545
563
|
const self = globalThis;
|
|
546
564
|
const polyfill = {
|
|
@@ -576,18 +594,17 @@ function sharedPolyfills(shared) {
|
|
|
576
594
|
},
|
|
577
595
|
__esModule: true
|
|
578
596
|
})),
|
|
579
|
-
"next/dist/client/image-component": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? (() => Promise.resolve({
|
|
580
|
-
Image: (
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
),
|
|
597
|
+
"next/dist/client/image-component": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
|
|
598
|
+
Image: imageImpl(bundle),
|
|
599
|
+
__esModule: true
|
|
600
|
+
})),
|
|
601
|
+
"next/image": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
|
|
602
|
+
default: imageImpl(bundle),
|
|
603
|
+
getImageProps: (_imgProps) => {
|
|
604
|
+
throw new Error(
|
|
605
|
+
"Next.js getImageProps() is not implemented in remote components"
|
|
606
|
+
);
|
|
607
|
+
},
|
|
591
608
|
__esModule: true
|
|
592
609
|
})),
|
|
593
610
|
"next/dist/client/script": self.__remote_component_host_shared_modules__?.["next/script"] ?? shared?.["next/script"] ?? (() => Promise.resolve({
|
|
@@ -595,21 +612,56 @@ function sharedPolyfills(shared) {
|
|
|
595
612
|
// do not throw an error for now
|
|
596
613
|
default: () => null,
|
|
597
614
|
__esModule: true
|
|
598
|
-
}))
|
|
615
|
+
})),
|
|
616
|
+
"next/router": self.__remote_component_host_shared_modules__?.["next/router"] ?? shared?.["next/router"] ?? (() => (
|
|
617
|
+
// TODO: incomplete implementation
|
|
618
|
+
Promise.resolve({
|
|
619
|
+
useRouter() {
|
|
620
|
+
return {
|
|
621
|
+
push: (routerUrl) => {
|
|
622
|
+
history.pushState({}, "", routerUrl);
|
|
623
|
+
},
|
|
624
|
+
replace: (routerUrl) => {
|
|
625
|
+
history.replaceState({}, "", routerUrl);
|
|
626
|
+
},
|
|
627
|
+
back: () => {
|
|
628
|
+
history.back();
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
},
|
|
632
|
+
__esModule: true
|
|
633
|
+
})
|
|
634
|
+
))
|
|
599
635
|
};
|
|
600
636
|
polyfill["next/navigation"] = polyfill["next/dist/client/components/navigation"];
|
|
601
637
|
polyfill["next/link"] = polyfill["next/dist/client/app-dir/link"];
|
|
602
638
|
polyfill["next/form"] = polyfill["next/dist/client/app-dir/form"];
|
|
603
|
-
polyfill["next/image"] = polyfill["next/dist/client/image-component"];
|
|
604
639
|
polyfill["next/dist/api/image"] = polyfill["next/dist/client/image-component"];
|
|
605
640
|
polyfill["next/script"] = polyfill["next/dist/client/script"];
|
|
606
641
|
return polyfill;
|
|
607
642
|
}
|
|
608
|
-
var import_jsx_runtime;
|
|
643
|
+
var import_jsx_runtime, imageImpl;
|
|
609
644
|
var init_polyfill = __esm({
|
|
610
645
|
"src/shared/client/polyfill.tsx"() {
|
|
611
646
|
"use strict";
|
|
647
|
+
// eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text
|
|
612
648
|
import_jsx_runtime = require("react/jsx-runtime");
|
|
649
|
+
imageImpl = (bundle) => function RemoteImage({ priority: _, ...props }) {
|
|
650
|
+
const newSrc = applyBundleUrlToImagePropsSrc(
|
|
651
|
+
bundle,
|
|
652
|
+
typeof props.src === "string" ? props.src : props.src.src
|
|
653
|
+
);
|
|
654
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
655
|
+
"img",
|
|
656
|
+
{
|
|
657
|
+
decoding: "async",
|
|
658
|
+
style: { color: "transparent" },
|
|
659
|
+
...props,
|
|
660
|
+
src: newSrc,
|
|
661
|
+
suppressHydrationWarning: true
|
|
662
|
+
}
|
|
663
|
+
);
|
|
664
|
+
};
|
|
613
665
|
}
|
|
614
666
|
});
|
|
615
667
|
|
|
@@ -652,6 +704,7 @@ async function webpackRuntime(bundle, shared, remoteShared) {
|
|
|
652
704
|
const newScript = document.createElement("script");
|
|
653
705
|
newScript.onload = () => {
|
|
654
706
|
resolve2();
|
|
707
|
+
newScript.remove();
|
|
655
708
|
};
|
|
656
709
|
newScript.onerror = () => {
|
|
657
710
|
reject(
|
|
@@ -659,6 +712,7 @@ async function webpackRuntime(bundle, shared, remoteShared) {
|
|
|
659
712
|
`Failed to load script ${script.src} for remote component`
|
|
660
713
|
)
|
|
661
714
|
);
|
|
715
|
+
newScript.remove();
|
|
662
716
|
};
|
|
663
717
|
const scriptSrc = script.getAttribute("src") || script.getAttribute("data-src");
|
|
664
718
|
if (scriptSrc) {
|
|
@@ -697,7 +751,7 @@ async function webpackRuntime(bundle, shared, remoteShared) {
|
|
|
697
751
|
await Promise.all(
|
|
698
752
|
Object.entries(resolve).map(async ([key, value]) => {
|
|
699
753
|
if (typeof value === "function") {
|
|
700
|
-
resolve[key] = await value();
|
|
754
|
+
resolve[key] = await value(remoteBundle);
|
|
701
755
|
}
|
|
702
756
|
return Promise.resolve(value);
|
|
703
757
|
})
|
|
@@ -781,6 +835,7 @@ __export(host_exports, {
|
|
|
781
835
|
registerSharedModules: () => registerSharedModules
|
|
782
836
|
});
|
|
783
837
|
module.exports = __toCommonJS(host_exports);
|
|
838
|
+
var import_react = require("react");
|
|
784
839
|
var import_client = require("react-dom/client");
|
|
785
840
|
|
|
786
841
|
// src/shared/client/component-loader.ts
|
|
@@ -862,6 +917,41 @@ function createRSCStream(name, data) {
|
|
|
862
917
|
init_webpack_adapter();
|
|
863
918
|
init_const();
|
|
864
919
|
|
|
920
|
+
// src/shared/client/apply-origin.ts
|
|
921
|
+
var tagNames = [
|
|
922
|
+
"img",
|
|
923
|
+
"source",
|
|
924
|
+
"video",
|
|
925
|
+
"audio",
|
|
926
|
+
"track",
|
|
927
|
+
"iframe",
|
|
928
|
+
"embed",
|
|
929
|
+
"script",
|
|
930
|
+
"link"
|
|
931
|
+
];
|
|
932
|
+
function applyOriginToNodes(doc, url) {
|
|
933
|
+
const nodes = doc.querySelectorAll(
|
|
934
|
+
tagNames.map((type) => `${type}[src],${type}[srcset]`).join(",")
|
|
935
|
+
);
|
|
936
|
+
nodes.forEach((node) => {
|
|
937
|
+
if (node.hasAttribute("src") && /^[./]+\/?/.test(node.getAttribute("src") ?? "")) {
|
|
938
|
+
node.src = new URL(node.getAttribute("src") ?? "/", url).href;
|
|
939
|
+
}
|
|
940
|
+
if (node.hasAttribute("srcset")) {
|
|
941
|
+
const srcSet = node.getAttribute("srcset")?.split(",").map((entry) => {
|
|
942
|
+
const [urlPart, descriptor] = entry.trim().split(/\s+/);
|
|
943
|
+
if (!urlPart)
|
|
944
|
+
return entry;
|
|
945
|
+
const absoluteUrl = new URL(urlPart, url).href;
|
|
946
|
+
return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
|
|
947
|
+
}).join(", ");
|
|
948
|
+
if (srcSet) {
|
|
949
|
+
node.setAttribute("srcset", srcSet);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
|
|
865
955
|
// src/html/host/runtime/index.ts
|
|
866
956
|
async function getRuntime(type, url, bundle, shared, remoteShared) {
|
|
867
957
|
if (typeof globalThis.process === "undefined") {
|
|
@@ -884,38 +974,64 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
884
974
|
if (typeof HTMLElement !== "undefined") {
|
|
885
975
|
class RemoteComponent extends HTMLElement {
|
|
886
976
|
constructor() {
|
|
887
|
-
super();
|
|
977
|
+
super(...arguments);
|
|
888
978
|
this.__next = null;
|
|
889
979
|
this.fouc = null;
|
|
890
980
|
this.isLoading = false;
|
|
891
|
-
this.
|
|
892
|
-
this.fallbackSlot = document.createElement("slot");
|
|
893
|
-
this.shadowRoot?.appendChild(this.fallbackSlot);
|
|
894
|
-
this.name = this.getAttribute("name") || "__vercel_remote_component";
|
|
895
|
-
this.bundle = "default";
|
|
896
|
-
if (this.hasAttribute("src") || this.querySelector("div#__REMOTE_COMPONENT__") || this.hasAttribute("data-ssr")) {
|
|
897
|
-
this.load().catch((e) => {
|
|
898
|
-
throw new Error(`Failed to load remote component: ${e}`);
|
|
899
|
-
});
|
|
900
|
-
}
|
|
981
|
+
this.root = null;
|
|
901
982
|
}
|
|
902
983
|
static get observedAttributes() {
|
|
903
|
-
return ["src"];
|
|
984
|
+
return ["src", "name", "mode"];
|
|
904
985
|
}
|
|
905
986
|
// watch for src attribute changes
|
|
906
987
|
// this is required to reload the remote component when the src attribute is added later
|
|
907
988
|
// this is for rendering the custom element using React
|
|
908
989
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
909
|
-
if (name === "src" && oldValue !== newValue) {
|
|
990
|
+
if ((name === "src" || name === "name") && oldValue !== newValue) {
|
|
991
|
+
if (this.getAttribute("src")) {
|
|
992
|
+
this.load().catch((e) => {
|
|
993
|
+
console.error(e);
|
|
994
|
+
throw new Error(
|
|
995
|
+
`Failed to load remote component: ${this.bundle ?? this.name ?? this.getAttribute("src")}`
|
|
996
|
+
);
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
} else if (name === "mode" && oldValue !== newValue && this.root) {
|
|
1000
|
+
const newRoot = this.attachShadow({
|
|
1001
|
+
mode: newValue === "closed" ? "closed" : "open"
|
|
1002
|
+
});
|
|
1003
|
+
Array.from(this.root.children).forEach((child) => {
|
|
1004
|
+
newRoot.appendChild(child);
|
|
1005
|
+
});
|
|
1006
|
+
this.root = newRoot;
|
|
910
1007
|
this.load().catch((e) => {
|
|
911
1008
|
throw new Error(`Failed to load remote component: ${e}`);
|
|
912
1009
|
});
|
|
913
1010
|
}
|
|
914
1011
|
}
|
|
915
1012
|
async load() {
|
|
1013
|
+
await new Promise((resolve) => {
|
|
1014
|
+
(typeof queueMicrotask === "function" ? queueMicrotask : requestAnimationFrame)(() => {
|
|
1015
|
+
resolve(void 0);
|
|
1016
|
+
});
|
|
1017
|
+
});
|
|
916
1018
|
if (this.isLoading) {
|
|
917
1019
|
return;
|
|
918
1020
|
}
|
|
1021
|
+
if (!this.root) {
|
|
1022
|
+
this.root = this.attachShadow({
|
|
1023
|
+
mode: this.getAttribute("mode") === "closed" ? "closed" : "open"
|
|
1024
|
+
});
|
|
1025
|
+
this.fallbackSlot = document.createElement("slot");
|
|
1026
|
+
this.root.appendChild(this.fallbackSlot);
|
|
1027
|
+
}
|
|
1028
|
+
this.name = this.getAttribute("name") || "__vercel_remote_component";
|
|
1029
|
+
this.bundle = "default";
|
|
1030
|
+
if (this.hasAttribute("src") || this.querySelector("div#__REMOTE_COMPONENT__") || this.hasAttribute("data-ssr")) {
|
|
1031
|
+
this.load().catch((e) => {
|
|
1032
|
+
throw new Error(`Failed to load remote component: ${e}`);
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
919
1035
|
this.isLoading = true;
|
|
920
1036
|
const src = this.getAttribute("src");
|
|
921
1037
|
const remoteComponentChild = this.querySelector("div#__REMOTE_COMPONENT__") || this.querySelector("div[data-bundle][data-route]");
|
|
@@ -946,22 +1062,29 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
946
1062
|
}
|
|
947
1063
|
html = await res.text();
|
|
948
1064
|
}
|
|
949
|
-
const
|
|
950
|
-
doc
|
|
1065
|
+
const parser = new DOMParser();
|
|
1066
|
+
const doc = parser.parseFromString(html, "text/html");
|
|
951
1067
|
const component = doc.querySelector(`div[data-bundle][data-route][id^="${this.name}"]`) ?? // fallback to the first element with the data-bundle and data-route attributes when not using a named remote component
|
|
952
1068
|
doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
|
|
953
1069
|
doc.querySelector("div#__next");
|
|
954
1070
|
const nextData = JSON.parse(
|
|
955
1071
|
(doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
|
|
956
1072
|
);
|
|
957
|
-
if (nextData && nextData.buildId === "development") {
|
|
1073
|
+
if (nextData && nextData.buildId === "development" && !this.reactRoot) {
|
|
958
1074
|
this.fouc = document.createElement("style");
|
|
959
1075
|
this.fouc.textContent = `:host { display: none; }`;
|
|
960
|
-
this.
|
|
1076
|
+
this.root.appendChild(this.fouc);
|
|
961
1077
|
}
|
|
962
1078
|
this.name = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : this.name);
|
|
963
1079
|
const rsc = doc.querySelector(`#${this.name}_rsc`);
|
|
964
1080
|
this.bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || this.bundle;
|
|
1081
|
+
if (url) {
|
|
1082
|
+
const self2 = globalThis;
|
|
1083
|
+
if (!self2.__remote_bundle_url__) {
|
|
1084
|
+
self2.__remote_bundle_url__ = {};
|
|
1085
|
+
}
|
|
1086
|
+
self2.__remote_bundle_url__[this.bundle ?? "default"] = url;
|
|
1087
|
+
}
|
|
965
1088
|
const metadata = document.createElement("script");
|
|
966
1089
|
metadata.type = "application/json";
|
|
967
1090
|
metadata.setAttribute("data-remote-component", "");
|
|
@@ -971,54 +1094,116 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
971
1094
|
route: component?.getAttribute("data-route") ?? nextData?.page ?? "/",
|
|
972
1095
|
runtime: component?.getAttribute("data-runtime") ?? nextData?.props.__REMOTE_COMPONENT__?.runtime
|
|
973
1096
|
});
|
|
974
|
-
this.
|
|
975
|
-
|
|
976
|
-
|
|
1097
|
+
if (this.previousElementSibling?.getAttribute("data-remote-component") !== null) {
|
|
1098
|
+
this.previousElementSibling?.remove();
|
|
1099
|
+
}
|
|
1100
|
+
this.parentElement?.insertBefore(metadata, this);
|
|
1101
|
+
const remoteSharedEl = doc.querySelector(
|
|
1102
|
+
`#${this.name}_shared[data-remote-components-shared]`
|
|
1103
|
+
);
|
|
1104
|
+
const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
|
|
977
1105
|
remoteSharedEl?.parentElement?.removeChild(remoteSharedEl);
|
|
978
1106
|
if (!component || !(rsc || nextData)) {
|
|
979
1107
|
throw new Error(`Failed to find component with id "${this.name}"`);
|
|
980
1108
|
}
|
|
981
1109
|
const removable = Array.from(this.childNodes);
|
|
982
1110
|
const links = doc.querySelectorAll("link[href]");
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1111
|
+
const remoteComponentSrc = this.getAttribute("src");
|
|
1112
|
+
const attachLinks = async () => {
|
|
1113
|
+
await Promise.all(
|
|
1114
|
+
Array.from(links).filter((link) => {
|
|
1115
|
+
return !component.contains(link);
|
|
1116
|
+
}).map((link) => {
|
|
1117
|
+
return new Promise((resolve, reject) => {
|
|
1118
|
+
const newLink = document.createElement("link");
|
|
1119
|
+
if (link.rel === "stylesheet") {
|
|
1120
|
+
newLink.onload = () => {
|
|
1121
|
+
resolve();
|
|
1122
|
+
};
|
|
1123
|
+
newLink.onerror = () => {
|
|
1124
|
+
reject(
|
|
1125
|
+
new Error(
|
|
1126
|
+
`Failed to load link ${link.href} for remote component`
|
|
1127
|
+
)
|
|
1128
|
+
);
|
|
1129
|
+
};
|
|
1130
|
+
} else {
|
|
989
1131
|
resolve();
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
if (attr.name === "href") {
|
|
1132
|
+
}
|
|
1133
|
+
for (const attr of link.attributes) {
|
|
1134
|
+
if (attr.name === "href") {
|
|
1135
|
+
newLink.setAttribute(
|
|
1136
|
+
attr.name,
|
|
1137
|
+
new URL(attr.value, url ?? location.origin).href
|
|
1138
|
+
);
|
|
1139
|
+
} else {
|
|
1140
|
+
newLink.setAttribute(attr.name, attr.value);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
if (remoteComponentSrc) {
|
|
1003
1144
|
newLink.setAttribute(
|
|
1004
|
-
|
|
1005
|
-
|
|
1145
|
+
"data-remote-component-src",
|
|
1146
|
+
remoteComponentSrc
|
|
1006
1147
|
);
|
|
1007
|
-
} else {
|
|
1008
|
-
newLink.setAttribute(attr.name, attr.value);
|
|
1009
1148
|
}
|
|
1149
|
+
this.root?.appendChild(newLink);
|
|
1150
|
+
});
|
|
1151
|
+
})
|
|
1152
|
+
);
|
|
1153
|
+
const styles = doc.querySelectorAll("style");
|
|
1154
|
+
styles.forEach((style) => {
|
|
1155
|
+
if (style.parentElement?.tagName.toLowerCase() === "head") {
|
|
1156
|
+
const newStyle = document.createElement("style");
|
|
1157
|
+
newStyle.textContent = style.textContent;
|
|
1158
|
+
if (remoteComponentSrc) {
|
|
1159
|
+
newStyle.setAttribute(
|
|
1160
|
+
"data-remote-component-src",
|
|
1161
|
+
remoteComponentSrc
|
|
1162
|
+
);
|
|
1010
1163
|
}
|
|
1011
|
-
this.
|
|
1012
|
-
}
|
|
1013
|
-
})
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
}
|
|
1164
|
+
this.root?.appendChild(newStyle);
|
|
1165
|
+
}
|
|
1166
|
+
});
|
|
1167
|
+
};
|
|
1168
|
+
if (!this.reactRoot) {
|
|
1169
|
+
await attachLinks();
|
|
1170
|
+
}
|
|
1171
|
+
applyOriginToNodes(doc, url ?? new URL(location.href));
|
|
1172
|
+
if (!this.reactRoot) {
|
|
1173
|
+
Array.from(component.children).forEach((el) => {
|
|
1174
|
+
this.root?.appendChild(el);
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1018
1177
|
for (const el of removable) {
|
|
1019
1178
|
el.parentElement?.removeChild(el);
|
|
1020
1179
|
}
|
|
1021
|
-
this.
|
|
1180
|
+
this.fallbackSlot?.remove();
|
|
1181
|
+
const applyReset = () => {
|
|
1182
|
+
if (this.getAttribute("reset") !== null && !this.root?.querySelector("link[data-remote-components-reset]")) {
|
|
1183
|
+
const allInitial = document.createElement("link");
|
|
1184
|
+
allInitial.setAttribute("data-remote-components-reset", "");
|
|
1185
|
+
const css = `:host { all: initial; }`;
|
|
1186
|
+
const allInitialHref = URL.createObjectURL(
|
|
1187
|
+
new Blob([css], { type: "text/css" })
|
|
1188
|
+
);
|
|
1189
|
+
allInitial.href = allInitialHref;
|
|
1190
|
+
allInitial.rel = "stylesheet";
|
|
1191
|
+
allInitial.onload = () => {
|
|
1192
|
+
URL.revokeObjectURL(allInitialHref);
|
|
1193
|
+
allInitial.removeAttribute("onload");
|
|
1194
|
+
};
|
|
1195
|
+
allInitial.onerror = () => {
|
|
1196
|
+
URL.revokeObjectURL(allInitialHref);
|
|
1197
|
+
allInitial.removeAttribute("onload");
|
|
1198
|
+
};
|
|
1199
|
+
this.root?.prepend(allInitial);
|
|
1200
|
+
} else if (this.getAttribute("reset") === null && this.root?.querySelector("link[data-remote-components-reset]")) {
|
|
1201
|
+
this.root.querySelector("link[data-remote-components-reset]")?.remove();
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
if (!this.reactRoot) {
|
|
1205
|
+
applyReset();
|
|
1206
|
+
}
|
|
1022
1207
|
const {
|
|
1023
1208
|
self,
|
|
1024
1209
|
createFromReadableStream,
|
|
@@ -1046,7 +1231,26 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1046
1231
|
window.location.href
|
|
1047
1232
|
);
|
|
1048
1233
|
}
|
|
1049
|
-
await preloadScripts(
|
|
1234
|
+
await preloadScripts(
|
|
1235
|
+
Array.from(scripts),
|
|
1236
|
+
url,
|
|
1237
|
+
this.bundle ?? "default",
|
|
1238
|
+
this.name ?? "__vercel_remote_component"
|
|
1239
|
+
);
|
|
1240
|
+
const doCleanup = () => {
|
|
1241
|
+
if (this.root && remoteComponentSrc) {
|
|
1242
|
+
const selector = `[data-remote-component-src]:not([data-remote-component-src="${remoteComponentSrc}"])`;
|
|
1243
|
+
const prevCleanup = [
|
|
1244
|
+
...this.root.querySelectorAll(selector),
|
|
1245
|
+
...document.body.querySelectorAll(selector)
|
|
1246
|
+
];
|
|
1247
|
+
if (prevCleanup.length > 0) {
|
|
1248
|
+
prevCleanup.forEach((prev) => {
|
|
1249
|
+
prev.remove();
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
};
|
|
1050
1254
|
if (rsc) {
|
|
1051
1255
|
rsc.parentElement?.removeChild(rsc);
|
|
1052
1256
|
const rscClone = document.createElement("script");
|
|
@@ -1055,36 +1259,97 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1055
1259
|
document.body.appendChild(rscClone);
|
|
1056
1260
|
let cache;
|
|
1057
1261
|
const RemoteComponentFromReadableStream = ({
|
|
1058
|
-
name
|
|
1262
|
+
name,
|
|
1263
|
+
initial
|
|
1059
1264
|
}) => {
|
|
1060
1265
|
const stream = createRSCStream(name, self[name] ?? [`0:[null]
|
|
1061
1266
|
`]);
|
|
1062
1267
|
const Component = cache ?? // cache the component to avoid reloading the RSC flight data
|
|
1063
1268
|
(cache = createFromReadableStream(stream));
|
|
1269
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
1270
|
+
if (self[name]) {
|
|
1271
|
+
delete self[name];
|
|
1272
|
+
}
|
|
1273
|
+
const rscScript = document.getElementById(`${name}_rsc`);
|
|
1274
|
+
if (rscScript) {
|
|
1275
|
+
rscScript.remove();
|
|
1276
|
+
}
|
|
1277
|
+
doCleanup();
|
|
1278
|
+
applyReset();
|
|
1279
|
+
if (!initial) {
|
|
1280
|
+
attachLinks().catch((e) => {
|
|
1281
|
+
console.error(e);
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
this.isLoading = false;
|
|
1285
|
+
}, [initial, name]);
|
|
1064
1286
|
return Component;
|
|
1065
1287
|
};
|
|
1066
|
-
(
|
|
1288
|
+
if (this.reactRoot) {
|
|
1289
|
+
const root = this.reactRoot;
|
|
1290
|
+
(0, import_react.startTransition)(() => {
|
|
1291
|
+
root.render(
|
|
1292
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1293
|
+
RemoteComponentFromReadableStream,
|
|
1294
|
+
{
|
|
1295
|
+
initial: false,
|
|
1296
|
+
name: this.name ?? "__vercel_remote_component"
|
|
1297
|
+
}
|
|
1298
|
+
)
|
|
1299
|
+
);
|
|
1300
|
+
});
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
this.reactRoot = (0, import_client.hydrateRoot)(
|
|
1067
1304
|
// hydrateRoot expects a document or element, but it works for the shadow DOM too
|
|
1068
1305
|
// @ts-expect-error support for shadow DOM
|
|
1069
|
-
this.
|
|
1070
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1306
|
+
this.root,
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1308
|
+
RemoteComponentFromReadableStream,
|
|
1309
|
+
{
|
|
1310
|
+
initial: true,
|
|
1311
|
+
name: this.name ?? "__vercel_remote_component"
|
|
1312
|
+
}
|
|
1313
|
+
)
|
|
1071
1314
|
);
|
|
1072
1315
|
} else if (nextData) {
|
|
1073
1316
|
const { Component, App } = nextClientPagesLoader2(
|
|
1074
|
-
this.bundle,
|
|
1317
|
+
this.bundle ?? "default",
|
|
1075
1318
|
nextData.page,
|
|
1076
|
-
this.
|
|
1319
|
+
this.root
|
|
1077
1320
|
);
|
|
1078
1321
|
if (Component) {
|
|
1079
|
-
(
|
|
1322
|
+
const RemoteComponentFromNext = ((NextApp, NextComponent, remoteComponent = this) => function RemoteComponentNext({ initial }) {
|
|
1323
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
1324
|
+
doCleanup();
|
|
1325
|
+
if (!initial) {
|
|
1326
|
+
applyReset();
|
|
1327
|
+
attachLinks().catch((e) => {
|
|
1328
|
+
console.error(e);
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
remoteComponent.isLoading = false;
|
|
1332
|
+
}, [initial]);
|
|
1333
|
+
return NextApp ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(NextApp, { Component: NextComponent, ...nextData.props }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(NextComponent, { ...nextData.props });
|
|
1334
|
+
})(App, Component, this);
|
|
1335
|
+
if (this.reactRoot) {
|
|
1336
|
+
const root = this.reactRoot;
|
|
1337
|
+
(0, import_react.startTransition)(() => {
|
|
1338
|
+
root.render(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RemoteComponentFromNext, { initial: false }));
|
|
1339
|
+
doCleanup();
|
|
1340
|
+
this.isLoading = false;
|
|
1341
|
+
});
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
this.reactRoot = (0, import_client.hydrateRoot)(
|
|
1080
1345
|
// hydrateRoot expects a document or element, but it works for the shadow DOM too
|
|
1081
1346
|
// @ts-expect-error support for shadow DOM
|
|
1082
|
-
this.
|
|
1083
|
-
|
|
1347
|
+
this.root,
|
|
1348
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RemoteComponentFromNext, { initial: true })
|
|
1084
1349
|
);
|
|
1085
1350
|
}
|
|
1086
1351
|
if (this.fouc) {
|
|
1087
|
-
this.
|
|
1352
|
+
this.root.removeChild(this.fouc);
|
|
1088
1353
|
}
|
|
1089
1354
|
}
|
|
1090
1355
|
this.isLoading = false;
|