remote-components 0.0.23 → 0.0.25
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 +329 -92
- package/dist/html/host.cjs.map +1 -1
- package/dist/html/host.js +332 -92
- package/dist/html/host.js.map +1 -1
- package/dist/internal/next/host/app-router-client.cjs +180 -71
- package/dist/internal/next/host/app-router-client.cjs.map +1 -1
- package/dist/internal/next/host/app-router-client.js +188 -72
- 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 +20 -13
- package/dist/internal/shared/client/remote-component.cjs.map +1 -1
- package/dist/internal/shared/client/remote-component.d.ts +4 -3
- package/dist/internal/shared/client/remote-component.js +20 -13
- package/dist/internal/shared/client/remote-component.js.map +1 -1
- package/dist/internal/shared/ssr/dom-flight.cjs +40 -0
- package/dist/internal/shared/ssr/dom-flight.cjs.map +1 -1
- package/dist/internal/shared/ssr/dom-flight.js +40 -0
- package/dist/internal/shared/ssr/dom-flight.js.map +1 -1
- package/dist/internal/shared/ssr/fetch-remote-component.cjs +1 -1
- 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 +1 -1
- package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
- package/dist/internal/shared/utils.cjs +31 -0
- package/dist/internal/shared/utils.cjs.map +1 -0
- package/dist/internal/shared/utils.d.ts +3 -0
- package/dist/internal/shared/utils.js +7 -0
- package/dist/internal/shared/utils.js.map +1 -0
- 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/client/index.cjs +16 -1
- package/dist/next/host/client/index.cjs.map +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 +27 -13
- package/dist/next/host/pages-router-server.cjs.map +1 -1
- package/dist/next/host/pages-router-server.js +27 -13
- 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 +213 -161
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +202 -150
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
package/dist/html/host.cjs
CHANGED
|
@@ -179,14 +179,25 @@ var init_next_client_pages_loader = __esm({
|
|
|
179
179
|
}
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
+
// src/shared/utils/index.ts
|
|
183
|
+
function escapeString(str) {
|
|
184
|
+
return str.replace(/[^a-z0-9]/g, "_");
|
|
185
|
+
}
|
|
186
|
+
var init_utils = __esm({
|
|
187
|
+
"src/shared/utils/index.ts"() {
|
|
188
|
+
"use strict";
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
182
192
|
// src/shared/client/const.ts
|
|
183
193
|
function getBundleKey(bundle) {
|
|
184
|
-
return bundle
|
|
194
|
+
return escapeString(bundle);
|
|
185
195
|
}
|
|
186
196
|
var RUNTIME_WEBPACK, RUNTIME_TURBOPACK, REMOTE_COMPONENT_REGEX;
|
|
187
197
|
var init_const = __esm({
|
|
188
198
|
"src/shared/client/const.ts"() {
|
|
189
199
|
"use strict";
|
|
200
|
+
init_utils();
|
|
190
201
|
RUNTIME_WEBPACK = "webpack";
|
|
191
202
|
RUNTIME_TURBOPACK = "turbopack";
|
|
192
203
|
REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
|
|
@@ -395,7 +406,7 @@ function initializeSharedModules(bundle, shared = {}, remoteShared = {}) {
|
|
|
395
406
|
Object.entries(remoteShared).map(async ([id, module2]) => {
|
|
396
407
|
if (self.__remote_shared_modules__?.[bundle]) {
|
|
397
408
|
if (shared[module2]) {
|
|
398
|
-
self.__remote_shared_modules__[bundle][id.replace("[app-ssr]", "[app-client]")] = await shared[module2]();
|
|
409
|
+
self.__remote_shared_modules__[bundle][id.replace("[app-ssr]", "[app-client]")] = await shared[module2](bundle);
|
|
399
410
|
} else {
|
|
400
411
|
console.error(`Shared module "${module2}" not found for "${bundle}".`);
|
|
401
412
|
}
|
|
@@ -408,7 +419,7 @@ function getSharedModule(bundle, id) {
|
|
|
408
419
|
for (const [key, value] of Object.entries(
|
|
409
420
|
self.__remote_shared_modules__?.[bundle] ?? {}
|
|
410
421
|
)) {
|
|
411
|
-
if (typeof id === "string" && id.includes(key) || id === key) {
|
|
422
|
+
if (typeof value !== "undefined" && (typeof id === "string" && id.includes(key) || id === key)) {
|
|
412
423
|
return value;
|
|
413
424
|
}
|
|
414
425
|
}
|
|
@@ -541,6 +552,24 @@ var init_webpack_adapter = __esm({
|
|
|
541
552
|
});
|
|
542
553
|
|
|
543
554
|
// src/shared/client/polyfill.tsx
|
|
555
|
+
function applyBundleUrlToSrc(bundle, src) {
|
|
556
|
+
const self = globalThis;
|
|
557
|
+
if (self.__remote_bundle_url__?.[bundle]?.origin === location.origin) {
|
|
558
|
+
return src;
|
|
559
|
+
}
|
|
560
|
+
const { assetPrefix, path } = /^(?<assetPrefix>.*?)\/_next\/(?<path>.*)/.exec(src)?.groups ?? {};
|
|
561
|
+
if (!path) {
|
|
562
|
+
return new URL(src, self.__remote_bundle_url__?.[bundle]?.origin).href;
|
|
563
|
+
}
|
|
564
|
+
return `${self.__remote_bundle_url__?.[bundle]?.origin ?? ""}${assetPrefix}/_next/${path}`;
|
|
565
|
+
}
|
|
566
|
+
function applyBundleUrlToImagePropsSrc(bundle, src) {
|
|
567
|
+
if (typeof src === "string") {
|
|
568
|
+
return applyBundleUrlToSrc(bundle, src);
|
|
569
|
+
}
|
|
570
|
+
const propSrc = src;
|
|
571
|
+
return applyBundleUrlToSrc(bundle, propSrc.src);
|
|
572
|
+
}
|
|
544
573
|
function sharedPolyfills(shared) {
|
|
545
574
|
const self = globalThis;
|
|
546
575
|
const polyfill = {
|
|
@@ -576,18 +605,17 @@ function sharedPolyfills(shared) {
|
|
|
576
605
|
},
|
|
577
606
|
__esModule: true
|
|
578
607
|
})),
|
|
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
|
-
),
|
|
608
|
+
"next/dist/client/image-component": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
|
|
609
|
+
Image: imageImpl(bundle),
|
|
610
|
+
__esModule: true
|
|
611
|
+
})),
|
|
612
|
+
"next/image": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
|
|
613
|
+
default: imageImpl(bundle),
|
|
614
|
+
getImageProps: (_imgProps) => {
|
|
615
|
+
throw new Error(
|
|
616
|
+
"Next.js getImageProps() is not implemented in remote components"
|
|
617
|
+
);
|
|
618
|
+
},
|
|
591
619
|
__esModule: true
|
|
592
620
|
})),
|
|
593
621
|
"next/dist/client/script": self.__remote_component_host_shared_modules__?.["next/script"] ?? shared?.["next/script"] ?? (() => Promise.resolve({
|
|
@@ -595,21 +623,56 @@ function sharedPolyfills(shared) {
|
|
|
595
623
|
// do not throw an error for now
|
|
596
624
|
default: () => null,
|
|
597
625
|
__esModule: true
|
|
598
|
-
}))
|
|
626
|
+
})),
|
|
627
|
+
"next/router": self.__remote_component_host_shared_modules__?.["next/router"] ?? shared?.["next/router"] ?? (() => (
|
|
628
|
+
// TODO: incomplete implementation
|
|
629
|
+
Promise.resolve({
|
|
630
|
+
useRouter() {
|
|
631
|
+
return {
|
|
632
|
+
push: (routerUrl) => {
|
|
633
|
+
history.pushState({}, "", routerUrl);
|
|
634
|
+
},
|
|
635
|
+
replace: (routerUrl) => {
|
|
636
|
+
history.replaceState({}, "", routerUrl);
|
|
637
|
+
},
|
|
638
|
+
back: () => {
|
|
639
|
+
history.back();
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
},
|
|
643
|
+
__esModule: true
|
|
644
|
+
})
|
|
645
|
+
))
|
|
599
646
|
};
|
|
600
647
|
polyfill["next/navigation"] = polyfill["next/dist/client/components/navigation"];
|
|
601
648
|
polyfill["next/link"] = polyfill["next/dist/client/app-dir/link"];
|
|
602
649
|
polyfill["next/form"] = polyfill["next/dist/client/app-dir/form"];
|
|
603
|
-
polyfill["next/image"] = polyfill["next/dist/client/image-component"];
|
|
604
650
|
polyfill["next/dist/api/image"] = polyfill["next/dist/client/image-component"];
|
|
605
651
|
polyfill["next/script"] = polyfill["next/dist/client/script"];
|
|
606
652
|
return polyfill;
|
|
607
653
|
}
|
|
608
|
-
var import_jsx_runtime;
|
|
654
|
+
var import_jsx_runtime, imageImpl;
|
|
609
655
|
var init_polyfill = __esm({
|
|
610
656
|
"src/shared/client/polyfill.tsx"() {
|
|
611
657
|
"use strict";
|
|
658
|
+
// eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text
|
|
612
659
|
import_jsx_runtime = require("react/jsx-runtime");
|
|
660
|
+
imageImpl = (bundle) => function RemoteImage({ priority: _, ...props }) {
|
|
661
|
+
const newSrc = applyBundleUrlToImagePropsSrc(
|
|
662
|
+
bundle,
|
|
663
|
+
typeof props.src === "string" ? props.src : props.src.src
|
|
664
|
+
);
|
|
665
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
666
|
+
"img",
|
|
667
|
+
{
|
|
668
|
+
decoding: "async",
|
|
669
|
+
style: { color: "transparent" },
|
|
670
|
+
...props,
|
|
671
|
+
src: newSrc,
|
|
672
|
+
suppressHydrationWarning: true
|
|
673
|
+
}
|
|
674
|
+
);
|
|
675
|
+
};
|
|
613
676
|
}
|
|
614
677
|
});
|
|
615
678
|
|
|
@@ -652,6 +715,7 @@ async function webpackRuntime(bundle, shared, remoteShared) {
|
|
|
652
715
|
const newScript = document.createElement("script");
|
|
653
716
|
newScript.onload = () => {
|
|
654
717
|
resolve2();
|
|
718
|
+
newScript.remove();
|
|
655
719
|
};
|
|
656
720
|
newScript.onerror = () => {
|
|
657
721
|
reject(
|
|
@@ -659,6 +723,7 @@ async function webpackRuntime(bundle, shared, remoteShared) {
|
|
|
659
723
|
`Failed to load script ${script.src} for remote component`
|
|
660
724
|
)
|
|
661
725
|
);
|
|
726
|
+
newScript.remove();
|
|
662
727
|
};
|
|
663
728
|
const scriptSrc = script.getAttribute("src") || script.getAttribute("data-src");
|
|
664
729
|
if (scriptSrc) {
|
|
@@ -697,7 +762,7 @@ async function webpackRuntime(bundle, shared, remoteShared) {
|
|
|
697
762
|
await Promise.all(
|
|
698
763
|
Object.entries(resolve).map(async ([key, value]) => {
|
|
699
764
|
if (typeof value === "function") {
|
|
700
|
-
resolve[key] = await value();
|
|
765
|
+
resolve[key] = await value(remoteBundle);
|
|
701
766
|
}
|
|
702
767
|
return Promise.resolve(value);
|
|
703
768
|
})
|
|
@@ -814,26 +879,27 @@ function fixPayload(payload) {
|
|
|
814
879
|
}
|
|
815
880
|
}
|
|
816
881
|
}
|
|
817
|
-
function createRSCStream(
|
|
882
|
+
function createRSCStream(rscName, data) {
|
|
818
883
|
return new import_web_streams_polyfill.ReadableStream({
|
|
819
884
|
type: "bytes",
|
|
820
885
|
start(controller) {
|
|
821
886
|
const encoder = new TextEncoder();
|
|
822
887
|
const self = globalThis;
|
|
823
|
-
if (
|
|
888
|
+
if (data.length > 0) {
|
|
824
889
|
data.forEach((chunk) => {
|
|
825
890
|
const lines = chunk.split("\n");
|
|
826
891
|
for (const line of lines) {
|
|
827
892
|
const match = /\.push\("(?<rsc>.*)"\);$/.exec(line);
|
|
828
893
|
if (match?.groups?.rsc) {
|
|
829
|
-
self[
|
|
830
|
-
self[
|
|
894
|
+
self[rscName] = self[rscName] ?? [];
|
|
895
|
+
self[rscName].push(JSON.parse(`"${match.groups.rsc}"`));
|
|
831
896
|
}
|
|
832
897
|
}
|
|
833
898
|
});
|
|
834
899
|
}
|
|
835
|
-
const allChunks = (self[
|
|
900
|
+
const allChunks = (self[rscName] ?? [`0:[null]
|
|
836
901
|
`]).join("");
|
|
902
|
+
self[rscName] = null;
|
|
837
903
|
allChunks.split("\n").forEach((chunk) => {
|
|
838
904
|
if (chunk.length > 0) {
|
|
839
905
|
const { before, id, prefix, payload } = /^(?<before>.*?)?(?<id>[0-9a-zA-Z]+):(?<prefix>[A-Z])?(?<payload>\[.*\])/.exec(
|
|
@@ -863,6 +929,44 @@ function createRSCStream(name, data) {
|
|
|
863
929
|
init_webpack_adapter();
|
|
864
930
|
init_const();
|
|
865
931
|
|
|
932
|
+
// src/html/host/index.tsx
|
|
933
|
+
init_utils();
|
|
934
|
+
|
|
935
|
+
// src/shared/client/apply-origin.ts
|
|
936
|
+
var tagNames = [
|
|
937
|
+
"img",
|
|
938
|
+
"source",
|
|
939
|
+
"video",
|
|
940
|
+
"audio",
|
|
941
|
+
"track",
|
|
942
|
+
"iframe",
|
|
943
|
+
"embed",
|
|
944
|
+
"script",
|
|
945
|
+
"link"
|
|
946
|
+
];
|
|
947
|
+
function applyOriginToNodes(doc, url) {
|
|
948
|
+
const nodes = doc.querySelectorAll(
|
|
949
|
+
tagNames.map((type) => `${type}[src],${type}[srcset]`).join(",")
|
|
950
|
+
);
|
|
951
|
+
nodes.forEach((node) => {
|
|
952
|
+
if (node.hasAttribute("src") && /^[./]+\/?/.test(node.getAttribute("src") ?? "")) {
|
|
953
|
+
node.src = new URL(node.getAttribute("src") ?? "/", url).href;
|
|
954
|
+
}
|
|
955
|
+
if (node.hasAttribute("srcset")) {
|
|
956
|
+
const srcSet = node.getAttribute("srcset")?.split(",").map((entry) => {
|
|
957
|
+
const [urlPart, descriptor] = entry.trim().split(/\s+/);
|
|
958
|
+
if (!urlPart)
|
|
959
|
+
return entry;
|
|
960
|
+
const absoluteUrl = new URL(urlPart, url).href;
|
|
961
|
+
return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
|
|
962
|
+
}).join(", ");
|
|
963
|
+
if (srcSet) {
|
|
964
|
+
node.setAttribute("srcset", srcSet);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
|
|
866
970
|
// src/html/host/runtime/index.ts
|
|
867
971
|
async function getRuntime(type, url, bundle, shared, remoteShared) {
|
|
868
972
|
if (typeof globalThis.process === "undefined") {
|
|
@@ -885,44 +989,64 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
885
989
|
if (typeof HTMLElement !== "undefined") {
|
|
886
990
|
class RemoteComponent extends HTMLElement {
|
|
887
991
|
constructor() {
|
|
888
|
-
super();
|
|
992
|
+
super(...arguments);
|
|
889
993
|
this.__next = null;
|
|
890
994
|
this.fouc = null;
|
|
891
995
|
this.isLoading = false;
|
|
892
996
|
this.root = null;
|
|
893
|
-
this.root = this.attachShadow({
|
|
894
|
-
mode: this.getAttribute("mode") === "closed" ? "closed" : "open"
|
|
895
|
-
});
|
|
896
|
-
this.fallbackSlot = document.createElement("slot");
|
|
897
|
-
this.root.appendChild(this.fallbackSlot);
|
|
898
|
-
this.name = this.getAttribute("name") || "__vercel_remote_component";
|
|
899
|
-
this.bundle = "default";
|
|
900
|
-
if (this.hasAttribute("src") || this.querySelector("div#__REMOTE_COMPONENT__") || this.hasAttribute("data-ssr")) {
|
|
901
|
-
this.load().catch((e) => {
|
|
902
|
-
throw new Error(`Failed to load remote component: ${e}`);
|
|
903
|
-
});
|
|
904
|
-
}
|
|
905
997
|
}
|
|
906
998
|
static get observedAttributes() {
|
|
907
|
-
return ["src", "name"];
|
|
999
|
+
return ["src", "name", "mode"];
|
|
908
1000
|
}
|
|
909
1001
|
// watch for src attribute changes
|
|
910
1002
|
// this is required to reload the remote component when the src attribute is added later
|
|
911
1003
|
// this is for rendering the custom element using React
|
|
912
1004
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
913
1005
|
if ((name === "src" || name === "name") && oldValue !== newValue) {
|
|
1006
|
+
if (this.getAttribute("src")) {
|
|
1007
|
+
this.load().catch((e) => {
|
|
1008
|
+
console.error(e);
|
|
1009
|
+
throw new Error(
|
|
1010
|
+
`Failed to load remote component: ${this.bundle ?? this.name ?? this.getAttribute("src")}`
|
|
1011
|
+
);
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
} else if (name === "mode" && oldValue !== newValue && this.root) {
|
|
1015
|
+
const newRoot = this.attachShadow({
|
|
1016
|
+
mode: newValue === "closed" ? "closed" : "open"
|
|
1017
|
+
});
|
|
1018
|
+
Array.from(this.root.children).forEach((child) => {
|
|
1019
|
+
newRoot.appendChild(child);
|
|
1020
|
+
});
|
|
1021
|
+
this.root = newRoot;
|
|
914
1022
|
this.load().catch((e) => {
|
|
915
|
-
|
|
916
|
-
throw new Error(
|
|
917
|
-
`Failed to load remote component: ${this.bundle ?? this.name ?? this.getAttribute("src")}`
|
|
918
|
-
);
|
|
1023
|
+
throw new Error(`Failed to load remote component: ${e}`);
|
|
919
1024
|
});
|
|
920
1025
|
}
|
|
921
1026
|
}
|
|
922
1027
|
async load() {
|
|
1028
|
+
await new Promise((resolve) => {
|
|
1029
|
+
(typeof queueMicrotask === "function" ? queueMicrotask : requestAnimationFrame)(() => {
|
|
1030
|
+
resolve(void 0);
|
|
1031
|
+
});
|
|
1032
|
+
});
|
|
923
1033
|
if (this.isLoading) {
|
|
924
1034
|
return;
|
|
925
1035
|
}
|
|
1036
|
+
if (!this.root) {
|
|
1037
|
+
this.root = this.attachShadow({
|
|
1038
|
+
mode: this.getAttribute("mode") === "closed" ? "closed" : "open"
|
|
1039
|
+
});
|
|
1040
|
+
this.fallbackSlot = document.createElement("slot");
|
|
1041
|
+
this.root.appendChild(this.fallbackSlot);
|
|
1042
|
+
}
|
|
1043
|
+
this.name = this.getAttribute("name") || "__vercel_remote_component";
|
|
1044
|
+
this.bundle = "default";
|
|
1045
|
+
if (this.hasAttribute("src") || this.querySelector("div#__REMOTE_COMPONENT__") || this.hasAttribute("data-ssr")) {
|
|
1046
|
+
this.load().catch((e) => {
|
|
1047
|
+
throw new Error(`Failed to load remote component: ${e}`);
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
926
1050
|
this.isLoading = true;
|
|
927
1051
|
const src = this.getAttribute("src");
|
|
928
1052
|
const remoteComponentChild = this.querySelector("div#__REMOTE_COMPONENT__") || this.querySelector("div[data-bundle][data-route]");
|
|
@@ -953,8 +1077,8 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
953
1077
|
}
|
|
954
1078
|
html = await res.text();
|
|
955
1079
|
}
|
|
956
|
-
const
|
|
957
|
-
doc
|
|
1080
|
+
const parser = new DOMParser();
|
|
1081
|
+
const doc = parser.parseFromString(html, "text/html");
|
|
958
1082
|
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
|
|
959
1083
|
doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
|
|
960
1084
|
doc.querySelector("div#__next");
|
|
@@ -964,11 +1088,18 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
964
1088
|
if (nextData && nextData.buildId === "development" && !this.reactRoot) {
|
|
965
1089
|
this.fouc = document.createElement("style");
|
|
966
1090
|
this.fouc.textContent = `:host { display: none; }`;
|
|
967
|
-
this.root
|
|
1091
|
+
this.root.appendChild(this.fouc);
|
|
968
1092
|
}
|
|
969
1093
|
this.name = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : this.name);
|
|
970
1094
|
const rsc = doc.querySelector(`#${this.name}_rsc`);
|
|
971
1095
|
this.bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || this.bundle;
|
|
1096
|
+
if (url) {
|
|
1097
|
+
const self2 = globalThis;
|
|
1098
|
+
if (!self2.__remote_bundle_url__) {
|
|
1099
|
+
self2.__remote_bundle_url__ = {};
|
|
1100
|
+
}
|
|
1101
|
+
self2.__remote_bundle_url__[this.bundle ?? "default"] = url;
|
|
1102
|
+
}
|
|
972
1103
|
const metadata = document.createElement("script");
|
|
973
1104
|
metadata.type = "application/json";
|
|
974
1105
|
metadata.setAttribute("data-remote-component", "");
|
|
@@ -978,47 +1109,81 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
978
1109
|
route: component?.getAttribute("data-route") ?? nextData?.page ?? "/",
|
|
979
1110
|
runtime: component?.getAttribute("data-runtime") ?? nextData?.props.__REMOTE_COMPONENT__?.runtime
|
|
980
1111
|
});
|
|
981
|
-
this.
|
|
982
|
-
|
|
983
|
-
|
|
1112
|
+
if (this.previousElementSibling?.getAttribute("data-remote-component") !== null) {
|
|
1113
|
+
this.previousElementSibling?.remove();
|
|
1114
|
+
}
|
|
1115
|
+
this.parentElement?.insertBefore(metadata, this);
|
|
1116
|
+
const remoteSharedEl = doc.querySelector(
|
|
1117
|
+
`#${this.name}_shared[data-remote-components-shared]`
|
|
1118
|
+
);
|
|
1119
|
+
const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
|
|
984
1120
|
remoteSharedEl?.parentElement?.removeChild(remoteSharedEl);
|
|
985
1121
|
if (!component || !(rsc || nextData)) {
|
|
986
1122
|
throw new Error(`Failed to find component with id "${this.name}"`);
|
|
987
1123
|
}
|
|
988
1124
|
const removable = Array.from(this.childNodes);
|
|
989
1125
|
const links = doc.querySelectorAll("link[href]");
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1126
|
+
const remoteComponentSrc = this.getAttribute("src");
|
|
1127
|
+
const attachLinks = async () => {
|
|
1128
|
+
await Promise.all(
|
|
1129
|
+
Array.from(links).filter((link) => {
|
|
1130
|
+
return !component.contains(link);
|
|
1131
|
+
}).map((link) => {
|
|
1132
|
+
return new Promise((resolve, reject) => {
|
|
1133
|
+
const newLink = document.createElement("link");
|
|
1134
|
+
if (link.rel === "stylesheet") {
|
|
1135
|
+
newLink.onload = () => {
|
|
1136
|
+
resolve();
|
|
1137
|
+
};
|
|
1138
|
+
newLink.onerror = () => {
|
|
1139
|
+
reject(
|
|
1140
|
+
new Error(
|
|
1141
|
+
`Failed to load link ${link.href} for remote component`
|
|
1142
|
+
)
|
|
1143
|
+
);
|
|
1144
|
+
};
|
|
1145
|
+
} else {
|
|
996
1146
|
resolve();
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
if (attr.name === "href") {
|
|
1147
|
+
}
|
|
1148
|
+
for (const attr of link.attributes) {
|
|
1149
|
+
if (attr.name === "href") {
|
|
1150
|
+
newLink.setAttribute(
|
|
1151
|
+
attr.name,
|
|
1152
|
+
new URL(attr.value, url ?? location.origin).href
|
|
1153
|
+
);
|
|
1154
|
+
} else {
|
|
1155
|
+
newLink.setAttribute(attr.name, attr.value);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
if (remoteComponentSrc) {
|
|
1010
1159
|
newLink.setAttribute(
|
|
1011
|
-
|
|
1012
|
-
|
|
1160
|
+
"data-remote-component-src",
|
|
1161
|
+
remoteComponentSrc
|
|
1013
1162
|
);
|
|
1014
|
-
} else {
|
|
1015
|
-
newLink.setAttribute(attr.name, attr.value);
|
|
1016
1163
|
}
|
|
1164
|
+
this.root?.appendChild(newLink);
|
|
1165
|
+
});
|
|
1166
|
+
})
|
|
1167
|
+
);
|
|
1168
|
+
const styles = doc.querySelectorAll("style");
|
|
1169
|
+
styles.forEach((style) => {
|
|
1170
|
+
if (style.parentElement?.tagName.toLowerCase() === "head") {
|
|
1171
|
+
const newStyle = document.createElement("style");
|
|
1172
|
+
newStyle.textContent = style.textContent;
|
|
1173
|
+
if (remoteComponentSrc) {
|
|
1174
|
+
newStyle.setAttribute(
|
|
1175
|
+
"data-remote-component-src",
|
|
1176
|
+
remoteComponentSrc
|
|
1177
|
+
);
|
|
1017
1178
|
}
|
|
1018
|
-
this.root?.appendChild(
|
|
1019
|
-
}
|
|
1020
|
-
})
|
|
1021
|
-
|
|
1179
|
+
this.root?.appendChild(newStyle);
|
|
1180
|
+
}
|
|
1181
|
+
});
|
|
1182
|
+
};
|
|
1183
|
+
if (!this.reactRoot) {
|
|
1184
|
+
await attachLinks();
|
|
1185
|
+
}
|
|
1186
|
+
applyOriginToNodes(doc, url ?? new URL(location.href));
|
|
1022
1187
|
if (!this.reactRoot) {
|
|
1023
1188
|
Array.from(component.children).forEach((el) => {
|
|
1024
1189
|
this.root?.appendChild(el);
|
|
@@ -1027,12 +1192,32 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1027
1192
|
for (const el of removable) {
|
|
1028
1193
|
el.parentElement?.removeChild(el);
|
|
1029
1194
|
}
|
|
1030
|
-
this.fallbackSlot
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1195
|
+
this.fallbackSlot?.remove();
|
|
1196
|
+
const applyReset = () => {
|
|
1197
|
+
if (this.getAttribute("reset") !== null && !this.root?.querySelector("link[data-remote-components-reset]")) {
|
|
1198
|
+
const allInitial = document.createElement("link");
|
|
1199
|
+
allInitial.setAttribute("data-remote-components-reset", "");
|
|
1200
|
+
const css = `:host { all: initial; }`;
|
|
1201
|
+
const allInitialHref = URL.createObjectURL(
|
|
1202
|
+
new Blob([css], { type: "text/css" })
|
|
1203
|
+
);
|
|
1204
|
+
allInitial.href = allInitialHref;
|
|
1205
|
+
allInitial.rel = "stylesheet";
|
|
1206
|
+
allInitial.onload = () => {
|
|
1207
|
+
URL.revokeObjectURL(allInitialHref);
|
|
1208
|
+
allInitial.removeAttribute("onload");
|
|
1209
|
+
};
|
|
1210
|
+
allInitial.onerror = () => {
|
|
1211
|
+
URL.revokeObjectURL(allInitialHref);
|
|
1212
|
+
allInitial.removeAttribute("onload");
|
|
1213
|
+
};
|
|
1214
|
+
this.root?.prepend(allInitial);
|
|
1215
|
+
} else if (this.getAttribute("reset") === null && this.root?.querySelector("link[data-remote-components-reset]")) {
|
|
1216
|
+
this.root.querySelector("link[data-remote-components-reset]")?.remove();
|
|
1217
|
+
}
|
|
1218
|
+
};
|
|
1219
|
+
if (!this.reactRoot) {
|
|
1220
|
+
applyReset();
|
|
1036
1221
|
}
|
|
1037
1222
|
const {
|
|
1038
1223
|
self,
|
|
@@ -1067,20 +1252,59 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1067
1252
|
this.bundle ?? "default",
|
|
1068
1253
|
this.name ?? "__vercel_remote_component"
|
|
1069
1254
|
);
|
|
1255
|
+
const doCleanup = () => {
|
|
1256
|
+
if (this.root && remoteComponentSrc) {
|
|
1257
|
+
const selector = `[data-remote-component-src]:not([data-remote-component-src="${remoteComponentSrc}"])`;
|
|
1258
|
+
const prevCleanup = [
|
|
1259
|
+
...this.root.querySelectorAll(selector),
|
|
1260
|
+
...document.body.querySelectorAll(selector)
|
|
1261
|
+
];
|
|
1262
|
+
if (prevCleanup.length > 0) {
|
|
1263
|
+
prevCleanup.forEach((prev) => {
|
|
1264
|
+
prev.remove();
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1070
1269
|
if (rsc) {
|
|
1071
1270
|
rsc.parentElement?.removeChild(rsc);
|
|
1271
|
+
const rscName = `__remote_component_rsc_${escapeString(url.href)}_${escapeString(this.name)}`;
|
|
1072
1272
|
const rscClone = document.createElement("script");
|
|
1073
|
-
rscClone.id = `${
|
|
1074
|
-
rscClone.textContent = rsc.textContent
|
|
1273
|
+
rscClone.id = `${rscName}_rsc`;
|
|
1274
|
+
rscClone.textContent = rsc.textContent?.replace(
|
|
1275
|
+
new RegExp(`self\\["${this.name}"\\]`, "g"),
|
|
1276
|
+
`self["${rscName}"]`
|
|
1277
|
+
) ?? "";
|
|
1075
1278
|
document.body.appendChild(rscClone);
|
|
1076
1279
|
let cache;
|
|
1077
1280
|
const RemoteComponentFromReadableStream = ({
|
|
1078
|
-
name
|
|
1281
|
+
name,
|
|
1282
|
+
initial
|
|
1079
1283
|
}) => {
|
|
1080
|
-
const stream = createRSCStream(
|
|
1081
|
-
|
|
1284
|
+
const stream = createRSCStream(
|
|
1285
|
+
rscName,
|
|
1286
|
+
self[rscName] ?? [`0:[null]
|
|
1287
|
+
`]
|
|
1288
|
+
);
|
|
1082
1289
|
const Component = cache ?? // cache the component to avoid reloading the RSC flight data
|
|
1083
1290
|
(cache = createFromReadableStream(stream));
|
|
1291
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
1292
|
+
if (self[name]) {
|
|
1293
|
+
delete self[name];
|
|
1294
|
+
}
|
|
1295
|
+
const rscScript = document.getElementById(`${name}_rsc`);
|
|
1296
|
+
if (rscScript) {
|
|
1297
|
+
rscScript.remove();
|
|
1298
|
+
}
|
|
1299
|
+
doCleanup();
|
|
1300
|
+
applyReset();
|
|
1301
|
+
if (!initial) {
|
|
1302
|
+
attachLinks().catch((e) => {
|
|
1303
|
+
console.error(e);
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
this.isLoading = false;
|
|
1307
|
+
}, [initial, name]);
|
|
1084
1308
|
return Component;
|
|
1085
1309
|
};
|
|
1086
1310
|
if (this.reactRoot) {
|
|
@@ -1090,11 +1314,11 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1090
1314
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1091
1315
|
RemoteComponentFromReadableStream,
|
|
1092
1316
|
{
|
|
1317
|
+
initial: false,
|
|
1093
1318
|
name: this.name ?? "__vercel_remote_component"
|
|
1094
1319
|
}
|
|
1095
1320
|
)
|
|
1096
1321
|
);
|
|
1097
|
-
this.isLoading = false;
|
|
1098
1322
|
});
|
|
1099
1323
|
return;
|
|
1100
1324
|
}
|
|
@@ -1105,6 +1329,7 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1105
1329
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1106
1330
|
RemoteComponentFromReadableStream,
|
|
1107
1331
|
{
|
|
1332
|
+
initial: true,
|
|
1108
1333
|
name: this.name ?? "__vercel_remote_component"
|
|
1109
1334
|
}
|
|
1110
1335
|
)
|
|
@@ -1116,12 +1341,24 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1116
1341
|
this.root
|
|
1117
1342
|
);
|
|
1118
1343
|
if (Component) {
|
|
1344
|
+
const RemoteComponentFromNext = ((NextApp, NextComponent, remoteComponent = this) => function RemoteComponentNext({ initial }) {
|
|
1345
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
1346
|
+
doCleanup();
|
|
1347
|
+
if (!initial) {
|
|
1348
|
+
applyReset();
|
|
1349
|
+
attachLinks().catch((e) => {
|
|
1350
|
+
console.error(e);
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
remoteComponent.isLoading = false;
|
|
1354
|
+
}, [initial]);
|
|
1355
|
+
return NextApp ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(NextApp, { Component: NextComponent, ...nextData.props }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(NextComponent, { ...nextData.props });
|
|
1356
|
+
})(App, Component, this);
|
|
1119
1357
|
if (this.reactRoot) {
|
|
1120
1358
|
const root = this.reactRoot;
|
|
1121
1359
|
(0, import_react.startTransition)(() => {
|
|
1122
|
-
root.render(
|
|
1123
|
-
|
|
1124
|
-
);
|
|
1360
|
+
root.render(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RemoteComponentFromNext, { initial: false }));
|
|
1361
|
+
doCleanup();
|
|
1125
1362
|
this.isLoading = false;
|
|
1126
1363
|
});
|
|
1127
1364
|
return;
|
|
@@ -1130,11 +1367,11 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
1130
1367
|
// hydrateRoot expects a document or element, but it works for the shadow DOM too
|
|
1131
1368
|
// @ts-expect-error support for shadow DOM
|
|
1132
1369
|
this.root,
|
|
1133
|
-
|
|
1370
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RemoteComponentFromNext, { initial: true })
|
|
1134
1371
|
);
|
|
1135
1372
|
}
|
|
1136
1373
|
if (this.fouc) {
|
|
1137
|
-
this.root
|
|
1374
|
+
this.root.removeChild(this.fouc);
|
|
1138
1375
|
}
|
|
1139
1376
|
}
|
|
1140
1377
|
this.isLoading = false;
|