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.js
CHANGED
|
@@ -373,7 +373,7 @@ function initializeSharedModules(bundle, shared = {}, remoteShared = {}) {
|
|
|
373
373
|
Object.entries(remoteShared).map(async ([id, module]) => {
|
|
374
374
|
if (self.__remote_shared_modules__?.[bundle]) {
|
|
375
375
|
if (shared[module]) {
|
|
376
|
-
self.__remote_shared_modules__[bundle][id.replace("[app-ssr]", "[app-client]")] = await shared[module]();
|
|
376
|
+
self.__remote_shared_modules__[bundle][id.replace("[app-ssr]", "[app-client]")] = await shared[module](bundle);
|
|
377
377
|
} else {
|
|
378
378
|
console.error(`Shared module "${module}" not found for "${bundle}".`);
|
|
379
379
|
}
|
|
@@ -386,7 +386,7 @@ function getSharedModule(bundle, id) {
|
|
|
386
386
|
for (const [key, value] of Object.entries(
|
|
387
387
|
self.__remote_shared_modules__?.[bundle] ?? {}
|
|
388
388
|
)) {
|
|
389
|
-
if (typeof id === "string" && id.includes(key) || id === key) {
|
|
389
|
+
if (typeof value !== "undefined" && (typeof id === "string" && id.includes(key) || id === key)) {
|
|
390
390
|
return value;
|
|
391
391
|
}
|
|
392
392
|
}
|
|
@@ -520,6 +520,24 @@ var init_webpack_adapter = __esm({
|
|
|
520
520
|
|
|
521
521
|
// src/shared/client/polyfill.tsx
|
|
522
522
|
import { jsx } from "react/jsx-runtime";
|
|
523
|
+
function applyBundleUrlToSrc(bundle, src) {
|
|
524
|
+
const self = globalThis;
|
|
525
|
+
if (self.__remote_bundle_url__?.[bundle]?.origin === location.origin) {
|
|
526
|
+
return src;
|
|
527
|
+
}
|
|
528
|
+
const { assetPrefix, path } = /^(?<assetPrefix>.*?)\/_next\/(?<path>.*)/.exec(src)?.groups ?? {};
|
|
529
|
+
if (!path) {
|
|
530
|
+
return new URL(src, self.__remote_bundle_url__?.[bundle]?.origin).href;
|
|
531
|
+
}
|
|
532
|
+
return `${self.__remote_bundle_url__?.[bundle]?.origin ?? ""}${assetPrefix}/_next/${path}`;
|
|
533
|
+
}
|
|
534
|
+
function applyBundleUrlToImagePropsSrc(bundle, src) {
|
|
535
|
+
if (typeof src === "string") {
|
|
536
|
+
return applyBundleUrlToSrc(bundle, src);
|
|
537
|
+
}
|
|
538
|
+
const propSrc = src;
|
|
539
|
+
return applyBundleUrlToSrc(bundle, propSrc.src);
|
|
540
|
+
}
|
|
523
541
|
function sharedPolyfills(shared) {
|
|
524
542
|
const self = globalThis;
|
|
525
543
|
const polyfill = {
|
|
@@ -555,18 +573,17 @@ function sharedPolyfills(shared) {
|
|
|
555
573
|
},
|
|
556
574
|
__esModule: true
|
|
557
575
|
})),
|
|
558
|
-
"next/dist/client/image-component": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? (() => Promise.resolve({
|
|
559
|
-
Image: (
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
),
|
|
576
|
+
"next/dist/client/image-component": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
|
|
577
|
+
Image: imageImpl(bundle),
|
|
578
|
+
__esModule: true
|
|
579
|
+
})),
|
|
580
|
+
"next/image": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
|
|
581
|
+
default: imageImpl(bundle),
|
|
582
|
+
getImageProps: (_imgProps) => {
|
|
583
|
+
throw new Error(
|
|
584
|
+
"Next.js getImageProps() is not implemented in remote components"
|
|
585
|
+
);
|
|
586
|
+
},
|
|
570
587
|
__esModule: true
|
|
571
588
|
})),
|
|
572
589
|
"next/dist/client/script": self.__remote_component_host_shared_modules__?.["next/script"] ?? shared?.["next/script"] ?? (() => Promise.resolve({
|
|
@@ -574,19 +591,57 @@ function sharedPolyfills(shared) {
|
|
|
574
591
|
// do not throw an error for now
|
|
575
592
|
default: () => null,
|
|
576
593
|
__esModule: true
|
|
577
|
-
}))
|
|
594
|
+
})),
|
|
595
|
+
"next/router": self.__remote_component_host_shared_modules__?.["next/router"] ?? shared?.["next/router"] ?? (() => (
|
|
596
|
+
// TODO: incomplete implementation
|
|
597
|
+
Promise.resolve({
|
|
598
|
+
useRouter() {
|
|
599
|
+
return {
|
|
600
|
+
push: (routerUrl) => {
|
|
601
|
+
history.pushState({}, "", routerUrl);
|
|
602
|
+
},
|
|
603
|
+
replace: (routerUrl) => {
|
|
604
|
+
history.replaceState({}, "", routerUrl);
|
|
605
|
+
},
|
|
606
|
+
back: () => {
|
|
607
|
+
history.back();
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
},
|
|
611
|
+
__esModule: true
|
|
612
|
+
})
|
|
613
|
+
))
|
|
578
614
|
};
|
|
579
615
|
polyfill["next/navigation"] = polyfill["next/dist/client/components/navigation"];
|
|
580
616
|
polyfill["next/link"] = polyfill["next/dist/client/app-dir/link"];
|
|
581
617
|
polyfill["next/form"] = polyfill["next/dist/client/app-dir/form"];
|
|
582
|
-
polyfill["next/image"] = polyfill["next/dist/client/image-component"];
|
|
583
618
|
polyfill["next/dist/api/image"] = polyfill["next/dist/client/image-component"];
|
|
584
619
|
polyfill["next/script"] = polyfill["next/dist/client/script"];
|
|
585
620
|
return polyfill;
|
|
586
621
|
}
|
|
622
|
+
var imageImpl;
|
|
587
623
|
var init_polyfill = __esm({
|
|
588
624
|
"src/shared/client/polyfill.tsx"() {
|
|
589
625
|
"use strict";
|
|
626
|
+
imageImpl = (bundle) => function RemoteImage({ priority: _, ...props }) {
|
|
627
|
+
const newSrc = applyBundleUrlToImagePropsSrc(
|
|
628
|
+
bundle,
|
|
629
|
+
typeof props.src === "string" ? props.src : props.src.src
|
|
630
|
+
);
|
|
631
|
+
return (
|
|
632
|
+
// eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text
|
|
633
|
+
/* @__PURE__ */ jsx(
|
|
634
|
+
"img",
|
|
635
|
+
{
|
|
636
|
+
decoding: "async",
|
|
637
|
+
style: { color: "transparent" },
|
|
638
|
+
...props,
|
|
639
|
+
src: newSrc,
|
|
640
|
+
suppressHydrationWarning: true
|
|
641
|
+
}
|
|
642
|
+
)
|
|
643
|
+
);
|
|
644
|
+
};
|
|
590
645
|
}
|
|
591
646
|
});
|
|
592
647
|
|
|
@@ -629,6 +684,7 @@ async function webpackRuntime(bundle, shared, remoteShared) {
|
|
|
629
684
|
const newScript = document.createElement("script");
|
|
630
685
|
newScript.onload = () => {
|
|
631
686
|
resolve2();
|
|
687
|
+
newScript.remove();
|
|
632
688
|
};
|
|
633
689
|
newScript.onerror = () => {
|
|
634
690
|
reject(
|
|
@@ -636,6 +692,7 @@ async function webpackRuntime(bundle, shared, remoteShared) {
|
|
|
636
692
|
`Failed to load script ${script.src} for remote component`
|
|
637
693
|
)
|
|
638
694
|
);
|
|
695
|
+
newScript.remove();
|
|
639
696
|
};
|
|
640
697
|
const scriptSrc = script.getAttribute("src") || script.getAttribute("data-src");
|
|
641
698
|
if (scriptSrc) {
|
|
@@ -674,7 +731,7 @@ async function webpackRuntime(bundle, shared, remoteShared) {
|
|
|
674
731
|
await Promise.all(
|
|
675
732
|
Object.entries(resolve).map(async ([key, value]) => {
|
|
676
733
|
if (typeof value === "function") {
|
|
677
|
-
resolve[key] = await value();
|
|
734
|
+
resolve[key] = await value(remoteBundle);
|
|
678
735
|
}
|
|
679
736
|
return Promise.resolve(value);
|
|
680
737
|
})
|
|
@@ -753,6 +810,7 @@ var init_turbopack = __esm({
|
|
|
753
810
|
});
|
|
754
811
|
|
|
755
812
|
// src/html/host/index.tsx
|
|
813
|
+
import { startTransition, useLayoutEffect } from "react";
|
|
756
814
|
import { hydrateRoot } from "react-dom/client";
|
|
757
815
|
|
|
758
816
|
// src/shared/client/component-loader.ts
|
|
@@ -834,6 +892,41 @@ function createRSCStream(name, data) {
|
|
|
834
892
|
init_webpack_adapter();
|
|
835
893
|
init_const();
|
|
836
894
|
|
|
895
|
+
// src/shared/client/apply-origin.ts
|
|
896
|
+
var tagNames = [
|
|
897
|
+
"img",
|
|
898
|
+
"source",
|
|
899
|
+
"video",
|
|
900
|
+
"audio",
|
|
901
|
+
"track",
|
|
902
|
+
"iframe",
|
|
903
|
+
"embed",
|
|
904
|
+
"script",
|
|
905
|
+
"link"
|
|
906
|
+
];
|
|
907
|
+
function applyOriginToNodes(doc, url) {
|
|
908
|
+
const nodes = doc.querySelectorAll(
|
|
909
|
+
tagNames.map((type) => `${type}[src],${type}[srcset]`).join(",")
|
|
910
|
+
);
|
|
911
|
+
nodes.forEach((node) => {
|
|
912
|
+
if (node.hasAttribute("src") && /^[./]+\/?/.test(node.getAttribute("src") ?? "")) {
|
|
913
|
+
node.src = new URL(node.getAttribute("src") ?? "/", url).href;
|
|
914
|
+
}
|
|
915
|
+
if (node.hasAttribute("srcset")) {
|
|
916
|
+
const srcSet = node.getAttribute("srcset")?.split(",").map((entry) => {
|
|
917
|
+
const [urlPart, descriptor] = entry.trim().split(/\s+/);
|
|
918
|
+
if (!urlPart)
|
|
919
|
+
return entry;
|
|
920
|
+
const absoluteUrl = new URL(urlPart, url).href;
|
|
921
|
+
return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
|
|
922
|
+
}).join(", ");
|
|
923
|
+
if (srcSet) {
|
|
924
|
+
node.setAttribute("srcset", srcSet);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
|
|
837
930
|
// src/html/host/runtime/index.ts
|
|
838
931
|
async function getRuntime(type, url, bundle, shared, remoteShared) {
|
|
839
932
|
if (typeof globalThis.process === "undefined") {
|
|
@@ -856,38 +949,64 @@ import { jsx as jsx2 } from "react/jsx-runtime";
|
|
|
856
949
|
if (typeof HTMLElement !== "undefined") {
|
|
857
950
|
class RemoteComponent extends HTMLElement {
|
|
858
951
|
constructor() {
|
|
859
|
-
super();
|
|
952
|
+
super(...arguments);
|
|
860
953
|
this.__next = null;
|
|
861
954
|
this.fouc = null;
|
|
862
955
|
this.isLoading = false;
|
|
863
|
-
this.
|
|
864
|
-
this.fallbackSlot = document.createElement("slot");
|
|
865
|
-
this.shadowRoot?.appendChild(this.fallbackSlot);
|
|
866
|
-
this.name = this.getAttribute("name") || "__vercel_remote_component";
|
|
867
|
-
this.bundle = "default";
|
|
868
|
-
if (this.hasAttribute("src") || this.querySelector("div#__REMOTE_COMPONENT__") || this.hasAttribute("data-ssr")) {
|
|
869
|
-
this.load().catch((e) => {
|
|
870
|
-
throw new Error(`Failed to load remote component: ${e}`);
|
|
871
|
-
});
|
|
872
|
-
}
|
|
956
|
+
this.root = null;
|
|
873
957
|
}
|
|
874
958
|
static get observedAttributes() {
|
|
875
|
-
return ["src"];
|
|
959
|
+
return ["src", "name", "mode"];
|
|
876
960
|
}
|
|
877
961
|
// watch for src attribute changes
|
|
878
962
|
// this is required to reload the remote component when the src attribute is added later
|
|
879
963
|
// this is for rendering the custom element using React
|
|
880
964
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
881
|
-
if (name === "src" && oldValue !== newValue) {
|
|
965
|
+
if ((name === "src" || name === "name") && oldValue !== newValue) {
|
|
966
|
+
if (this.getAttribute("src")) {
|
|
967
|
+
this.load().catch((e) => {
|
|
968
|
+
console.error(e);
|
|
969
|
+
throw new Error(
|
|
970
|
+
`Failed to load remote component: ${this.bundle ?? this.name ?? this.getAttribute("src")}`
|
|
971
|
+
);
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
} else if (name === "mode" && oldValue !== newValue && this.root) {
|
|
975
|
+
const newRoot = this.attachShadow({
|
|
976
|
+
mode: newValue === "closed" ? "closed" : "open"
|
|
977
|
+
});
|
|
978
|
+
Array.from(this.root.children).forEach((child) => {
|
|
979
|
+
newRoot.appendChild(child);
|
|
980
|
+
});
|
|
981
|
+
this.root = newRoot;
|
|
882
982
|
this.load().catch((e) => {
|
|
883
983
|
throw new Error(`Failed to load remote component: ${e}`);
|
|
884
984
|
});
|
|
885
985
|
}
|
|
886
986
|
}
|
|
887
987
|
async load() {
|
|
988
|
+
await new Promise((resolve) => {
|
|
989
|
+
(typeof queueMicrotask === "function" ? queueMicrotask : requestAnimationFrame)(() => {
|
|
990
|
+
resolve(void 0);
|
|
991
|
+
});
|
|
992
|
+
});
|
|
888
993
|
if (this.isLoading) {
|
|
889
994
|
return;
|
|
890
995
|
}
|
|
996
|
+
if (!this.root) {
|
|
997
|
+
this.root = this.attachShadow({
|
|
998
|
+
mode: this.getAttribute("mode") === "closed" ? "closed" : "open"
|
|
999
|
+
});
|
|
1000
|
+
this.fallbackSlot = document.createElement("slot");
|
|
1001
|
+
this.root.appendChild(this.fallbackSlot);
|
|
1002
|
+
}
|
|
1003
|
+
this.name = this.getAttribute("name") || "__vercel_remote_component";
|
|
1004
|
+
this.bundle = "default";
|
|
1005
|
+
if (this.hasAttribute("src") || this.querySelector("div#__REMOTE_COMPONENT__") || this.hasAttribute("data-ssr")) {
|
|
1006
|
+
this.load().catch((e) => {
|
|
1007
|
+
throw new Error(`Failed to load remote component: ${e}`);
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
891
1010
|
this.isLoading = true;
|
|
892
1011
|
const src = this.getAttribute("src");
|
|
893
1012
|
const remoteComponentChild = this.querySelector("div#__REMOTE_COMPONENT__") || this.querySelector("div[data-bundle][data-route]");
|
|
@@ -918,22 +1037,29 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
918
1037
|
}
|
|
919
1038
|
html = await res.text();
|
|
920
1039
|
}
|
|
921
|
-
const
|
|
922
|
-
doc
|
|
1040
|
+
const parser = new DOMParser();
|
|
1041
|
+
const doc = parser.parseFromString(html, "text/html");
|
|
923
1042
|
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
|
|
924
1043
|
doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
|
|
925
1044
|
doc.querySelector("div#__next");
|
|
926
1045
|
const nextData = JSON.parse(
|
|
927
1046
|
(doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
|
|
928
1047
|
);
|
|
929
|
-
if (nextData && nextData.buildId === "development") {
|
|
1048
|
+
if (nextData && nextData.buildId === "development" && !this.reactRoot) {
|
|
930
1049
|
this.fouc = document.createElement("style");
|
|
931
1050
|
this.fouc.textContent = `:host { display: none; }`;
|
|
932
|
-
this.
|
|
1051
|
+
this.root.appendChild(this.fouc);
|
|
933
1052
|
}
|
|
934
1053
|
this.name = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : this.name);
|
|
935
1054
|
const rsc = doc.querySelector(`#${this.name}_rsc`);
|
|
936
1055
|
this.bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || this.bundle;
|
|
1056
|
+
if (url) {
|
|
1057
|
+
const self2 = globalThis;
|
|
1058
|
+
if (!self2.__remote_bundle_url__) {
|
|
1059
|
+
self2.__remote_bundle_url__ = {};
|
|
1060
|
+
}
|
|
1061
|
+
self2.__remote_bundle_url__[this.bundle ?? "default"] = url;
|
|
1062
|
+
}
|
|
937
1063
|
const metadata = document.createElement("script");
|
|
938
1064
|
metadata.type = "application/json";
|
|
939
1065
|
metadata.setAttribute("data-remote-component", "");
|
|
@@ -943,54 +1069,116 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
943
1069
|
route: component?.getAttribute("data-route") ?? nextData?.page ?? "/",
|
|
944
1070
|
runtime: component?.getAttribute("data-runtime") ?? nextData?.props.__REMOTE_COMPONENT__?.runtime
|
|
945
1071
|
});
|
|
946
|
-
this.
|
|
947
|
-
|
|
948
|
-
|
|
1072
|
+
if (this.previousElementSibling?.getAttribute("data-remote-component") !== null) {
|
|
1073
|
+
this.previousElementSibling?.remove();
|
|
1074
|
+
}
|
|
1075
|
+
this.parentElement?.insertBefore(metadata, this);
|
|
1076
|
+
const remoteSharedEl = doc.querySelector(
|
|
1077
|
+
`#${this.name}_shared[data-remote-components-shared]`
|
|
1078
|
+
);
|
|
1079
|
+
const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
|
|
949
1080
|
remoteSharedEl?.parentElement?.removeChild(remoteSharedEl);
|
|
950
1081
|
if (!component || !(rsc || nextData)) {
|
|
951
1082
|
throw new Error(`Failed to find component with id "${this.name}"`);
|
|
952
1083
|
}
|
|
953
1084
|
const removable = Array.from(this.childNodes);
|
|
954
1085
|
const links = doc.querySelectorAll("link[href]");
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1086
|
+
const remoteComponentSrc = this.getAttribute("src");
|
|
1087
|
+
const attachLinks = async () => {
|
|
1088
|
+
await Promise.all(
|
|
1089
|
+
Array.from(links).filter((link) => {
|
|
1090
|
+
return !component.contains(link);
|
|
1091
|
+
}).map((link) => {
|
|
1092
|
+
return new Promise((resolve, reject) => {
|
|
1093
|
+
const newLink = document.createElement("link");
|
|
1094
|
+
if (link.rel === "stylesheet") {
|
|
1095
|
+
newLink.onload = () => {
|
|
1096
|
+
resolve();
|
|
1097
|
+
};
|
|
1098
|
+
newLink.onerror = () => {
|
|
1099
|
+
reject(
|
|
1100
|
+
new Error(
|
|
1101
|
+
`Failed to load link ${link.href} for remote component`
|
|
1102
|
+
)
|
|
1103
|
+
);
|
|
1104
|
+
};
|
|
1105
|
+
} else {
|
|
961
1106
|
resolve();
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
if (attr.name === "href") {
|
|
1107
|
+
}
|
|
1108
|
+
for (const attr of link.attributes) {
|
|
1109
|
+
if (attr.name === "href") {
|
|
1110
|
+
newLink.setAttribute(
|
|
1111
|
+
attr.name,
|
|
1112
|
+
new URL(attr.value, url ?? location.origin).href
|
|
1113
|
+
);
|
|
1114
|
+
} else {
|
|
1115
|
+
newLink.setAttribute(attr.name, attr.value);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
if (remoteComponentSrc) {
|
|
975
1119
|
newLink.setAttribute(
|
|
976
|
-
|
|
977
|
-
|
|
1120
|
+
"data-remote-component-src",
|
|
1121
|
+
remoteComponentSrc
|
|
978
1122
|
);
|
|
979
|
-
} else {
|
|
980
|
-
newLink.setAttribute(attr.name, attr.value);
|
|
981
1123
|
}
|
|
1124
|
+
this.root?.appendChild(newLink);
|
|
1125
|
+
});
|
|
1126
|
+
})
|
|
1127
|
+
);
|
|
1128
|
+
const styles = doc.querySelectorAll("style");
|
|
1129
|
+
styles.forEach((style) => {
|
|
1130
|
+
if (style.parentElement?.tagName.toLowerCase() === "head") {
|
|
1131
|
+
const newStyle = document.createElement("style");
|
|
1132
|
+
newStyle.textContent = style.textContent;
|
|
1133
|
+
if (remoteComponentSrc) {
|
|
1134
|
+
newStyle.setAttribute(
|
|
1135
|
+
"data-remote-component-src",
|
|
1136
|
+
remoteComponentSrc
|
|
1137
|
+
);
|
|
982
1138
|
}
|
|
983
|
-
this.
|
|
984
|
-
}
|
|
985
|
-
})
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
}
|
|
1139
|
+
this.root?.appendChild(newStyle);
|
|
1140
|
+
}
|
|
1141
|
+
});
|
|
1142
|
+
};
|
|
1143
|
+
if (!this.reactRoot) {
|
|
1144
|
+
await attachLinks();
|
|
1145
|
+
}
|
|
1146
|
+
applyOriginToNodes(doc, url ?? new URL(location.href));
|
|
1147
|
+
if (!this.reactRoot) {
|
|
1148
|
+
Array.from(component.children).forEach((el) => {
|
|
1149
|
+
this.root?.appendChild(el);
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
990
1152
|
for (const el of removable) {
|
|
991
1153
|
el.parentElement?.removeChild(el);
|
|
992
1154
|
}
|
|
993
|
-
this.
|
|
1155
|
+
this.fallbackSlot?.remove();
|
|
1156
|
+
const applyReset = () => {
|
|
1157
|
+
if (this.getAttribute("reset") !== null && !this.root?.querySelector("link[data-remote-components-reset]")) {
|
|
1158
|
+
const allInitial = document.createElement("link");
|
|
1159
|
+
allInitial.setAttribute("data-remote-components-reset", "");
|
|
1160
|
+
const css = `:host { all: initial; }`;
|
|
1161
|
+
const allInitialHref = URL.createObjectURL(
|
|
1162
|
+
new Blob([css], { type: "text/css" })
|
|
1163
|
+
);
|
|
1164
|
+
allInitial.href = allInitialHref;
|
|
1165
|
+
allInitial.rel = "stylesheet";
|
|
1166
|
+
allInitial.onload = () => {
|
|
1167
|
+
URL.revokeObjectURL(allInitialHref);
|
|
1168
|
+
allInitial.removeAttribute("onload");
|
|
1169
|
+
};
|
|
1170
|
+
allInitial.onerror = () => {
|
|
1171
|
+
URL.revokeObjectURL(allInitialHref);
|
|
1172
|
+
allInitial.removeAttribute("onload");
|
|
1173
|
+
};
|
|
1174
|
+
this.root?.prepend(allInitial);
|
|
1175
|
+
} else if (this.getAttribute("reset") === null && this.root?.querySelector("link[data-remote-components-reset]")) {
|
|
1176
|
+
this.root.querySelector("link[data-remote-components-reset]")?.remove();
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
if (!this.reactRoot) {
|
|
1180
|
+
applyReset();
|
|
1181
|
+
}
|
|
994
1182
|
const {
|
|
995
1183
|
self,
|
|
996
1184
|
createFromReadableStream,
|
|
@@ -1018,7 +1206,26 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1018
1206
|
window.location.href
|
|
1019
1207
|
);
|
|
1020
1208
|
}
|
|
1021
|
-
await preloadScripts(
|
|
1209
|
+
await preloadScripts(
|
|
1210
|
+
Array.from(scripts),
|
|
1211
|
+
url,
|
|
1212
|
+
this.bundle ?? "default",
|
|
1213
|
+
this.name ?? "__vercel_remote_component"
|
|
1214
|
+
);
|
|
1215
|
+
const doCleanup = () => {
|
|
1216
|
+
if (this.root && remoteComponentSrc) {
|
|
1217
|
+
const selector = `[data-remote-component-src]:not([data-remote-component-src="${remoteComponentSrc}"])`;
|
|
1218
|
+
const prevCleanup = [
|
|
1219
|
+
...this.root.querySelectorAll(selector),
|
|
1220
|
+
...document.body.querySelectorAll(selector)
|
|
1221
|
+
];
|
|
1222
|
+
if (prevCleanup.length > 0) {
|
|
1223
|
+
prevCleanup.forEach((prev) => {
|
|
1224
|
+
prev.remove();
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1022
1229
|
if (rsc) {
|
|
1023
1230
|
rsc.parentElement?.removeChild(rsc);
|
|
1024
1231
|
const rscClone = document.createElement("script");
|
|
@@ -1027,36 +1234,97 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1027
1234
|
document.body.appendChild(rscClone);
|
|
1028
1235
|
let cache;
|
|
1029
1236
|
const RemoteComponentFromReadableStream = ({
|
|
1030
|
-
name
|
|
1237
|
+
name,
|
|
1238
|
+
initial
|
|
1031
1239
|
}) => {
|
|
1032
1240
|
const stream = createRSCStream(name, self[name] ?? [`0:[null]
|
|
1033
1241
|
`]);
|
|
1034
1242
|
const Component = cache ?? // cache the component to avoid reloading the RSC flight data
|
|
1035
1243
|
(cache = createFromReadableStream(stream));
|
|
1244
|
+
useLayoutEffect(() => {
|
|
1245
|
+
if (self[name]) {
|
|
1246
|
+
delete self[name];
|
|
1247
|
+
}
|
|
1248
|
+
const rscScript = document.getElementById(`${name}_rsc`);
|
|
1249
|
+
if (rscScript) {
|
|
1250
|
+
rscScript.remove();
|
|
1251
|
+
}
|
|
1252
|
+
doCleanup();
|
|
1253
|
+
applyReset();
|
|
1254
|
+
if (!initial) {
|
|
1255
|
+
attachLinks().catch((e) => {
|
|
1256
|
+
console.error(e);
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1259
|
+
this.isLoading = false;
|
|
1260
|
+
}, [initial, name]);
|
|
1036
1261
|
return Component;
|
|
1037
1262
|
};
|
|
1038
|
-
|
|
1263
|
+
if (this.reactRoot) {
|
|
1264
|
+
const root = this.reactRoot;
|
|
1265
|
+
startTransition(() => {
|
|
1266
|
+
root.render(
|
|
1267
|
+
/* @__PURE__ */ jsx2(
|
|
1268
|
+
RemoteComponentFromReadableStream,
|
|
1269
|
+
{
|
|
1270
|
+
initial: false,
|
|
1271
|
+
name: this.name ?? "__vercel_remote_component"
|
|
1272
|
+
}
|
|
1273
|
+
)
|
|
1274
|
+
);
|
|
1275
|
+
});
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
this.reactRoot = hydrateRoot(
|
|
1039
1279
|
// hydrateRoot expects a document or element, but it works for the shadow DOM too
|
|
1040
1280
|
// @ts-expect-error support for shadow DOM
|
|
1041
|
-
this.
|
|
1042
|
-
/* @__PURE__ */ jsx2(
|
|
1281
|
+
this.root,
|
|
1282
|
+
/* @__PURE__ */ jsx2(
|
|
1283
|
+
RemoteComponentFromReadableStream,
|
|
1284
|
+
{
|
|
1285
|
+
initial: true,
|
|
1286
|
+
name: this.name ?? "__vercel_remote_component"
|
|
1287
|
+
}
|
|
1288
|
+
)
|
|
1043
1289
|
);
|
|
1044
1290
|
} else if (nextData) {
|
|
1045
1291
|
const { Component, App } = nextClientPagesLoader2(
|
|
1046
|
-
this.bundle,
|
|
1292
|
+
this.bundle ?? "default",
|
|
1047
1293
|
nextData.page,
|
|
1048
|
-
this.
|
|
1294
|
+
this.root
|
|
1049
1295
|
);
|
|
1050
1296
|
if (Component) {
|
|
1051
|
-
|
|
1297
|
+
const RemoteComponentFromNext = ((NextApp, NextComponent, remoteComponent = this) => function RemoteComponentNext({ initial }) {
|
|
1298
|
+
useLayoutEffect(() => {
|
|
1299
|
+
doCleanup();
|
|
1300
|
+
if (!initial) {
|
|
1301
|
+
applyReset();
|
|
1302
|
+
attachLinks().catch((e) => {
|
|
1303
|
+
console.error(e);
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
remoteComponent.isLoading = false;
|
|
1307
|
+
}, [initial]);
|
|
1308
|
+
return NextApp ? /* @__PURE__ */ jsx2(NextApp, { Component: NextComponent, ...nextData.props }) : /* @__PURE__ */ jsx2(NextComponent, { ...nextData.props });
|
|
1309
|
+
})(App, Component, this);
|
|
1310
|
+
if (this.reactRoot) {
|
|
1311
|
+
const root = this.reactRoot;
|
|
1312
|
+
startTransition(() => {
|
|
1313
|
+
root.render(/* @__PURE__ */ jsx2(RemoteComponentFromNext, { initial: false }));
|
|
1314
|
+
doCleanup();
|
|
1315
|
+
this.isLoading = false;
|
|
1316
|
+
});
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
this.reactRoot = hydrateRoot(
|
|
1052
1320
|
// hydrateRoot expects a document or element, but it works for the shadow DOM too
|
|
1053
1321
|
// @ts-expect-error support for shadow DOM
|
|
1054
|
-
this.
|
|
1055
|
-
|
|
1322
|
+
this.root,
|
|
1323
|
+
/* @__PURE__ */ jsx2(RemoteComponentFromNext, { initial: true })
|
|
1056
1324
|
);
|
|
1057
1325
|
}
|
|
1058
1326
|
if (this.fouc) {
|
|
1059
|
-
this.
|
|
1327
|
+
this.root.removeChild(this.fouc);
|
|
1060
1328
|
}
|
|
1061
1329
|
}
|
|
1062
1330
|
this.isLoading = false;
|