remote-components 0.0.33 → 0.0.35

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 (77) hide show
  1. package/dist/{component-loader-28ad0083.d.ts → component-loader-8951c052.d.ts} +6 -4
  2. package/dist/html/host.cjs +353 -129
  3. package/dist/html/host.cjs.map +1 -1
  4. package/dist/html/host.js +353 -129
  5. package/dist/html/host.js.map +1 -1
  6. package/dist/html/remote.cjs +199 -0
  7. package/dist/html/remote.cjs.map +1 -0
  8. package/dist/html/remote.d.ts +2 -0
  9. package/dist/html/remote.js +198 -0
  10. package/dist/html/remote.js.map +1 -0
  11. package/dist/internal/next/host/app-router-client.cjs +60 -19
  12. package/dist/internal/next/host/app-router-client.cjs.map +1 -1
  13. package/dist/internal/next/host/app-router-client.d.ts +3 -3
  14. package/dist/internal/next/host/app-router-client.js +65 -23
  15. package/dist/internal/next/host/app-router-client.js.map +1 -1
  16. package/dist/internal/next/host/app-router-compat.cjs.map +1 -1
  17. package/dist/internal/next/host/app-router-compat.d.ts +1 -1
  18. package/dist/internal/next/host/app-router-compat.js.map +1 -1
  19. package/dist/internal/next/remote/render-server.cjs +1 -1
  20. package/dist/internal/next/remote/render-server.cjs.map +1 -1
  21. package/dist/internal/next/remote/render-server.js +1 -1
  22. package/dist/internal/next/remote/render-server.js.map +1 -1
  23. package/dist/internal/shared/client/polyfill.cjs.map +1 -1
  24. package/dist/internal/shared/client/polyfill.js.map +1 -1
  25. package/dist/internal/shared/client/remote-component.cjs +237 -133
  26. package/dist/internal/shared/client/remote-component.cjs.map +1 -1
  27. package/dist/internal/shared/client/remote-component.d.ts +29 -22
  28. package/dist/internal/shared/client/remote-component.js +235 -133
  29. package/dist/internal/shared/client/remote-component.js.map +1 -1
  30. package/dist/internal/shared/error.cjs +1 -1
  31. package/dist/internal/shared/error.cjs.map +1 -1
  32. package/dist/internal/shared/error.d.ts +1 -1
  33. package/dist/internal/shared/error.js +1 -1
  34. package/dist/internal/shared/error.js.map +1 -1
  35. package/dist/internal/shared/ssr/dom-flight.cjs +24 -8
  36. package/dist/internal/shared/ssr/dom-flight.cjs.map +1 -1
  37. package/dist/internal/shared/ssr/dom-flight.d.ts +1 -1
  38. package/dist/internal/shared/ssr/dom-flight.js +24 -8
  39. package/dist/internal/shared/ssr/dom-flight.js.map +1 -1
  40. package/dist/internal/shared/ssr/fetch-remote-component.cjs +8 -4
  41. package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
  42. package/dist/internal/shared/ssr/fetch-remote-component.d.ts +2 -1
  43. package/dist/internal/shared/ssr/fetch-remote-component.js +9 -5
  44. package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
  45. package/dist/next/config.cjs +100 -86
  46. package/dist/next/config.cjs.map +1 -1
  47. package/dist/next/config.js +100 -86
  48. package/dist/next/config.js.map +1 -1
  49. package/dist/next/host/app-router-server.cjs +1 -0
  50. package/dist/next/host/app-router-server.cjs.map +1 -1
  51. package/dist/next/host/app-router-server.js +2 -1
  52. package/dist/next/host/app-router-server.js.map +1 -1
  53. package/dist/next/host/client/index.cjs +1381 -1187
  54. package/dist/next/host/client/index.cjs.map +1 -1
  55. package/dist/next/host/client/index.d.ts +1 -1
  56. package/dist/next/host/client/index.js +682 -490
  57. package/dist/next/host/client/index.js.map +1 -1
  58. package/dist/next/host/pages-router-server.cjs +4 -4
  59. package/dist/next/host/pages-router-server.cjs.map +1 -1
  60. package/dist/next/host/pages-router-server.js +4 -4
  61. package/dist/next/host/pages-router-server.js.map +1 -1
  62. package/dist/next/{middleware.cjs → proxy.cjs} +24 -14
  63. package/dist/next/proxy.cjs.map +1 -0
  64. package/dist/next/proxy.d.ts +29 -0
  65. package/dist/next/{middleware.js → proxy.js} +21 -11
  66. package/dist/next/proxy.js.map +1 -0
  67. package/dist/react/index.cjs +201 -107
  68. package/dist/react/index.cjs.map +1 -1
  69. package/dist/react/index.d.ts +2 -2
  70. package/dist/react/index.js +206 -112
  71. package/dist/react/index.js.map +1 -1
  72. package/dist/{types-7c207455.d.ts → types-4e7dea94.d.ts} +2 -1
  73. package/dist/{types-e4a3fa37.d.ts → types-cbf6c34f.d.ts} +2 -2
  74. package/package.json +22 -9
  75. package/dist/next/middleware.cjs.map +0 -1
  76. package/dist/next/middleware.d.ts +0 -29
  77. package/dist/next/middleware.js.map +0 -1
@@ -5,54 +5,272 @@ import * as Image from "next/image";
5
5
 
6
6
  // src/react/index.tsx
7
7
  import {
8
- useState,
8
+ startTransition,
9
9
  useEffect,
10
10
  useLayoutEffect,
11
- useRef,
12
11
  useMemo,
13
- startTransition
12
+ useRef,
13
+ useState
14
14
  } from "react";
15
15
  import { createPortal } from "react-dom";
16
16
 
17
- // src/shared/client/component-loader.ts
18
- import * as React from "react";
19
- import * as ReactDOM from "react-dom";
20
- import * as ReactDOMClient from "react-dom/client";
21
- import * as JSXDevRuntime from "react/jsx-dev-runtime";
22
- import * as JSXRuntime from "react/jsx-runtime";
17
+ // src/shared/client/apply-origin.ts
18
+ var tagNames = [
19
+ "img",
20
+ "source",
21
+ "video",
22
+ "audio",
23
+ "track",
24
+ "iframe",
25
+ "embed",
26
+ "script",
27
+ "link"
28
+ ];
29
+ function applyOriginToNodes(doc, url) {
30
+ if (url.origin !== location.origin) {
31
+ const nodes = doc.querySelectorAll(
32
+ tagNames.map(
33
+ (type) => `${type}[src],${type}[srcset],${type}[href],${type}[imagesrcset]`
34
+ ).join(",")
35
+ );
36
+ nodes.forEach((node) => {
37
+ if (node.hasAttribute("src") && /^[./]+\/?/.test(node.getAttribute("src") ?? "")) {
38
+ node.src = new URL(node.getAttribute("src") ?? "/", url).href;
39
+ }
40
+ if (node.hasAttribute("href") && /^[./]+\/?/.test(node.getAttribute("href") ?? "")) {
41
+ node.setAttribute(
42
+ "href",
43
+ new URL(node.getAttribute("href") ?? "/", url).href
44
+ );
45
+ }
46
+ if (node.hasAttribute("srcset")) {
47
+ const srcSet = node.getAttribute("srcset")?.split(",").map((entry) => {
48
+ const [urlPart, descriptor] = entry.trim().split(/\s+/);
49
+ if (!urlPart)
50
+ return entry;
51
+ const absoluteUrl = new URL(urlPart, url).href;
52
+ return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
53
+ }).join(", ");
54
+ if (srcSet) {
55
+ node.setAttribute("srcset", srcSet);
56
+ }
57
+ }
58
+ if (node.hasAttribute("imagesrcset")) {
59
+ const srcSet = node.getAttribute("imagesrcset")?.split(",").map((entry) => {
60
+ const [urlPart, descriptor] = entry.trim().split(/\s+/);
61
+ if (!urlPart)
62
+ return entry;
63
+ const absoluteUrl = new URL(urlPart, url).href;
64
+ return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
65
+ }).join(", ");
66
+ if (srcSet) {
67
+ node.setAttribute("imagesrcset", srcSet);
68
+ }
69
+ }
70
+ });
71
+ }
72
+ }
23
73
 
24
- // src/shared/webpack/shared-modules.ts
25
- function applySharedModules(bundle, resolve) {
74
+ // src/shared/client/polyfill.tsx
75
+ import { jsx } from "react/jsx-runtime";
76
+ function applyBundleUrlToSrc(bundle, src) {
26
77
  const self = globalThis;
27
- if (self.__remote_webpack_require__?.[bundle]) {
28
- const modulePaths = Object.keys(
29
- self.__remote_webpack_module_map__?.[bundle] ?? self.__remote_webpack_require__[bundle].m ?? {}
30
- );
31
- for (const [key, value] of Object.entries(resolve)) {
32
- let ids = modulePaths.filter((p) => p === key);
33
- if (ids.length === 0) {
34
- ids = modulePaths.filter((p) => p.includes(key));
78
+ if (self.__remote_bundle_url__?.[bundle]?.origin === location.origin) {
79
+ return src;
80
+ }
81
+ const { assetPrefix, path } = /^(?<assetPrefix>.*?)\/_next\/(?<path>.*)/.exec(src)?.groups ?? {};
82
+ if (!path) {
83
+ return new URL(src, self.__remote_bundle_url__?.[bundle]?.origin).href;
84
+ }
85
+ return `${self.__remote_bundle_url__?.[bundle]?.origin ?? ""}${assetPrefix}/_next/${path}`;
86
+ }
87
+ function applyBundleUrlToImagePropsSrc(bundle, src) {
88
+ if (typeof src === "string") {
89
+ return applyBundleUrlToSrc(bundle, src);
90
+ }
91
+ const propSrc = src;
92
+ return applyBundleUrlToSrc(bundle, propSrc.src);
93
+ }
94
+ var imageImpl = (bundle) => function RemoteImage({
95
+ fill: _fill,
96
+ loader: _loader,
97
+ quality: _quality,
98
+ priority: _priority,
99
+ loading: _loading,
100
+ placeholder: _placeholder,
101
+ blurDataURL: _blurDataURL,
102
+ unoptimized: _unoptimized,
103
+ overrideSrc: _overrideSrc,
104
+ src,
105
+ ...props
106
+ }) {
107
+ const newSrc = applyBundleUrlToImagePropsSrc(
108
+ bundle,
109
+ typeof src === "string" ? src : src.src
110
+ );
111
+ return (
112
+ // eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text
113
+ /* @__PURE__ */ jsx(
114
+ "img",
115
+ {
116
+ decoding: "async",
117
+ style: { color: "transparent" },
118
+ ...props,
119
+ src: newSrc,
120
+ suppressHydrationWarning: true
35
121
  }
36
- for (let id of ids) {
37
- const webpackBundle = self.__remote_webpack_require__[bundle];
38
- if (webpackBundle.m) {
39
- if (self.__remote_webpack_module_map__?.[bundle]?.[id]) {
40
- id = `${self.__remote_webpack_module_map__[bundle][id]}`;
122
+ )
123
+ );
124
+ };
125
+ function sharedPolyfills(shared) {
126
+ const self = globalThis;
127
+ const polyfill = {
128
+ "next/dist/client/components/navigation": self.__remote_component_host_shared_modules__?.["next/navigation"] ?? shared?.["next/navigation"] ?? (() => Promise.resolve({
129
+ useRouter() {
130
+ return {
131
+ push: (routerUrl) => {
132
+ history.pushState({}, "", routerUrl);
133
+ },
134
+ replace: (routerUrl) => {
135
+ history.replaceState({}, "", routerUrl);
136
+ },
137
+ back: () => {
138
+ history.back();
41
139
  }
42
- webpackBundle.m[id] = (module) => {
43
- module.exports = value;
140
+ };
141
+ },
142
+ usePathname() {
143
+ return location.pathname;
144
+ },
145
+ useParams() {
146
+ return {};
147
+ },
148
+ useSearchParams() {
149
+ return new URLSearchParams(location.search);
150
+ },
151
+ useSelectedLayoutSegment() {
152
+ return null;
153
+ },
154
+ useSelectedLayoutSegments() {
155
+ return [];
156
+ },
157
+ __esModule: true
158
+ })),
159
+ "next/dist/client/app-dir/link": self.__remote_component_host_shared_modules__?.["next/link"] ?? shared?.["next/link"] ?? (() => Promise.resolve({
160
+ default: ({
161
+ scroll: _,
162
+ replace,
163
+ prefetch,
164
+ onNavigate,
165
+ children,
166
+ ...props
167
+ }) => {
168
+ if (prefetch) {
169
+ console.warn(
170
+ "Next.js Link prefetch is not supported in remote components"
171
+ );
172
+ }
173
+ return /* @__PURE__ */ jsx(
174
+ "a",
175
+ {
176
+ ...props,
177
+ href: props.href,
178
+ onClick: (e) => {
179
+ e.preventDefault();
180
+ let preventDefaulted = false;
181
+ e.preventDefault = () => {
182
+ preventDefaulted = true;
183
+ e.defaultPrevented = true;
184
+ };
185
+ if (typeof props.onClick === "function") {
186
+ props.onClick(e);
187
+ }
188
+ onNavigate?.(e);
189
+ if (preventDefaulted) {
190
+ return;
191
+ }
192
+ if (replace) {
193
+ history.replaceState({}, "", props.href);
194
+ } else {
195
+ history.pushState({}, "", props.href);
196
+ }
197
+ },
198
+ suppressHydrationWarning: true,
199
+ children: children ?? null
200
+ }
201
+ );
202
+ },
203
+ useLinkStatus() {
204
+ return { pending: false };
205
+ },
206
+ __esModule: true
207
+ })),
208
+ "next/dist/client/app-dir/form": self.__remote_component_host_shared_modules__?.["next/form"] ?? shared?.["next/form"] ?? (() => Promise.resolve({
209
+ default: () => {
210
+ throw new Error("Next.js <Form> component not implemented");
211
+ },
212
+ __esModule: true
213
+ })),
214
+ "next/dist/client/image-component": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
215
+ Image: imageImpl(bundle),
216
+ __esModule: true
217
+ })),
218
+ "next/image": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
219
+ default: imageImpl(bundle),
220
+ getImageProps: (_imgProps) => {
221
+ throw new Error(
222
+ "Next.js getImageProps() is not implemented in remote components"
223
+ );
224
+ },
225
+ __esModule: true
226
+ })),
227
+ "next/dist/client/script": self.__remote_component_host_shared_modules__?.["next/script"] ?? shared?.["next/script"] ?? (() => Promise.resolve({
228
+ // TODO: implement <Script> component for non-Next.js host applications
229
+ // do not throw an error for now
230
+ default: () => null,
231
+ __esModule: true
232
+ })),
233
+ "next/router": self.__remote_component_host_shared_modules__?.["next/router"] ?? shared?.["next/router"] ?? (() => (
234
+ // TODO: incomplete implementation
235
+ Promise.resolve({
236
+ useRouter() {
237
+ return {
238
+ push: (routerUrl) => {
239
+ history.pushState({}, "", routerUrl);
240
+ },
241
+ replace: (routerUrl) => {
242
+ history.replaceState({}, "", routerUrl);
243
+ },
244
+ back: () => {
245
+ history.back();
246
+ }
44
247
  };
248
+ },
249
+ __esModule: true
250
+ })
251
+ )),
252
+ "next/dist/build/polyfills/process": () => Promise.resolve({
253
+ default: {
254
+ env: {
255
+ NODE_ENV: "production"
45
256
  }
46
- }
47
- }
48
- }
257
+ },
258
+ __esModule: true
259
+ })
260
+ };
261
+ polyfill["next/navigation"] = polyfill["next/dist/client/components/navigation"];
262
+ polyfill["next/link"] = polyfill["next/dist/client/app-dir/link"];
263
+ polyfill["next/form"] = polyfill["next/dist/client/app-dir/form"];
264
+ polyfill["next/dist/api/image"] = polyfill["next/dist/client/image-component"];
265
+ polyfill["next/script"] = polyfill["next/dist/client/script"];
266
+ return polyfill;
49
267
  }
50
268
 
51
269
  // src/shared/error.ts
52
270
  var RemoteComponentsError = class extends Error {
271
+ code = "REMOTE_COMPONENTS_ERROR";
53
272
  constructor(message, options) {
54
273
  super(message, options);
55
- this.code = "REMOTE_COMPONENTS_ERROR";
56
274
  this.name = "RemoteComponentsError";
57
275
  }
58
276
  };
@@ -68,6 +286,13 @@ function failedToFetchRemoteComponentError(url, error) {
68
286
  );
69
287
  }
70
288
 
289
+ // src/shared/client/component-loader.ts
290
+ import * as React from "react";
291
+ import * as JSXDevRuntime from "react/jsx-dev-runtime";
292
+ import * as JSXRuntime from "react/jsx-runtime";
293
+ import * as ReactDOM from "react-dom";
294
+ import * as ReactDOMClient from "react-dom/client";
295
+
71
296
  // src/shared/webpack/next-client-pages-loader.ts
72
297
  function nextClientPagesLoader(bundle, route, styleContainer = document.head) {
73
298
  const self = globalThis;
@@ -155,29 +380,151 @@ function nextClientPagesLoader(bundle, route, styleContainer = document.head) {
155
380
  node.remove();
156
381
  node = nextCss.previousSibling;
157
382
  }
158
- self.__remote_next_css__[bundle] = elements;
159
- }
160
- if (styleContainer) {
161
- const elements = self.__remote_next_css__[bundle];
162
- elements.forEach((el) => {
163
- styleContainer.appendChild(el.cloneNode(true));
164
- });
383
+ self.__remote_next_css__[bundle] = elements;
384
+ }
385
+ if (styleContainer) {
386
+ const elements = self.__remote_next_css__[bundle];
387
+ elements.forEach((el) => {
388
+ styleContainer.appendChild(el.cloneNode(true));
389
+ });
390
+ } else {
391
+ const elements = self.__remote_next_css__[bundle];
392
+ elements.forEach((el) => {
393
+ document.head.appendChild(el);
394
+ });
395
+ }
396
+ delete self.__NEXT_P;
397
+ self.__NEXT_P = __NEXT_P_ORIGINAL;
398
+ if (nextCssOriginal) {
399
+ nextCssOriginal.parentNode?.appendChild(nextCssOriginal);
400
+ }
401
+ nextCss.remove();
402
+ nextCssEnd.remove();
403
+ return { Component, App };
404
+ }
405
+ return { Component: null, App: null };
406
+ }
407
+
408
+ // src/shared/webpack/shared-modules.ts
409
+ function applySharedModules(bundle, resolve) {
410
+ const self = globalThis;
411
+ if (self.__remote_webpack_require__?.[bundle]) {
412
+ const modulePaths = Object.keys(
413
+ self.__remote_webpack_module_map__?.[bundle] ?? self.__remote_webpack_require__[bundle].m ?? {}
414
+ );
415
+ for (const [key, value] of Object.entries(resolve)) {
416
+ let ids = modulePaths.filter((p) => p === key);
417
+ if (ids.length === 0) {
418
+ ids = modulePaths.filter((p) => p.includes(key));
419
+ }
420
+ for (let id of ids) {
421
+ const webpackBundle = self.__remote_webpack_require__[bundle];
422
+ if (webpackBundle.m) {
423
+ if (self.__remote_webpack_module_map__?.[bundle]?.[id]) {
424
+ id = `${self.__remote_webpack_module_map__[bundle][id]}`;
425
+ }
426
+ webpackBundle.m[id] = (module) => {
427
+ module.exports = value;
428
+ };
429
+ }
430
+ }
431
+ }
432
+ }
433
+ }
434
+
435
+ // src/shared/client/rsc.ts
436
+ import { ReadableStream } from "web-streams-polyfill";
437
+ function fixPayload(payload) {
438
+ if (Array.isArray(payload)) {
439
+ if (payload[0] === "$") {
440
+ fixPayload(payload[3]);
441
+ if (payload.length === 4) {
442
+ payload.push(null, null, 1);
443
+ }
165
444
  } else {
166
- const elements = self.__remote_next_css__[bundle];
167
- elements.forEach((el) => {
168
- document.head.appendChild(el);
169
- });
445
+ for (const item of payload) {
446
+ fixPayload(item);
447
+ }
170
448
  }
171
- delete self.__NEXT_P;
172
- self.__NEXT_P = __NEXT_P_ORIGINAL;
173
- if (nextCssOriginal) {
174
- nextCssOriginal.parentNode?.appendChild(nextCssOriginal);
449
+ } else if (typeof payload === "object" && payload !== null) {
450
+ for (const key in payload) {
451
+ fixPayload(payload[key]);
175
452
  }
176
- nextCss.remove();
177
- nextCssEnd.remove();
178
- return { Component, App };
179
453
  }
180
- return { Component: null, App: null };
454
+ }
455
+ function createRSCStream(rscName, data) {
456
+ return new ReadableStream({
457
+ type: "bytes",
458
+ start(controller) {
459
+ const encoder = new TextEncoder();
460
+ const self = globalThis;
461
+ if (data.length > 0) {
462
+ data.forEach((chunk) => {
463
+ const lines = chunk.split("\n");
464
+ for (const line of lines) {
465
+ const match = /\.push\("(?<rsc>.*)"\);$/.exec(line);
466
+ if (match?.groups?.rsc) {
467
+ self[rscName] = self[rscName] ?? [];
468
+ self[rscName].push(JSON.parse(`"${match.groups.rsc}"`));
469
+ }
470
+ }
471
+ });
472
+ }
473
+ const allChunks = (self[rscName] ?? [`0:[null]
474
+ `]).join("");
475
+ self[rscName] = null;
476
+ allChunks.split("\n").forEach((chunk) => {
477
+ if (chunk.length > 0) {
478
+ const { before, id, prefix, payload } = /^(?<before>[^:]*?)?(?<id>[0-9a-zA-Z]+):(?<prefix>[A-Z])?(?<payload>\[.*\])/.exec(
479
+ chunk
480
+ )?.groups ?? {};
481
+ if (payload) {
482
+ const jsonPayload = JSON.parse(payload);
483
+ fixPayload(jsonPayload);
484
+ const reconstruct = `${before ?? ""}${id}:${prefix ?? ""}${JSON.stringify(jsonPayload)}`;
485
+ controller.enqueue(encoder.encode(`${reconstruct}
486
+ `));
487
+ } else {
488
+ controller.enqueue(encoder.encode(`${chunk}
489
+ `));
490
+ }
491
+ } else {
492
+ controller.enqueue(encoder.encode(`${chunk}
493
+ `));
494
+ }
495
+ });
496
+ controller.close();
497
+ }
498
+ });
499
+ }
500
+
501
+ // src/shared/client/script-loader.ts
502
+ async function loadScripts(scripts) {
503
+ await Promise.all(
504
+ scripts.map((script) => {
505
+ return new Promise((resolve, reject) => {
506
+ const newSrc = new URL(
507
+ // remove the remote component bundle name identifier from the script src
508
+ script.src.replace(/\/_next\/\[.+\](?<whitespace>%20| )/, "/_next/"),
509
+ location.origin
510
+ ).href;
511
+ const newScript = document.createElement("script");
512
+ newScript.onload = () => {
513
+ resolve();
514
+ };
515
+ newScript.onerror = () => {
516
+ reject(
517
+ new RemoteComponentsError(
518
+ `Failed to load <script src="${script.src}"> for Remote Component. Check the URL is correct.`
519
+ )
520
+ );
521
+ };
522
+ newScript.src = newSrc;
523
+ newScript.async = true;
524
+ document.head.appendChild(newScript);
525
+ });
526
+ })
527
+ );
181
528
  }
182
529
 
183
530
  // src/shared/utils/index.ts
@@ -196,6 +543,7 @@ var attrToProp = {
196
543
  var DEFAULT_ROUTE = "/";
197
544
  var RUNTIME_WEBPACK = "webpack";
198
545
  var RUNTIME_TURBOPACK = "turbopack";
546
+ var RUNTIME_SCRIPT = "script";
199
547
  var REMOTE_COMPONENT_REGEX = /(?<prefix>.*?)\[(?<bundle>[^\]]+)\](?:%20| )(?<id>.+)/;
200
548
  function getBundleKey(bundle) {
201
549
  return escapeString(bundle);
@@ -364,7 +712,10 @@ async function handleTurbopackChunk(code, bundle, url) {
364
712
  function createModuleRequire(runtime) {
365
713
  return (id) => {
366
714
  const self = globalThis;
367
- const { bundle, id: moduleId } = id.match(REMOTE_COMPONENT_REGEX)?.groups ?? { bundle: "default", id };
715
+ const { bundle, id: moduleId } = id.match(REMOTE_COMPONENT_REGEX)?.groups ?? {
716
+ bundle: "default",
717
+ id
718
+ };
368
719
  const remoteRuntime = self.__remote_webpack_require__?.[bundle ?? "default"] ? self.__remote_webpack_require__[bundle ?? "default"]?.type || "webpack" : runtime;
369
720
  try {
370
721
  if (remoteRuntime === RUNTIME_WEBPACK && bundle && moduleId) {
@@ -700,101 +1051,6 @@ function handleTurbopackModule(bundle, moduleId, id) {
700
1051
  return moduleExports.exports;
701
1052
  }
702
1053
 
703
- // src/shared/client/script-loader.ts
704
- async function loadScripts(scripts) {
705
- await Promise.all(
706
- scripts.map((script) => {
707
- return new Promise((resolve, reject) => {
708
- const newSrc = new URL(
709
- // remove the remote component bundle name identifier from the script src
710
- script.src.replace(/\/_next\/\[.+\](?<whitespace>%20| )/, "/_next/"),
711
- location.origin
712
- ).href;
713
- const newScript = document.createElement("script");
714
- newScript.onload = () => {
715
- resolve();
716
- };
717
- newScript.onerror = () => {
718
- reject(
719
- new RemoteComponentsError(
720
- `Failed to load <script src="${script.src}"> for Remote Component. Check the URL is correct.`
721
- )
722
- );
723
- };
724
- newScript.src = newSrc;
725
- newScript.async = true;
726
- document.head.appendChild(newScript);
727
- });
728
- })
729
- );
730
- }
731
-
732
- // src/shared/client/rsc.ts
733
- import { ReadableStream } from "web-streams-polyfill";
734
- function fixPayload(payload) {
735
- if (Array.isArray(payload)) {
736
- if (payload[0] === "$") {
737
- fixPayload(payload[3]);
738
- if (payload.length === 4) {
739
- payload.push(null, null, 1);
740
- }
741
- } else {
742
- for (const item of payload) {
743
- fixPayload(item);
744
- }
745
- }
746
- } else if (typeof payload === "object" && payload !== null) {
747
- for (const key in payload) {
748
- fixPayload(payload[key]);
749
- }
750
- }
751
- }
752
- function createRSCStream(rscName, data) {
753
- return new ReadableStream({
754
- type: "bytes",
755
- start(controller) {
756
- const encoder = new TextEncoder();
757
- const self = globalThis;
758
- if (data.length > 0) {
759
- data.forEach((chunk) => {
760
- const lines = chunk.split("\n");
761
- for (const line of lines) {
762
- const match = /\.push\("(?<rsc>.*)"\);$/.exec(line);
763
- if (match?.groups?.rsc) {
764
- self[rscName] = self[rscName] ?? [];
765
- self[rscName].push(JSON.parse(`"${match.groups.rsc}"`));
766
- }
767
- }
768
- });
769
- }
770
- const allChunks = (self[rscName] ?? [`0:[null]
771
- `]).join("");
772
- self[rscName] = null;
773
- allChunks.split("\n").forEach((chunk) => {
774
- if (chunk.length > 0) {
775
- const { before, id, prefix, payload } = /^(?<before>[^:]*?)?(?<id>[0-9a-zA-Z]+):(?<prefix>[A-Z])?(?<payload>\[.*\])/.exec(
776
- chunk
777
- )?.groups ?? {};
778
- if (payload) {
779
- const jsonPayload = JSON.parse(payload);
780
- fixPayload(jsonPayload);
781
- const reconstruct = `${before ?? ""}${id}:${prefix ?? ""}${JSON.stringify(jsonPayload)}`;
782
- controller.enqueue(encoder.encode(`${reconstruct}
783
- `));
784
- } else {
785
- controller.enqueue(encoder.encode(`${chunk}
786
- `));
787
- }
788
- } else {
789
- controller.enqueue(encoder.encode(`${chunk}
790
- `));
791
- }
792
- });
793
- controller.close();
794
- }
795
- });
796
- }
797
-
798
1054
  // src/shared/client/component-loader.ts
799
1055
  async function loadRemoteComponent({
800
1056
  url,
@@ -867,7 +1123,9 @@ async function loadRemoteComponent({
867
1123
  component: null,
868
1124
  error: new RemoteComponentsError(
869
1125
  `Failed to load remote component "${name}".`,
870
- { cause: error instanceof Error ? error : new Error(String(error)) }
1126
+ {
1127
+ cause: error instanceof Error ? error : new Error(String(error))
1128
+ }
871
1129
  )
872
1130
  };
873
1131
  }
@@ -925,7 +1183,7 @@ function isBooleanScriptAttribute(attr) {
925
1183
  }
926
1184
  function setAttributesFromProps(el, props) {
927
1185
  for (const [p, value] of Object.entries(props)) {
928
- if (!Object.prototype.hasOwnProperty.call(props, p))
1186
+ if (!Object.hasOwn(props, p))
929
1187
  continue;
930
1188
  if (ignoreProps.includes(p))
931
1189
  continue;
@@ -944,257 +1202,99 @@ function setAttributesFromProps(el, props) {
944
1202
  }
945
1203
  }
946
1204
  }
947
-
948
- // src/shared/client/polyfill.tsx
949
- import { jsx } from "react/jsx-runtime";
950
- function applyBundleUrlToSrc(bundle, src) {
951
- const self = globalThis;
952
- if (self.__remote_bundle_url__?.[bundle]?.origin === location.origin) {
953
- return src;
954
- }
955
- const { assetPrefix, path } = /^(?<assetPrefix>.*?)\/_next\/(?<path>.*)/.exec(src)?.groups ?? {};
956
- if (!path) {
957
- return new URL(src, self.__remote_bundle_url__?.[bundle]?.origin).href;
958
- }
959
- return `${self.__remote_bundle_url__?.[bundle]?.origin ?? ""}${assetPrefix}/_next/${path}`;
960
- }
961
- function applyBundleUrlToImagePropsSrc(bundle, src) {
962
- if (typeof src === "string") {
963
- return applyBundleUrlToSrc(bundle, src);
964
- }
965
- const propSrc = src;
966
- return applyBundleUrlToSrc(bundle, propSrc.src);
967
- }
968
- var imageImpl = (bundle) => function RemoteImage({
969
- fill: _fill,
970
- loader: _loader,
971
- quality: _quality,
972
- priority: _priority,
973
- loading: _loading,
974
- placeholder: _placeholder,
975
- blurDataURL: _blurDataURL,
976
- unoptimized: _unoptimized,
977
- overrideSrc: _overrideSrc,
978
- src,
979
- ...props
980
- }) {
981
- const newSrc = applyBundleUrlToImagePropsSrc(
982
- bundle,
983
- typeof src === "string" ? src : src.src
984
- );
985
- return (
986
- // eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text
987
- /* @__PURE__ */ jsx(
988
- "img",
989
- {
990
- decoding: "async",
991
- style: { color: "transparent" },
992
- ...props,
993
- src: newSrc,
994
- suppressHydrationWarning: true
995
- }
996
- )
997
- );
998
- };
999
- function sharedPolyfills(shared) {
1205
+
1206
+ // src/shared/client/static-loader.ts
1207
+ async function loadStaticRemoteComponent(scripts, url) {
1000
1208
  const self = globalThis;
1001
- const polyfill = {
1002
- "next/dist/client/components/navigation": self.__remote_component_host_shared_modules__?.["next/navigation"] ?? shared?.["next/navigation"] ?? (() => Promise.resolve({
1003
- useRouter() {
1004
- return {
1005
- push: (routerUrl) => {
1006
- history.pushState({}, "", routerUrl);
1007
- },
1008
- replace: (routerUrl) => {
1009
- history.replaceState({}, "", routerUrl);
1010
- },
1011
- back: () => {
1012
- history.back();
1209
+ if (self.__remote_script_entrypoint_mount__?.[url.href]) {
1210
+ self.__remote_script_entrypoint_mount__[url.href] = /* @__PURE__ */ new Set();
1211
+ }
1212
+ if (self.__remote_script_entrypoint_unmount__?.[url.href]) {
1213
+ self.__remote_script_entrypoint_unmount__[url.href] = /* @__PURE__ */ new Set();
1214
+ }
1215
+ const mountUnmountSets = await Promise.all(
1216
+ scripts.map(async (script) => {
1217
+ try {
1218
+ let src = typeof script.getAttribute === "function" ? script.getAttribute("src") ?? script.src : script.src;
1219
+ if (!src && script.textContent) {
1220
+ const blob = new Blob(
1221
+ [
1222
+ script.textContent.replace(
1223
+ /import\.meta\.url/g,
1224
+ JSON.stringify(url)
1225
+ )
1226
+ ],
1227
+ {
1228
+ type: "text/javascript"
1229
+ }
1230
+ );
1231
+ src = URL.createObjectURL(blob);
1232
+ }
1233
+ const mod = await import(
1234
+ /* @vite-ignore */
1235
+ /* webpackIgnore: true */
1236
+ new URL(src, url).href
1237
+ );
1238
+ if (src.startsWith("blob:")) {
1239
+ URL.revokeObjectURL(src);
1240
+ }
1241
+ if (typeof mod.mount === "function" || typeof mod.default?.mount === "function") {
1242
+ if (!self.__remote_script_entrypoint_mount__) {
1243
+ self.__remote_script_entrypoint_mount__ = {};
1013
1244
  }
1014
- };
1015
- },
1016
- usePathname() {
1017
- return location.pathname;
1018
- },
1019
- useParams() {
1020
- return {};
1021
- },
1022
- useSearchParams() {
1023
- return new URLSearchParams(location.search);
1024
- },
1025
- useSelectedLayoutSegment() {
1026
- return null;
1027
- },
1028
- useSelectedLayoutSegments() {
1029
- return [];
1030
- },
1031
- __esModule: true
1032
- })),
1033
- "next/dist/client/app-dir/link": self.__remote_component_host_shared_modules__?.["next/link"] ?? shared?.["next/link"] ?? (() => Promise.resolve({
1034
- default: ({
1035
- scroll: _,
1036
- replace,
1037
- prefetch,
1038
- onNavigate,
1039
- children,
1040
- ...props
1041
- }) => {
1042
- if (prefetch) {
1043
- console.warn(
1044
- "Next.js Link prefetch is not supported in remote components"
1245
+ if (!self.__remote_script_entrypoint_mount__[url.href]) {
1246
+ self.__remote_script_entrypoint_mount__[url.href] = /* @__PURE__ */ new Set();
1247
+ }
1248
+ self.__remote_script_entrypoint_mount__[url.href]?.add(
1249
+ mod.mount || mod.default?.mount || (() => {
1250
+ })
1045
1251
  );
1046
1252
  }
1047
- return /* @__PURE__ */ jsx(
1048
- "a",
1049
- {
1050
- ...props,
1051
- href: props.href,
1052
- onClick: (e) => {
1053
- e.preventDefault();
1054
- let preventDefaulted = false;
1055
- e.preventDefault = () => {
1056
- preventDefaulted = true;
1057
- e.defaultPrevented = true;
1058
- };
1059
- if (typeof props.onClick === "function") {
1060
- props.onClick(e);
1061
- }
1062
- onNavigate?.(e);
1063
- if (preventDefaulted) {
1064
- return;
1065
- }
1066
- if (replace) {
1067
- history.replaceState({}, "", props.href);
1068
- } else {
1069
- history.pushState({}, "", props.href);
1070
- }
1071
- },
1072
- suppressHydrationWarning: true,
1073
- children: children ?? null
1253
+ if (typeof mod.unmount === "function" || typeof mod.default?.unmount === "function") {
1254
+ if (!self.__remote_script_entrypoint_unmount__) {
1255
+ self.__remote_script_entrypoint_unmount__ = {};
1074
1256
  }
1075
- );
1076
- },
1077
- useLinkStatus() {
1078
- return { pending: false };
1079
- },
1080
- __esModule: true
1081
- })),
1082
- "next/dist/client/app-dir/form": self.__remote_component_host_shared_modules__?.["next/form"] ?? shared?.["next/form"] ?? (() => Promise.resolve({
1083
- default: () => {
1084
- throw new Error("Next.js <Form> component not implemented");
1085
- },
1086
- __esModule: true
1087
- })),
1088
- "next/dist/client/image-component": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
1089
- Image: imageImpl(bundle),
1090
- __esModule: true
1091
- })),
1092
- "next/image": self.__remote_component_host_shared_modules__?.["next/image"] ?? shared?.["next/image"] ?? ((bundle) => Promise.resolve({
1093
- default: imageImpl(bundle),
1094
- getImageProps: (_imgProps) => {
1095
- throw new Error(
1096
- "Next.js getImageProps() is not implemented in remote components"
1097
- );
1098
- },
1099
- __esModule: true
1100
- })),
1101
- "next/dist/client/script": self.__remote_component_host_shared_modules__?.["next/script"] ?? shared?.["next/script"] ?? (() => Promise.resolve({
1102
- // TODO: implement <Script> component for non-Next.js host applications
1103
- // do not throw an error for now
1104
- default: () => null,
1105
- __esModule: true
1106
- })),
1107
- "next/router": self.__remote_component_host_shared_modules__?.["next/router"] ?? shared?.["next/router"] ?? (() => (
1108
- // TODO: incomplete implementation
1109
- Promise.resolve({
1110
- useRouter() {
1111
- return {
1112
- push: (routerUrl) => {
1113
- history.pushState({}, "", routerUrl);
1114
- },
1115
- replace: (routerUrl) => {
1116
- history.replaceState({}, "", routerUrl);
1117
- },
1118
- back: () => {
1119
- history.back();
1120
- }
1121
- };
1122
- },
1123
- __esModule: true
1124
- })
1125
- )),
1126
- "next/dist/build/polyfills/process": () => Promise.resolve({
1127
- default: {
1128
- env: {
1129
- NODE_ENV: "production"
1257
+ if (!self.__remote_script_entrypoint_unmount__[url.href]) {
1258
+ self.__remote_script_entrypoint_unmount__[url.href] = /* @__PURE__ */ new Set();
1259
+ }
1260
+ self.__remote_script_entrypoint_unmount__[url.href]?.add(
1261
+ mod.unmount || mod.default?.unmount || (() => {
1262
+ })
1263
+ );
1130
1264
  }
1131
- },
1132
- __esModule: true
1133
- })
1134
- };
1135
- polyfill["next/navigation"] = polyfill["next/dist/client/components/navigation"];
1136
- polyfill["next/link"] = polyfill["next/dist/client/app-dir/link"];
1137
- polyfill["next/form"] = polyfill["next/dist/client/app-dir/form"];
1138
- polyfill["next/dist/api/image"] = polyfill["next/dist/client/image-component"];
1139
- polyfill["next/script"] = polyfill["next/dist/client/script"];
1140
- return polyfill;
1141
- }
1142
-
1143
- // src/shared/client/apply-origin.ts
1144
- var tagNames = [
1145
- "img",
1146
- "source",
1147
- "video",
1148
- "audio",
1149
- "track",
1150
- "iframe",
1151
- "embed",
1152
- "script",
1153
- "link"
1154
- ];
1155
- function applyOriginToNodes(doc, url) {
1156
- if (url.origin !== location.origin) {
1157
- const nodes = doc.querySelectorAll(
1158
- tagNames.map(
1159
- (type) => `${type}[src],${type}[srcset],${type}[href],${type}[imagesrcset]`
1160
- ).join(",")
1161
- );
1162
- nodes.forEach((node) => {
1163
- if (node.hasAttribute("src") && /^[./]+\/?/.test(node.getAttribute("src") ?? "")) {
1164
- node.src = new URL(node.getAttribute("src") ?? "/", url).href;
1165
- }
1166
- if (node.hasAttribute("href") && /^[./]+\/?/.test(node.getAttribute("href") ?? "")) {
1167
- node.setAttribute(
1168
- "href",
1169
- new URL(node.getAttribute("href") ?? "/", url).href
1265
+ return {
1266
+ mount: mod.mount || mod.default?.mount,
1267
+ unmount: mod.unmount || mod.default?.unmount
1268
+ };
1269
+ } catch (e) {
1270
+ console.error(
1271
+ new RemoteComponentsError(
1272
+ `Error loading remote component script from "${script.src || url.href}".`,
1273
+ { cause: e }
1274
+ )
1170
1275
  );
1276
+ return {
1277
+ mount: void 0,
1278
+ unmount: void 0
1279
+ };
1171
1280
  }
1172
- if (node.hasAttribute("srcset")) {
1173
- const srcSet = node.getAttribute("srcset")?.split(",").map((entry) => {
1174
- const [urlPart, descriptor] = entry.trim().split(/\s+/);
1175
- if (!urlPart)
1176
- return entry;
1177
- const absoluteUrl = new URL(urlPart, url).href;
1178
- return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
1179
- }).join(", ");
1180
- if (srcSet) {
1181
- node.setAttribute("srcset", srcSet);
1182
- }
1281
+ })
1282
+ );
1283
+ return mountUnmountSets.reduce(
1284
+ (acc, { mount, unmount }) => {
1285
+ if (typeof mount === "function") {
1286
+ acc.mount.add(mount);
1183
1287
  }
1184
- if (node.hasAttribute("imagesrcset")) {
1185
- const srcSet = node.getAttribute("imagesrcset")?.split(",").map((entry) => {
1186
- const [urlPart, descriptor] = entry.trim().split(/\s+/);
1187
- if (!urlPart)
1188
- return entry;
1189
- const absoluteUrl = new URL(urlPart, url).href;
1190
- return descriptor ? `${absoluteUrl} ${descriptor}` : absoluteUrl;
1191
- }).join(", ");
1192
- if (srcSet) {
1193
- node.setAttribute("imagesrcset", srcSet);
1194
- }
1288
+ if (typeof unmount === "function") {
1289
+ acc.unmount.add(unmount);
1195
1290
  }
1196
- });
1197
- }
1291
+ return acc;
1292
+ },
1293
+ {
1294
+ mount: /* @__PURE__ */ new Set(),
1295
+ unmount: /* @__PURE__ */ new Set()
1296
+ }
1297
+ );
1198
1298
  }
1199
1299
 
1200
1300
  // src/shared/ssr/fetch-headers.ts
@@ -1230,7 +1330,7 @@ function getRemoteComponentHtml(html) {
1230
1330
  return ssrRemoteComponentContainer.innerHTML;
1231
1331
  }
1232
1332
  const remoteComponentContainer = temp.querySelectorAll(
1233
- `div[data-bundle][data-route][data-runtime][id^="__vercel_remote_component"],div[data-bundle][data-route],div#__next`
1333
+ `div[data-bundle][data-route][data-runtime][id^="__vercel_remote_component"],div[data-bundle][data-route],div#__next,remote-component:not([src])`
1234
1334
  );
1235
1335
  if (remoteComponentContainer.length > 0) {
1236
1336
  return `${Array.from(temp.querySelectorAll("link,script")).map((link) => link.outerHTML).join("")}${Array.from(remoteComponentContainer).map((container) => container.outerHTML).join("")}`;
@@ -1295,6 +1395,10 @@ function RemoteComponent({
1295
1395
  );
1296
1396
  const prevSrcRef = useRef(null);
1297
1397
  const componentHydrationHtml = useRef(null);
1398
+ const prevIsRemoteComponentRef = useRef(false);
1399
+ const prevUrlRef = useRef(null);
1400
+ const prevRemoteComponentContainerRef = useRef(null);
1401
+ const unmountRef = useRef(null);
1298
1402
  useLayoutEffect(() => {
1299
1403
  if (childrenRef.current.length > 0 && remoteComponent) {
1300
1404
  childrenRef.current.forEach((el) => {
@@ -1407,34 +1511,58 @@ function RemoteComponent({
1407
1511
  }
1408
1512
  const parser = new DOMParser();
1409
1513
  const doc = parser.parseFromString(html, "text/html");
1410
- if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(`div[data-bundle][data-route][id^="${name}"]`)) {
1514
+ if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
1515
+ `div[data-bundle][data-route][id^="${name}"]`
1516
+ ) || doc.querySelectorAll("remote-component:not([src])").length > 1 && !doc.querySelector(`remote-component[name="${name}"]`)) {
1411
1517
  throw multipleRemoteComponentsError(url.href);
1412
1518
  }
1413
1519
  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
1414
1520
  doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
1415
- doc.querySelector("div#__next");
1521
+ doc.querySelector("div#__next") ?? // fallback to the remote-component web component
1522
+ doc.querySelector(`remote-component[name="${name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
1416
1523
  const nextData = JSON.parse(
1417
1524
  (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
1418
1525
  );
1419
1526
  const remoteName = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : name);
1420
1527
  const rsc = doc.querySelector(`#${remoteName}_rsc`);
1421
1528
  const bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || "default";
1529
+ const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
1422
1530
  const metadata = {
1423
1531
  name: remoteName,
1424
1532
  bundle,
1425
- route: component?.getAttribute("data-route") ?? nextData?.page ?? DEFAULT_ROUTE,
1426
- runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_WEBPACK)
1533
+ route: component?.getAttribute("data-route") ?? nextData?.page ?? (url.pathname || DEFAULT_ROUTE),
1534
+ runtime: component?.getAttribute("data-runtime") ?? (nextData?.props.__REMOTE_COMPONENT__?.runtime || RUNTIME_SCRIPT)
1427
1535
  };
1428
1536
  const remoteSharedEl = doc.querySelector(
1429
1537
  `#${remoteName}_shared[data-remote-components-shared]`
1430
1538
  );
1431
1539
  const remoteShared = nextData?.props.__REMOTE_COMPONENT__?.shared ?? (JSON.parse(remoteSharedEl?.textContent ?? "{}") ?? {});
1432
1540
  remoteSharedEl?.remove();
1433
- if (!component || !(rsc || nextData)) {
1541
+ if (!component || !(rsc || nextData || isRemoteComponent)) {
1434
1542
  throw new RemoteComponentsError(
1435
1543
  `Remote Component not found on ${url.href}.${remoteName !== "__vercel_remote_component" ? `The name for the <RemoteComponent> is "${remoteName}". Check <RemoteComponent> usage.` : ""} Did you forget to wrap the content in <RemoteComponent>?`
1436
1544
  );
1437
1545
  }
1546
+ if (prevIsRemoteComponentRef.current) {
1547
+ if (shadowRoot) {
1548
+ shadowRoot.innerHTML = "";
1549
+ }
1550
+ const self = globalThis;
1551
+ const prevUrl = prevUrlRef.current;
1552
+ if (prevUrl && self.__remote_script_entrypoint_unmount__?.[prevUrl.href]) {
1553
+ const unmountPromises = Promise.all(
1554
+ Array.from(unmountRef.current ?? []).map(
1555
+ async (unmount) => unmount(
1556
+ shadowRoot ?? prevRemoteComponentContainerRef.current
1557
+ )
1558
+ )
1559
+ );
1560
+ unmountRef.current = null;
1561
+ await unmountPromises;
1562
+ }
1563
+ }
1564
+ prevIsRemoteComponentRef.current = isRemoteComponent;
1565
+ prevUrlRef.current = url;
1438
1566
  applyOriginToNodes(doc, url);
1439
1567
  const links = Array.from(
1440
1568
  doc.querySelectorAll("link[href]")
@@ -1449,64 +1577,64 @@ function RemoteComponent({
1449
1577
  return acc;
1450
1578
  }, {})
1451
1579
  }));
1452
- const scripts = doc.querySelectorAll(
1453
- "script[src],script[data-src]"
1454
- );
1455
- const inlineScripts = doc.querySelectorAll(
1580
+ const scripts = (isRemoteComponent ? component : doc).querySelectorAll("script[src],script[data-src]");
1581
+ const inlineScripts = (isRemoteComponent ? component : doc).querySelectorAll(
1456
1582
  "script:not([src]):not([data-src]):not([id*='_rsc']):not([id='__NEXT_DATA__']):not([id='__REMOTE_NEXT_DATA__'])"
1457
1583
  );
1458
- const self = globalThis;
1459
- const prevNextScripts = self.__next_s;
1460
- const nextScripts = [];
1461
- self.__next_s = nextScripts;
1462
- await Promise.all(
1463
- Array.from(inlineScripts).filter(
1464
- (script) => !(script.id.endsWith("_shared") && script.getAttribute("type") === "application/json" && typeof script.getAttribute(
1465
- "data-remote-components-shared"
1466
- ) === "string")
1467
- ).map((script) => {
1468
- return new Promise((resolve) => {
1469
- if (script.textContent && !script.textContent.includes("self.__next_f=") && !script.textContent.includes("self.__next_f.push")) {
1470
- if (!script.getAttribute("type") || script.getAttribute("type") === "text/javascript" || script.getAttribute("type") === "application/javascript") {
1471
- const newScript = document.createElement("script");
1472
- const blob = new Blob([script.textContent], {
1473
- type: "application/javascript"
1474
- });
1475
- const blobUrl = URL.createObjectURL(blob);
1476
- newScript.onload = () => {
1584
+ if (!isRemoteComponent) {
1585
+ const self = globalThis;
1586
+ const prevNextScripts = self.__next_s;
1587
+ const nextScripts = [];
1588
+ self.__next_s = nextScripts;
1589
+ await Promise.all(
1590
+ Array.from(inlineScripts).filter(
1591
+ (script) => !(script.id.endsWith("_shared") && script.getAttribute("type") === "application/json" && typeof script.getAttribute(
1592
+ "data-remote-components-shared"
1593
+ ) === "string")
1594
+ ).map((script) => {
1595
+ return new Promise((resolve) => {
1596
+ if (script.textContent && !script.textContent.includes("self.__next_f=") && !script.textContent.includes("self.__next_f.push")) {
1597
+ if (!script.getAttribute("type") || script.getAttribute("type") === "text/javascript" || script.getAttribute("type") === "application/javascript") {
1598
+ const newScript = document.createElement("script");
1599
+ const blob = new Blob([script.textContent], {
1600
+ type: "application/javascript"
1601
+ });
1602
+ const blobUrl = URL.createObjectURL(blob);
1603
+ newScript.onload = () => {
1604
+ resolve(void 0);
1605
+ URL.revokeObjectURL(blobUrl);
1606
+ newScript.remove();
1607
+ };
1608
+ newScript.onerror = () => {
1609
+ URL.revokeObjectURL(blobUrl);
1610
+ newScript.remove();
1611
+ resolve(void 0);
1612
+ };
1613
+ newScript.src = blobUrl;
1614
+ document.body.appendChild(newScript);
1615
+ } else {
1477
1616
  resolve(void 0);
1478
- URL.revokeObjectURL(blobUrl);
1479
- newScript.remove();
1480
- };
1481
- newScript.onerror = () => {
1482
- URL.revokeObjectURL(blobUrl);
1483
- newScript.remove();
1484
- resolve(void 0);
1485
- };
1486
- newScript.src = blobUrl;
1487
- document.body.appendChild(newScript);
1617
+ document.body.appendChild(script);
1618
+ }
1488
1619
  } else {
1489
1620
  resolve(void 0);
1490
- document.body.appendChild(script);
1491
1621
  }
1492
- } else {
1493
- resolve(void 0);
1494
- }
1495
- });
1496
- })
1497
- );
1498
- nextScripts.forEach(([scriptSrc, props]) => {
1499
- const script = document.createElement("script");
1500
- if (scriptSrc) {
1501
- script.src = scriptSrc;
1502
- }
1503
- if (typeof props.children === "string") {
1504
- script.textContent = props.children;
1505
- }
1506
- setAttributesFromProps(script, props);
1507
- document.head.appendChild(script);
1508
- });
1509
- self.__next_s = prevNextScripts;
1622
+ });
1623
+ })
1624
+ );
1625
+ nextScripts.forEach(([scriptSrc, props]) => {
1626
+ const script = document.createElement("script");
1627
+ if (scriptSrc) {
1628
+ script.src = scriptSrc;
1629
+ }
1630
+ if (typeof props.children === "string") {
1631
+ script.textContent = props.children;
1632
+ }
1633
+ setAttributesFromProps(script, props);
1634
+ document.head.appendChild(script);
1635
+ });
1636
+ self.__next_s = prevNextScripts;
1637
+ }
1510
1638
  let rscName;
1511
1639
  if (rsc) {
1512
1640
  rscName = `__remote_component_rsc_${escapeString(url.href)}_${escapeString(remoteName)}`;
@@ -1523,7 +1651,11 @@ function RemoteComponent({
1523
1651
  url: url.href,
1524
1652
  data: rsc ? (rsc.textContent || "").split("\n").filter(Boolean) : []
1525
1653
  };
1526
- componentHydrationHtml.current = Array.from(doc.querySelectorAll("link,style")).map((link) => link.outerHTML).join("") + component.innerHTML;
1654
+ componentHydrationHtml.current = `${Array.from(
1655
+ doc.querySelectorAll("link,style")
1656
+ ).map((link) => link.outerHTML).join(
1657
+ ""
1658
+ )}${reset ? `<style data-remote-components-reset="">:host { all: initial; }</style>` : ""}${component.innerHTML}`;
1527
1659
  const userShared = await shared;
1528
1660
  if ("__remote_components_missing_shared__" in userShared) {
1529
1661
  userShared.__remote_components_missing_shared__().catch((e) => {
@@ -1534,48 +1666,89 @@ function RemoteComponent({
1534
1666
  remoteShared.__remote_components_missing_shared__
1535
1667
  );
1536
1668
  }
1537
- const result = await loadRemoteComponent({
1538
- url: new URL(url, location.origin),
1539
- name: remoteName,
1540
- rscName,
1541
- bundle,
1542
- route: metadata.route,
1543
- runtime: metadata.runtime,
1544
- data: newData.data,
1545
- nextData,
1546
- scripts: Array.from(scripts).map((script) => {
1547
- const scriptSrc = script.getAttribute("data-src") || script.getAttribute("src") || script.src;
1548
- const { prefix, id: path } = REMOTE_COMPONENT_REGEX.exec(
1549
- scriptSrc
1550
- )?.groups ?? {
1551
- prefix: void 0,
1552
- id: scriptSrc
1553
- };
1554
- return {
1555
- src: new URL(
1556
- `${prefix ?? ""}${path}`.replace(
1557
- /(?<char>[^:])(?<double>\/\/)/g,
1558
- "$1/"
1559
- ),
1560
- url
1561
- ).href
1562
- };
1563
- }),
1564
- shared: {
1565
- ...sharedPolyfills(userShared),
1566
- ...userShared
1567
- },
1568
- remoteShared,
1569
- container: shadowRoot
1570
- });
1571
- if (rsc) {
1572
- rsc.remove();
1573
- }
1574
- setData(newData);
1575
- if (result.error) {
1576
- setRemoteComponent(result.error);
1669
+ if (isRemoteComponent) {
1670
+ setData(newData);
1671
+ if (shadowRoot) {
1672
+ let shadowRootHtml = component.innerHTML;
1673
+ if (reset) {
1674
+ shadowRootHtml = `<style data-remote-components-reset="">:host { all: initial; }</style>${shadowRootHtml}`;
1675
+ }
1676
+ shadowRoot.innerHTML = shadowRootHtml;
1677
+ setRemoteComponent(null);
1678
+ const { mount, unmount } = await loadStaticRemoteComponent(
1679
+ Array.from(shadowRoot.querySelectorAll("script")),
1680
+ url
1681
+ );
1682
+ unmountRef.current = unmount;
1683
+ await Promise.all(
1684
+ Array.from(mount).map((mountFn) => mountFn(shadowRoot))
1685
+ );
1686
+ } else if (isolate === false) {
1687
+ setRemoteComponent(
1688
+ // TODO: remove wrapper div by converting HTML to RSC or React tree
1689
+ /* @__PURE__ */ jsx2(
1690
+ "div",
1691
+ {
1692
+ dangerouslySetInnerHTML: { __html: component.innerHTML },
1693
+ ref: prevRemoteComponentContainerRef
1694
+ }
1695
+ )
1696
+ );
1697
+ const { mount, unmount } = await loadStaticRemoteComponent(
1698
+ Array.from(component.querySelectorAll("script")),
1699
+ url
1700
+ );
1701
+ unmountRef.current = unmount;
1702
+ await Promise.all(
1703
+ Array.from(mount).map(
1704
+ (mountFn) => mountFn(prevRemoteComponentContainerRef.current)
1705
+ )
1706
+ );
1707
+ }
1577
1708
  } else {
1578
- setRemoteComponent(result.component);
1709
+ const result = await loadRemoteComponent({
1710
+ url: new URL(url, location.origin),
1711
+ name: remoteName,
1712
+ rscName,
1713
+ bundle,
1714
+ route: metadata.route,
1715
+ runtime: metadata.runtime,
1716
+ data: newData.data,
1717
+ nextData,
1718
+ scripts: Array.from(scripts).map((script) => {
1719
+ const scriptSrc = script.getAttribute("data-src") || script.getAttribute("src") || script.src;
1720
+ const { prefix, id: path } = REMOTE_COMPONENT_REGEX.exec(
1721
+ scriptSrc
1722
+ )?.groups ?? {
1723
+ prefix: void 0,
1724
+ id: scriptSrc
1725
+ };
1726
+ return {
1727
+ src: new URL(
1728
+ `${prefix ?? ""}${path}`.replace(
1729
+ /(?<char>[^:])(?<double>\/\/)/g,
1730
+ "$1/"
1731
+ ),
1732
+ url
1733
+ ).href
1734
+ };
1735
+ }),
1736
+ shared: {
1737
+ ...sharedPolyfills(userShared),
1738
+ ...userShared
1739
+ },
1740
+ remoteShared,
1741
+ container: shadowRoot
1742
+ });
1743
+ if (rsc) {
1744
+ rsc.remove();
1745
+ }
1746
+ setData(newData);
1747
+ if (result.error) {
1748
+ setRemoteComponent(result.error);
1749
+ } else {
1750
+ setRemoteComponent(result.component);
1751
+ }
1579
1752
  }
1580
1753
  } catch (error) {
1581
1754
  setRemoteComponent(error);
@@ -1590,7 +1763,8 @@ function RemoteComponent({
1590
1763
  name,
1591
1764
  shared,
1592
1765
  shadowRoot,
1593
- additionalHeaders
1766
+ additionalHeaders,
1767
+ reset
1594
1768
  ]);
1595
1769
  if (remoteComponent instanceof Error) {
1596
1770
  throw remoteComponent;
@@ -1599,7 +1773,7 @@ function RemoteComponent({
1599
1773
  name: data?.name || name,
1600
1774
  bundle: data?.bundle || "default",
1601
1775
  route: data?.route || DEFAULT_ROUTE,
1602
- runtime: data?.runtime || RUNTIME_WEBPACK
1776
+ runtime: prevIsRemoteComponentRef.current ? RUNTIME_SCRIPT : data?.runtime || RUNTIME_WEBPACK
1603
1777
  }) });
1604
1778
  const resetStyle = reset ? /* @__PURE__ */ jsx2("style", { "data-remote-components-reset": "", children: `:host { all: initial; }` }) : null;
1605
1779
  const linksToRender = data?.links?.map((link) => /* @__PURE__ */ createElement2(
@@ -1618,6 +1792,24 @@ function RemoteComponent({
1618
1792
  if (componentHydrationHtml.current && shadowRoot && !shadowRoot.innerHTML) {
1619
1793
  shadowRoot.innerHTML = componentHydrationHtml.current;
1620
1794
  componentHydrationHtml.current = null;
1795
+ if (prevIsRemoteComponentRef.current) {
1796
+ loadStaticRemoteComponent(
1797
+ Array.from(shadowRoot.querySelectorAll("script")),
1798
+ url
1799
+ ).then(({ mount }) => {
1800
+ return Promise.all(
1801
+ Array.from(mount).map((mountFn) => mountFn(shadowRoot))
1802
+ );
1803
+ }).catch((e) => {
1804
+ const error = new RemoteComponentsError(
1805
+ `Error mounting remote component from "${url.href}"`,
1806
+ {
1807
+ cause: e
1808
+ }
1809
+ );
1810
+ setRemoteComponent(error);
1811
+ });
1812
+ }
1621
1813
  }
1622
1814
  if (isolate !== false) {
1623
1815
  const shadowRemoteComponentHtml = shadowRoot?.querySelector(`#__REMOTE_COMPONENT${name}`) ?? shadowRoot?.querySelector("div[data-bundle][data-route]");