remote-components 0.0.23 → 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.
Files changed (69) hide show
  1. package/dist/html/host.cjs +297 -82
  2. package/dist/html/host.cjs.map +1 -1
  3. package/dist/html/host.js +300 -82
  4. package/dist/html/host.js.map +1 -1
  5. package/dist/internal/next/host/app-router-client.cjs +176 -70
  6. package/dist/internal/next/host/app-router-client.cjs.map +1 -1
  7. package/dist/internal/next/host/app-router-client.js +184 -71
  8. package/dist/internal/next/host/app-router-client.js.map +1 -1
  9. package/dist/internal/next/host/app-router-compat.cjs +114 -0
  10. package/dist/internal/next/host/app-router-compat.cjs.map +1 -0
  11. package/dist/internal/next/host/app-router-compat.d.ts +31 -0
  12. package/dist/internal/next/host/app-router-compat.js +79 -0
  13. package/dist/internal/next/host/app-router-compat.js.map +1 -0
  14. package/dist/internal/next/remote/render-client.cjs +10 -2
  15. package/dist/internal/next/remote/render-client.cjs.map +1 -1
  16. package/dist/internal/next/remote/render-client.js +10 -2
  17. package/dist/internal/next/remote/render-client.js.map +1 -1
  18. package/dist/internal/shared/client/apply-origin.cjs +61 -0
  19. package/dist/internal/shared/client/apply-origin.cjs.map +1 -0
  20. package/dist/internal/shared/client/apply-origin.d.ts +3 -0
  21. package/dist/internal/shared/client/apply-origin.js +37 -0
  22. package/dist/internal/shared/client/apply-origin.js.map +1 -0
  23. package/dist/internal/shared/client/polyfill.cjs +149 -0
  24. package/dist/internal/shared/client/polyfill.cjs.map +1 -0
  25. package/dist/internal/shared/client/polyfill.d.ts +6 -0
  26. package/dist/internal/shared/client/polyfill.js +124 -0
  27. package/dist/internal/shared/client/polyfill.js.map +1 -0
  28. package/dist/internal/shared/client/remote-component.cjs +3 -3
  29. package/dist/internal/shared/client/remote-component.cjs.map +1 -1
  30. package/dist/internal/shared/client/remote-component.d.ts +1 -1
  31. package/dist/internal/shared/client/remote-component.js +3 -3
  32. package/dist/internal/shared/client/remote-component.js.map +1 -1
  33. package/dist/internal/shared/ssr/dom-flight.cjs +40 -0
  34. package/dist/internal/shared/ssr/dom-flight.cjs.map +1 -1
  35. package/dist/internal/shared/ssr/dom-flight.js +40 -0
  36. package/dist/internal/shared/ssr/dom-flight.js.map +1 -1
  37. package/dist/internal/shared/ssr/fetch-remote-component.cjs +1 -1
  38. package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
  39. package/dist/internal/shared/ssr/fetch-remote-component.d.ts +6 -0
  40. package/dist/internal/shared/ssr/fetch-remote-component.js +1 -1
  41. package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
  42. package/dist/next/config.cjs +50 -28
  43. package/dist/next/config.cjs.map +1 -1
  44. package/dist/next/config.js +50 -28
  45. package/dist/next/config.js.map +1 -1
  46. package/dist/next/host/client/index.cjs +16 -1
  47. package/dist/next/host/client/index.cjs.map +1 -1
  48. package/dist/next/host/client/index.js +16 -1
  49. package/dist/next/host/client/index.js.map +1 -1
  50. package/dist/next/host/pages-router-server.cjs +27 -13
  51. package/dist/next/host/pages-router-server.cjs.map +1 -1
  52. package/dist/next/host/pages-router-server.js +27 -13
  53. package/dist/next/host/pages-router-server.js.map +1 -1
  54. package/dist/next/middleware.cjs +5 -2
  55. package/dist/next/middleware.cjs.map +1 -1
  56. package/dist/next/middleware.d.ts +1 -0
  57. package/dist/next/middleware.js +5 -2
  58. package/dist/next/middleware.js.map +1 -1
  59. package/dist/next/remote/pages-router.cjs +3 -1
  60. package/dist/next/remote/pages-router.cjs.map +1 -1
  61. package/dist/next/remote/pages-router.d.ts +1 -0
  62. package/dist/next/remote/pages-router.js +3 -1
  63. package/dist/next/remote/pages-router.js.map +1 -1
  64. package/dist/react/index.cjs +203 -159
  65. package/dist/react/index.cjs.map +1 -1
  66. package/dist/react/index.d.ts +1 -1
  67. package/dist/react/index.js +192 -148
  68. package/dist/react/index.js.map +1 -1
  69. package/package.json +1 -1
@@ -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: (props) => (
581
- // eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text
582
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
583
- "img",
584
- {
585
- ...props,
586
- src: props.src,
587
- suppressHydrationWarning: true
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
  })
@@ -863,6 +917,41 @@ function createRSCStream(name, data) {
863
917
  init_webpack_adapter();
864
918
  init_const();
865
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
+
866
955
  // src/html/host/runtime/index.ts
867
956
  async function getRuntime(type, url, bundle, shared, remoteShared) {
868
957
  if (typeof globalThis.process === "undefined") {
@@ -885,44 +974,64 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
885
974
  if (typeof HTMLElement !== "undefined") {
886
975
  class RemoteComponent extends HTMLElement {
887
976
  constructor() {
888
- super();
977
+ super(...arguments);
889
978
  this.__next = null;
890
979
  this.fouc = null;
891
980
  this.isLoading = false;
892
981
  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
982
  }
906
983
  static get observedAttributes() {
907
- return ["src", "name"];
984
+ return ["src", "name", "mode"];
908
985
  }
909
986
  // watch for src attribute changes
910
987
  // this is required to reload the remote component when the src attribute is added later
911
988
  // this is for rendering the custom element using React
912
989
  attributeChangedCallback(name, oldValue, newValue) {
913
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;
914
1007
  this.load().catch((e) => {
915
- console.error(e);
916
- throw new Error(
917
- `Failed to load remote component: ${this.bundle ?? this.name ?? this.getAttribute("src")}`
918
- );
1008
+ throw new Error(`Failed to load remote component: ${e}`);
919
1009
  });
920
1010
  }
921
1011
  }
922
1012
  async load() {
1013
+ await new Promise((resolve) => {
1014
+ (typeof queueMicrotask === "function" ? queueMicrotask : requestAnimationFrame)(() => {
1015
+ resolve(void 0);
1016
+ });
1017
+ });
923
1018
  if (this.isLoading) {
924
1019
  return;
925
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
+ }
926
1035
  this.isLoading = true;
927
1036
  const src = this.getAttribute("src");
928
1037
  const remoteComponentChild = this.querySelector("div#__REMOTE_COMPONENT__") || this.querySelector("div[data-bundle][data-route]");
@@ -953,8 +1062,8 @@ if (typeof HTMLElement !== "undefined") {
953
1062
  }
954
1063
  html = await res.text();
955
1064
  }
956
- const doc = document.createElement("div");
957
- doc.innerHTML = html;
1065
+ const parser = new DOMParser();
1066
+ const doc = parser.parseFromString(html, "text/html");
958
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
959
1068
  doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
960
1069
  doc.querySelector("div#__next");
@@ -964,11 +1073,18 @@ if (typeof HTMLElement !== "undefined") {
964
1073
  if (nextData && nextData.buildId === "development" && !this.reactRoot) {
965
1074
  this.fouc = document.createElement("style");
966
1075
  this.fouc.textContent = `:host { display: none; }`;
967
- this.root?.appendChild(this.fouc);
1076
+ this.root.appendChild(this.fouc);
968
1077
  }
969
1078
  this.name = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : this.name);
970
1079
  const rsc = doc.querySelector(`#${this.name}_rsc`);
971
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
+ }
972
1088
  const metadata = document.createElement("script");
973
1089
  metadata.type = "application/json";
974
1090
  metadata.setAttribute("data-remote-component", "");
@@ -978,47 +1094,81 @@ if (typeof HTMLElement !== "undefined") {
978
1094
  route: component?.getAttribute("data-route") ?? nextData?.page ?? "/",
979
1095
  runtime: component?.getAttribute("data-runtime") ?? nextData?.props.__REMOTE_COMPONENT__?.runtime
980
1096
  });
981
- this.parentNode?.insertBefore(metadata, this);
982
- const remoteSharedEl = doc.querySelector(`#${this.name}_shared`);
983
- const remoteShared = JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {};
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 ?? "{}") ?? {});
984
1105
  remoteSharedEl?.parentElement?.removeChild(remoteSharedEl);
985
1106
  if (!component || !(rsc || nextData)) {
986
1107
  throw new Error(`Failed to find component with id "${this.name}"`);
987
1108
  }
988
1109
  const removable = Array.from(this.childNodes);
989
1110
  const links = doc.querySelectorAll("link[href]");
990
- await Promise.all(
991
- Array.from(links).map((link) => {
992
- return new Promise((resolve, reject) => {
993
- const newLink = document.createElement("link");
994
- if (link.rel === "stylesheet") {
995
- newLink.onload = () => {
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 {
996
1131
  resolve();
997
- };
998
- newLink.onerror = () => {
999
- reject(
1000
- new Error(
1001
- `Failed to load link ${link.href} for remote component`
1002
- )
1003
- );
1004
- };
1005
- } else {
1006
- resolve();
1007
- }
1008
- for (const attr of link.attributes) {
1009
- 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) {
1010
1144
  newLink.setAttribute(
1011
- attr.name,
1012
- new URL(attr.value, url ?? location.origin).href
1145
+ "data-remote-component-src",
1146
+ remoteComponentSrc
1013
1147
  );
1014
- } else {
1015
- newLink.setAttribute(attr.name, attr.value);
1016
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
+ );
1017
1163
  }
1018
- this.root?.appendChild(newLink);
1019
- });
1020
- })
1021
- );
1164
+ this.root?.appendChild(newStyle);
1165
+ }
1166
+ });
1167
+ };
1168
+ if (!this.reactRoot) {
1169
+ await attachLinks();
1170
+ }
1171
+ applyOriginToNodes(doc, url ?? new URL(location.href));
1022
1172
  if (!this.reactRoot) {
1023
1173
  Array.from(component.children).forEach((el) => {
1024
1174
  this.root?.appendChild(el);
@@ -1027,12 +1177,32 @@ if (typeof HTMLElement !== "undefined") {
1027
1177
  for (const el of removable) {
1028
1178
  el.parentElement?.removeChild(el);
1029
1179
  }
1030
- this.fallbackSlot.remove();
1031
- if (this.getAttribute("reset") !== null && !this.root?.querySelector("style[data-remote-components-reset]")) {
1032
- const allInitial = document.createElement("style");
1033
- allInitial.setAttribute("data-remote-components-reset", "");
1034
- allInitial.textContent = `:host { all: initial; }`;
1035
- this.root?.prepend(allInitial);
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();
1036
1206
  }
1037
1207
  const {
1038
1208
  self,
@@ -1067,6 +1237,20 @@ if (typeof HTMLElement !== "undefined") {
1067
1237
  this.bundle ?? "default",
1068
1238
  this.name ?? "__vercel_remote_component"
1069
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
+ };
1070
1254
  if (rsc) {
1071
1255
  rsc.parentElement?.removeChild(rsc);
1072
1256
  const rscClone = document.createElement("script");
@@ -1075,12 +1259,30 @@ if (typeof HTMLElement !== "undefined") {
1075
1259
  document.body.appendChild(rscClone);
1076
1260
  let cache;
1077
1261
  const RemoteComponentFromReadableStream = ({
1078
- name
1262
+ name,
1263
+ initial
1079
1264
  }) => {
1080
1265
  const stream = createRSCStream(name, self[name] ?? [`0:[null]
1081
1266
  `]);
1082
1267
  const Component = cache ?? // cache the component to avoid reloading the RSC flight data
1083
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]);
1084
1286
  return Component;
1085
1287
  };
1086
1288
  if (this.reactRoot) {
@@ -1090,11 +1292,11 @@ if (typeof HTMLElement !== "undefined") {
1090
1292
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1091
1293
  RemoteComponentFromReadableStream,
1092
1294
  {
1295
+ initial: false,
1093
1296
  name: this.name ?? "__vercel_remote_component"
1094
1297
  }
1095
1298
  )
1096
1299
  );
1097
- this.isLoading = false;
1098
1300
  });
1099
1301
  return;
1100
1302
  }
@@ -1105,6 +1307,7 @@ if (typeof HTMLElement !== "undefined") {
1105
1307
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1106
1308
  RemoteComponentFromReadableStream,
1107
1309
  {
1310
+ initial: true,
1108
1311
  name: this.name ?? "__vercel_remote_component"
1109
1312
  }
1110
1313
  )
@@ -1116,12 +1319,24 @@ if (typeof HTMLElement !== "undefined") {
1116
1319
  this.root
1117
1320
  );
1118
1321
  if (Component) {
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);
1119
1335
  if (this.reactRoot) {
1120
1336
  const root = this.reactRoot;
1121
1337
  (0, import_react.startTransition)(() => {
1122
- root.render(
1123
- App ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(App, { Component, ...nextData.props }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Component, { ...nextData.props })
1124
- );
1338
+ root.render(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RemoteComponentFromNext, { initial: false }));
1339
+ doCleanup();
1125
1340
  this.isLoading = false;
1126
1341
  });
1127
1342
  return;
@@ -1130,11 +1345,11 @@ if (typeof HTMLElement !== "undefined") {
1130
1345
  // hydrateRoot expects a document or element, but it works for the shadow DOM too
1131
1346
  // @ts-expect-error support for shadow DOM
1132
1347
  this.root,
1133
- App ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(App, { Component, ...nextData.props }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Component, { ...nextData.props })
1348
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RemoteComponentFromNext, { initial: true })
1134
1349
  );
1135
1350
  }
1136
1351
  if (this.fouc) {
1137
- this.root?.removeChild(this.fouc);
1352
+ this.root.removeChild(this.fouc);
1138
1353
  }
1139
1354
  }
1140
1355
  this.isLoading = false;