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.
Files changed (74) hide show
  1. package/dist/html/host.cjs +329 -92
  2. package/dist/html/host.cjs.map +1 -1
  3. package/dist/html/host.js +332 -92
  4. package/dist/html/host.js.map +1 -1
  5. package/dist/internal/next/host/app-router-client.cjs +180 -71
  6. package/dist/internal/next/host/app-router-client.cjs.map +1 -1
  7. package/dist/internal/next/host/app-router-client.js +188 -72
  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 +20 -13
  29. package/dist/internal/shared/client/remote-component.cjs.map +1 -1
  30. package/dist/internal/shared/client/remote-component.d.ts +4 -3
  31. package/dist/internal/shared/client/remote-component.js +20 -13
  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/internal/shared/utils.cjs +31 -0
  43. package/dist/internal/shared/utils.cjs.map +1 -0
  44. package/dist/internal/shared/utils.d.ts +3 -0
  45. package/dist/internal/shared/utils.js +7 -0
  46. package/dist/internal/shared/utils.js.map +1 -0
  47. package/dist/next/config.cjs +50 -28
  48. package/dist/next/config.cjs.map +1 -1
  49. package/dist/next/config.js +50 -28
  50. package/dist/next/config.js.map +1 -1
  51. package/dist/next/host/client/index.cjs +16 -1
  52. package/dist/next/host/client/index.cjs.map +1 -1
  53. package/dist/next/host/client/index.js +16 -1
  54. package/dist/next/host/client/index.js.map +1 -1
  55. package/dist/next/host/pages-router-server.cjs +27 -13
  56. package/dist/next/host/pages-router-server.cjs.map +1 -1
  57. package/dist/next/host/pages-router-server.js +27 -13
  58. package/dist/next/host/pages-router-server.js.map +1 -1
  59. package/dist/next/middleware.cjs +5 -2
  60. package/dist/next/middleware.cjs.map +1 -1
  61. package/dist/next/middleware.d.ts +1 -0
  62. package/dist/next/middleware.js +5 -2
  63. package/dist/next/middleware.js.map +1 -1
  64. package/dist/next/remote/pages-router.cjs +3 -1
  65. package/dist/next/remote/pages-router.cjs.map +1 -1
  66. package/dist/next/remote/pages-router.d.ts +1 -0
  67. package/dist/next/remote/pages-router.js +3 -1
  68. package/dist/next/remote/pages-router.js.map +1 -1
  69. package/dist/react/index.cjs +213 -161
  70. package/dist/react/index.cjs.map +1 -1
  71. package/dist/react/index.d.ts +2 -1
  72. package/dist/react/index.js +202 -150
  73. package/dist/react/index.js.map +1 -1
  74. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { createElement } from "react";
2
3
  import {
3
4
  useState,
4
5
  useEffect,
@@ -15,11 +16,14 @@ import {
15
16
  RUNTIME_WEBPACK,
16
17
  REMOTE_COMPONENT_REGEX
17
18
  } from "#internal/shared/client/remote-component";
19
+ import { sharedPolyfills } from "#internal/shared/client/polyfill";
20
+ import { applyOriginToNodes } from "#internal/shared/client/apply-origin";
21
+ import { escapeString } from "#internal/shared/utils";
18
22
  function getRemoteComponentHtml(html) {
19
23
  if (typeof document === "undefined")
20
24
  return html;
21
- const temp = document.createElement("div");
22
- temp.innerHTML = html;
25
+ const parser = new DOMParser();
26
+ const temp = parser.parseFromString(html, "text/html");
23
27
  const ssrRemoteComponentContainer = temp.querySelector(
24
28
  'div[id^="__REMOTE_COMPONENT"]'
25
29
  );
@@ -34,6 +38,10 @@ function getRemoteComponentHtml(html) {
34
38
  }
35
39
  return "";
36
40
  }
41
+ const attrToProp = {
42
+ fetchpriority: "fetchPriority",
43
+ crossorigin: "crossOrigin"
44
+ };
37
45
  function RemoteComponent({
38
46
  src,
39
47
  isolate,
@@ -63,19 +71,18 @@ function RemoteComponent({
63
71
  const shadowRootContainerRef = useRef(null);
64
72
  const [shadowRoot, setShadowRoot] = useState(() => {
65
73
  const self = globalThis;
66
- const shadowRootKey = `__remote_components_shadowroot_${src ? new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href.replace(/[^a-z0-9]/g, "_") : ""}_${(data?.name ?? name).replace(/[^a-z0-9]/g, "_")}`;
67
- const ssrShadowRoot = typeof document !== "undefined" ? document.getElementById(
68
- `shadowroot_${src ? new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href.replace(/[^a-z0-9]/g, "_") : ""}_${(data?.name ?? name).replace(/[^a-z0-9]/g, "_")}`
74
+ const shadowRootKey = `__remote_components_shadowroot_${src ? escapeString(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${escapeString(data?.name ?? name)}`;
75
+ const ssrShadowRoot = typeof document !== "undefined" ? document.querySelector(
76
+ `[data-remote-component-id="shadowroot_${src ? escapeString(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${escapeString(data?.name ?? name)}"]`
69
77
  )?.shadowRoot ?? self[shadowRootKey] ?? null : null;
70
78
  self[shadowRootKey] = null;
71
79
  return ssrShadowRoot;
72
80
  });
73
81
  const htmlRef = useRef(
74
- typeof document !== "undefined" ? document.getElementById(
75
- `shadowroot_${src ? new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href.replace(/[^a-z0-9]/g, "_") : ""}_${(data?.name ?? name).replace(/[^a-z0-9]/g, "_")}`
82
+ typeof document !== "undefined" ? document.querySelector(
83
+ `[data-remote-component-id="shadowroot_${src ? escapeString(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${escapeString(data?.name ?? name)}"]`
76
84
  )?.shadowRoot?.innerHTML ?? document.getElementById(`__REMOTE_COMPONENT${name}`)?.innerHTML ?? document.querySelector(`div[data-bundle][data-route][id^="${name}"]`)?.innerHTML ?? document.querySelector("div[data-bundle][data-route]")?.innerHTML : null
77
85
  );
78
- const ssrHtmlRef = useRef(htmlRef.current);
79
86
  const endTemplateRef = useRef(null);
80
87
  const childrenRef = useRef(
81
88
  typeof document !== "undefined" ? (() => {
@@ -90,6 +97,7 @@ function RemoteComponent({
90
97
  return elements;
91
98
  })() : []
92
99
  );
100
+ const prevSrcRef = useRef(null);
93
101
  useLayoutEffect(() => {
94
102
  if (childrenRef.current.length > 0 && remoteComponent) {
95
103
  childrenRef.current.forEach((el) => {
@@ -98,14 +106,17 @@ function RemoteComponent({
98
106
  childrenRef.current = [];
99
107
  }
100
108
  if (isolate !== false && typeof document !== "undefined" && !shadowRoot) {
109
+ const self = globalThis;
110
+ const shadowRootKey = `__remote_components_shadowroot_${src ? escapeString(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${escapeString(data?.name ?? name)}`;
101
111
  let shadowRootElement = null;
102
- const element = document.getElementById(
103
- `shadowroot_${src ? new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href.replace(/[^a-z0-9]/g, "_") : ""}_${(data?.name ?? name).replace(/[^a-z0-9]/g, "_")}`
112
+ const element = document.querySelector(
113
+ `[data-remote-component-id="shadowroot_${src ? escapeString(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${escapeString(data?.name ?? name)}"]`
104
114
  );
105
- shadowRootElement = element?.shadowRoot ?? null;
115
+ shadowRootElement = self[shadowRootKey] ?? element?.shadowRoot ?? null;
106
116
  if (!shadowRootElement && element) {
107
117
  try {
108
118
  shadowRootElement = element.attachShadow({ mode });
119
+ self[shadowRootKey] = shadowRootElement;
109
120
  } catch {
110
121
  }
111
122
  }
@@ -116,7 +127,30 @@ function RemoteComponent({
116
127
  setShadowRoot(shadowRootElement);
117
128
  }
118
129
  }
119
- }, [name, isolate, shadowRoot, remoteComponent, mode]);
130
+ }, [name, isolate, shadowRoot, remoteComponent, mode, src, data]);
131
+ useLayoutEffect(() => {
132
+ if (shadowRoot && remoteComponent) {
133
+ const resetStyles = shadowRoot.querySelectorAll(
134
+ "style[data-remote-components-reset]"
135
+ );
136
+ if (resetStyles.length > 1) {
137
+ resetStyles.forEach((style, index) => {
138
+ if (index > 0) {
139
+ style.remove();
140
+ }
141
+ });
142
+ }
143
+ htmlRef.current = null;
144
+ let el = shadowRoot.childNodes[0] ?? null;
145
+ while (el && (!("id" in el) || el.id !== `${name}_start`)) {
146
+ const nextEl = el.nextSibling;
147
+ if (el.nodeName !== "LINK" && el.nodeName !== "STYLE") {
148
+ el.parentNode?.removeChild(el);
149
+ }
150
+ el = nextEl;
151
+ }
152
+ }
153
+ }, [shadowRoot, remoteComponent, name]);
120
154
  const url = useMemo(() => {
121
155
  if (typeof src !== "string")
122
156
  return new URL(
@@ -130,115 +164,135 @@ function RemoteComponent({
130
164
  }, [src]);
131
165
  useEffect(() => {
132
166
  let mounted = true;
133
- startTransition(async () => {
134
- try {
135
- let html = getRemoteComponentHtml(
136
- htmlRef.current ?? (endTemplateRef.current?.previousElementSibling?.tagName === "div" ? endTemplateRef.current.previousElementSibling.innerHTML : "")
137
- );
138
- if (!html && src) {
139
- const fetchInit = {
140
- method: "GET",
141
- headers: {
142
- Accept: "text/html"
143
- },
144
- credentials
167
+ if (src && src !== prevSrcRef.current) {
168
+ prevSrcRef.current = src;
169
+ startTransition(async () => {
170
+ try {
171
+ let html = getRemoteComponentHtml(
172
+ htmlRef.current ?? (endTemplateRef.current?.previousElementSibling?.tagName === "div" ? endTemplateRef.current.previousElementSibling.innerHTML : "")
173
+ );
174
+ if (!html && src) {
175
+ const fetchInit = {
176
+ method: "GET",
177
+ headers: {
178
+ Accept: "text/html"
179
+ },
180
+ credentials
181
+ };
182
+ const res = await fetch(url, fetchInit);
183
+ if (!res.ok) {
184
+ throw new Error(
185
+ `Failed to fetch remote component "${name}": ${res.status}`
186
+ );
187
+ }
188
+ const remoteHtml = await res.text();
189
+ htmlRef.current = remoteHtml;
190
+ html = getRemoteComponentHtml(remoteHtml);
191
+ }
192
+ const parser = new DOMParser();
193
+ const doc = parser.parseFromString(html, "text/html");
194
+ const component = doc.querySelector(`div[data-bundle][data-route][id^="${name}"]`) ?? // fallback to the first element with the data-bundle and data-route attributes when not using a named remote component
195
+ doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
196
+ doc.querySelector("div#__next");
197
+ const nextData = JSON.parse(
198
+ (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
199
+ );
200
+ const remoteName = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : name);
201
+ const rsc = doc.querySelector(`#${remoteName}_rsc`);
202
+ const bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default";
203
+ const metadata = {
204
+ name: remoteName,
205
+ bundle,
206
+ route: component?.getAttribute("data-route") ?? nextData?.page ?? DEFAULT_ROUTE,
207
+ runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_WEBPACK)
145
208
  };
146
- const res = await fetch(url, fetchInit);
147
- if (!res.ok) {
148
- throw new Error(
149
- `Failed to fetch remote component "${name}": ${res.status}`
150
- );
209
+ const remoteSharedEl = doc.querySelector(
210
+ `#${remoteName}_shared[data-remote-components-shared]`
211
+ );
212
+ const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
213
+ remoteSharedEl?.remove();
214
+ if (!component || !(rsc || nextData)) {
215
+ throw new Error(`Failed to find component with id "${remoteName}"`);
151
216
  }
152
- const remoteHtml = await res.text();
153
- htmlRef.current = remoteHtml;
154
- html = getRemoteComponentHtml(remoteHtml);
155
- }
156
- const doc = document.createElement("div");
157
- doc.innerHTML = html;
158
- const component = doc.querySelector(`div[data-bundle][data-route][id^="${name}"]`) ?? // fallback to the first element with the data-bundle and data-route attributes when not using a named remote component
159
- doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
160
- doc.querySelector("div#__next");
161
- const nextData = JSON.parse(
162
- (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
163
- );
164
- const remoteName = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : name);
165
- const rsc = doc.querySelector(`#${remoteName}_rsc`);
166
- const bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default";
167
- const metadata = {
168
- name: remoteName,
169
- bundle,
170
- route: component?.getAttribute("data-route") ?? nextData?.page ?? DEFAULT_ROUTE,
171
- runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_WEBPACK)
172
- };
173
- const remoteSharedEl = doc.querySelector(`#${remoteName}_shared`);
174
- const remoteShared = JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {};
175
- remoteSharedEl?.parentElement?.removeChild(remoteSharedEl);
176
- if (!component || !(rsc || nextData)) {
177
- throw new Error(`Failed to find component with id "${remoteName}"`);
178
- }
179
- const links = Array.from(
180
- doc.querySelectorAll("link[href]")
181
- ).map((link) => ({
182
- rel: link.rel,
183
- href: new URL(link.getAttribute("href") ?? link.href, url).href,
184
- as: link.getAttribute("as") || void 0
185
- }));
186
- const scripts = doc.querySelectorAll(
187
- "script[src],script[data-src]"
188
- );
189
- const inlineScripts = doc.querySelectorAll(
190
- "script:not([src]):not([data-src]):not([id*='_rsc']):not([id='__NEXT_DATA__']):not([id='__REMOTE_NEXT_DATA__'])"
191
- );
192
- const self = globalThis;
193
- const prevNextScripts = self.__next_s;
194
- const nextScripts = [];
195
- self.__next_s = nextScripts;
196
- await Promise.all(
197
- Array.from(inlineScripts).map((script) => {
198
- return new Promise((resolve) => {
199
- if (script.textContent && !script.textContent.includes("self.__next_f=") && !script.textContent.includes("self.__next_f.push")) {
200
- if (!script.getAttribute("type") || script.getAttribute("type") === "text/javascript" || script.getAttribute("type") === "application/javascript") {
201
- const newScript = document.createElement("script");
202
- const blob = new Blob([script.textContent], {
203
- type: "application/javascript"
204
- });
205
- const blobUrl = URL.createObjectURL(blob);
206
- newScript.onload = () => {
207
- resolve(void 0);
208
- URL.revokeObjectURL(blobUrl);
209
- newScript.remove();
210
- };
211
- newScript.onerror = () => {
212
- URL.revokeObjectURL(blobUrl);
213
- newScript.remove();
217
+ applyOriginToNodes(doc, url);
218
+ const links = Array.from(
219
+ doc.querySelectorAll("link[href]")
220
+ ).filter((link) => {
221
+ return !component.contains(link);
222
+ }).map((link) => ({
223
+ href: new URL(link.getAttribute("href") ?? link.href, url).href,
224
+ ...link.getAttributeNames().reduce((acc, key) => {
225
+ if (key !== "href") {
226
+ acc[attrToProp[key] ?? key] = link.getAttribute(key) ?? "";
227
+ }
228
+ return acc;
229
+ }, {})
230
+ }));
231
+ const scripts = doc.querySelectorAll(
232
+ "script[src],script[data-src]"
233
+ );
234
+ const inlineScripts = doc.querySelectorAll(
235
+ "script:not([src]):not([data-src]):not([id*='_rsc']):not([id='__NEXT_DATA__']):not([id='__REMOTE_NEXT_DATA__'])"
236
+ );
237
+ const self = globalThis;
238
+ const prevNextScripts = self.__next_s;
239
+ const nextScripts = [];
240
+ self.__next_s = nextScripts;
241
+ await Promise.all(
242
+ Array.from(inlineScripts).filter(
243
+ (script) => !(script.id.endsWith("_shared") && script.getAttribute("type") === "application/json" && typeof script.getAttribute(
244
+ "data-remote-components-shared"
245
+ ) === "string")
246
+ ).map((script) => {
247
+ return new Promise((resolve) => {
248
+ if (script.textContent && !script.textContent.includes("self.__next_f=") && !script.textContent.includes("self.__next_f.push")) {
249
+ if (!script.getAttribute("type") || script.getAttribute("type") === "text/javascript" || script.getAttribute("type") === "application/javascript") {
250
+ const newScript = document.createElement("script");
251
+ const blob = new Blob([script.textContent], {
252
+ type: "application/javascript"
253
+ });
254
+ const blobUrl = URL.createObjectURL(blob);
255
+ newScript.onload = () => {
256
+ resolve(void 0);
257
+ URL.revokeObjectURL(blobUrl);
258
+ newScript.remove();
259
+ };
260
+ newScript.onerror = () => {
261
+ URL.revokeObjectURL(blobUrl);
262
+ newScript.remove();
263
+ resolve(void 0);
264
+ };
265
+ newScript.src = blobUrl;
266
+ document.body.appendChild(newScript);
267
+ } else {
214
268
  resolve(void 0);
215
- };
216
- newScript.src = blobUrl;
217
- document.body.appendChild(newScript);
269
+ document.body.appendChild(script);
270
+ }
218
271
  } else {
219
272
  resolve(void 0);
220
- document.body.appendChild(script);
221
273
  }
222
- } else {
223
- resolve(void 0);
224
- }
225
- });
226
- })
227
- );
228
- nextScripts.forEach(([scriptSrc, props]) => {
229
- const script = document.createElement("script");
230
- if (scriptSrc) {
231
- script.src = scriptSrc;
232
- }
233
- if (typeof props.children === "string") {
234
- script.textContent = props.children;
235
- }
236
- setAttributesFromProps(script, props);
237
- document.head.appendChild(script);
238
- });
239
- self.__next_s = prevNextScripts;
240
- if (mounted) {
274
+ });
275
+ })
276
+ );
277
+ nextScripts.forEach(([scriptSrc, props]) => {
278
+ const script = document.createElement("script");
279
+ if (scriptSrc) {
280
+ script.src = scriptSrc;
281
+ }
282
+ if (typeof props.children === "string") {
283
+ script.textContent = props.children;
284
+ }
285
+ setAttributesFromProps(script, props);
286
+ document.head.appendChild(script);
287
+ });
288
+ self.__next_s = prevNextScripts;
289
+ let rscName;
241
290
  if (rsc) {
291
+ rscName = `__remote_component_rsc_${escapeString(url.href)}_${escapeString(remoteName)}`;
292
+ rsc.textContent = rsc.textContent?.replace(
293
+ new RegExp(`self\\["${remoteName}"\\]`, "g"),
294
+ `self["${rscName}"]`
295
+ ) ?? "";
242
296
  document.body.appendChild(rsc);
243
297
  }
244
298
  const newData = {
@@ -248,9 +302,11 @@ function RemoteComponent({
248
302
  url: url.href,
249
303
  data: rsc ? (rsc.textContent || "").split("\n").filter(Boolean) : []
250
304
  };
305
+ const userShared = await shared;
251
306
  const result = await loadRemoteComponent({
252
307
  url: new URL(url, location.origin),
253
308
  name: remoteName,
309
+ rscName,
254
310
  bundle,
255
311
  route: metadata.route,
256
312
  runtime: metadata.runtime,
@@ -274,25 +330,29 @@ function RemoteComponent({
274
330
  ).href
275
331
  };
276
332
  }),
277
- shared,
333
+ shared: {
334
+ ...sharedPolyfills(userShared),
335
+ ...userShared
336
+ },
278
337
  remoteShared,
279
338
  container: shadowRoot
280
339
  });
340
+ if (rsc) {
341
+ rsc.remove();
342
+ }
343
+ setData(newData);
344
+ if (result.error) {
345
+ setRemoteComponent(result.error);
346
+ } else {
347
+ setRemoteComponent(result.component);
348
+ }
349
+ } catch (error) {
281
350
  if (mounted) {
282
- setData(newData);
283
- if (result.error) {
284
- setRemoteComponent(result.error);
285
- } else {
286
- setRemoteComponent(result.component);
287
- }
351
+ setRemoteComponent(error);
288
352
  }
289
353
  }
290
- } catch (error) {
291
- if (mounted) {
292
- setRemoteComponent(error);
293
- }
294
- }
295
- });
354
+ });
355
+ }
296
356
  return () => {
297
357
  mounted = false;
298
358
  };
@@ -306,16 +366,17 @@ function RemoteComponent({
306
366
  route: data?.route || DEFAULT_ROUTE,
307
367
  runtime: data?.runtime || RUNTIME_WEBPACK
308
368
  }) });
309
- const linksToRender = data?.links?.map((link) => /* @__PURE__ */ jsx(
369
+ const resetStyle = reset ? /* @__PURE__ */ jsx("style", { "data-remote-components-reset": "", children: `:host { all: initial; }` }) : null;
370
+ const linksToRender = data?.links?.map((link) => /* @__PURE__ */ createElement(
310
371
  "link",
311
372
  {
312
- as: link.as,
373
+ ...link,
313
374
  href: new URL(link.href, url).href,
314
- rel: link.rel
315
- },
316
- `${link.href}_${link.rel}`
375
+ key: JSON.stringify(link)
376
+ }
317
377
  )) || null;
318
378
  const componentToRender = /* @__PURE__ */ jsxs(Fragment, { children: [
379
+ resetStyle,
319
380
  linksToRender,
320
381
  remoteComponent ?? children
321
382
  ] });
@@ -324,20 +385,13 @@ function RemoteComponent({
324
385
  if (shadowRemoteComponentHtml) {
325
386
  shadowRemoteComponentHtml.remove();
326
387
  }
327
- if (shadowRoot && remoteComponent && htmlRef.current) {
328
- if (ssrHtmlRef.current) {
329
- const content = shadowRoot.querySelectorAll(":not(link,style)");
330
- content.forEach((node) => node.remove());
331
- ssrHtmlRef.current = null;
332
- }
333
- htmlRef.current = null;
334
- }
335
388
  return /* @__PURE__ */ jsxs(Fragment, { children: [
336
389
  metadataJson,
337
390
  /* @__PURE__ */ jsxs(
338
391
  "div",
339
392
  {
340
- id: `shadowroot_${src ? new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href.replace(/[^a-z0-9]/g, "_") : ""}_${(data?.name ?? name).replace(/[^a-z0-9]/g, "_")}`,
393
+ "data-remote-component-id": `shadowroot_${src ? escapeString(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${escapeString(data?.name ?? name)}`,
394
+ id: `shadowroot_${data?.name ?? name}`,
341
395
  ref: shadowRootContainerRef,
342
396
  children: [
343
397
  typeof document === "undefined" ? (
@@ -352,28 +406,25 @@ function RemoteComponent({
352
406
  src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="
353
407
  onload="(function(el){
354
408
  const root = el.getRootNode();
355
- globalThis.__remote_components_shadowroot_${src ? new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href.replace(/[^a-z0-9]/g, "_") : ""}_${(data?.name ?? name).replace(/[^a-z0-9]/g, "_")} = root;
409
+ globalThis.__remote_components_shadowroot_${src ? escapeString(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${escapeString(data?.name ?? name)} = root;
356
410
  el.parentElement.remove();
357
411
  })(this)"
358
412
  />`
359
413
  }
360
414
  }
361
415
  ) : null,
362
- reset ? /* @__PURE__ */ jsx(
363
- "style",
364
- {
365
- "data-remote-components-reset": true,
366
- children: `:host { all: initial; }`
367
- }
368
- ) : null,
416
+ resetStyle,
369
417
  linksToRender,
370
418
  children
371
419
  ] })
372
420
  ) : null,
373
421
  shadowRoot && remoteComponent ? createPortal(
374
422
  /* @__PURE__ */ jsxs(Fragment, { children: [
423
+ /* @__PURE__ */ jsx("template", { id: `${name}_start` }),
424
+ resetStyle,
375
425
  linksToRender,
376
- remoteComponent
426
+ remoteComponent,
427
+ /* @__PURE__ */ jsx("template", { id: `${name}_end`, ref: endTemplateRef })
377
428
  ] }),
378
429
  shadowRoot
379
430
  ) : null
@@ -382,6 +433,7 @@ function RemoteComponent({
382
433
  )
383
434
  ] });
384
435
  }
436
+ htmlRef.current = null;
385
437
  return /* @__PURE__ */ jsxs(Fragment, { children: [
386
438
  /* @__PURE__ */ jsx("template", { id: `${name}_start` }),
387
439
  metadataJson,