remote-components 0.3.4 → 0.3.5

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 (42) hide show
  1. package/dist/host/html.cjs +471 -413
  2. package/dist/host/html.cjs.map +1 -1
  3. package/dist/host/html.js +471 -413
  4. package/dist/host/html.js.map +1 -1
  5. package/dist/host/nextjs/app/client-only.cjs +245 -131
  6. package/dist/host/nextjs/app/client-only.cjs.map +1 -1
  7. package/dist/host/nextjs/app/client-only.js +245 -131
  8. package/dist/host/nextjs/app/client-only.js.map +1 -1
  9. package/dist/host/nextjs/app.cjs +34 -2
  10. package/dist/host/nextjs/app.cjs.map +1 -1
  11. package/dist/host/nextjs/app.js +35 -3
  12. package/dist/host/nextjs/app.js.map +1 -1
  13. package/dist/host/react.cjs +245 -131
  14. package/dist/host/react.cjs.map +1 -1
  15. package/dist/host/react.js +245 -131
  16. package/dist/host/react.js.map +1 -1
  17. package/dist/internal/host/nextjs/app-client.cjs +38 -24
  18. package/dist/internal/host/nextjs/app-client.cjs.map +1 -1
  19. package/dist/internal/host/nextjs/app-client.js +38 -24
  20. package/dist/internal/host/nextjs/app-client.js.map +1 -1
  21. package/dist/internal/host/nextjs/remote-component-links.cjs +24 -13
  22. package/dist/internal/host/nextjs/remote-component-links.cjs.map +1 -1
  23. package/dist/internal/host/nextjs/remote-component-links.d.ts +3 -0
  24. package/dist/internal/host/nextjs/remote-component-links.js +24 -13
  25. package/dist/internal/host/nextjs/remote-component-links.js.map +1 -1
  26. package/dist/internal/host/shared/lifecycle.cjs +69 -0
  27. package/dist/internal/host/shared/lifecycle.cjs.map +1 -0
  28. package/dist/internal/host/shared/lifecycle.d.ts +34 -0
  29. package/dist/internal/host/shared/lifecycle.js +44 -0
  30. package/dist/internal/host/shared/lifecycle.js.map +1 -0
  31. package/dist/internal/host/shared/pipeline.cjs +222 -0
  32. package/dist/internal/host/shared/pipeline.cjs.map +1 -0
  33. package/dist/internal/host/shared/pipeline.d.ts +153 -0
  34. package/dist/internal/host/shared/pipeline.js +200 -0
  35. package/dist/internal/host/shared/pipeline.js.map +1 -0
  36. package/dist/internal/runtime/turbopack/patterns.cjs +1 -1
  37. package/dist/internal/runtime/turbopack/patterns.cjs.map +1 -1
  38. package/dist/internal/runtime/turbopack/patterns.js +1 -1
  39. package/dist/internal/runtime/turbopack/patterns.js.map +1 -1
  40. package/dist/internal/runtime/turbopack/remote-scope-setup.cjs.map +1 -1
  41. package/dist/internal/runtime/turbopack/remote-scope-setup.js.map +1 -1
  42. package/package.json +2 -2
@@ -24,8 +24,10 @@ module.exports = __toCommonJS(app_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_wrapper = require("remote-components/remote/defaults/wrapper");
26
26
  var import_react = require("react");
27
+ var import_react_dom = require("react-dom");
27
28
  var import_app_client = require("#internal/host/nextjs/app-client");
28
29
  var import_fetch_remote_component = require("#internal/host/server/fetch-remote-component");
30
+ var import_constants = require("#internal/runtime/constants");
29
31
  async function ConsumeRemoteComponent({
30
32
  src,
31
33
  name: nameProp,
@@ -74,10 +76,40 @@ async function ConsumeRemoteComponent({
74
76
  children: component
75
77
  }
76
78
  );
79
+ const preloadHints = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChunkPreloadHints, { scripts, runtime });
77
80
  if (import_react.Children.count(children) > 0) {
78
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Suspense, { fallback: children, children: remoteComponentClient });
81
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Suspense, { fallback: children, children: [
82
+ preloadHints,
83
+ remoteComponentClient
84
+ ] });
79
85
  }
80
- return remoteComponentClient;
86
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
87
+ preloadHints,
88
+ remoteComponentClient
89
+ ] });
90
+ }
91
+ function ChunkPreloadHints({
92
+ scripts,
93
+ runtime
94
+ }) {
95
+ const scriptsWithSrc = scripts.filter((script) => script.src);
96
+ const as = runtime === import_constants.RUNTIME_TURBOPACK ? "fetch" : "script";
97
+ if (typeof import_react_dom.preload === "function") {
98
+ for (const script of scriptsWithSrc) {
99
+ (0, import_react_dom.preload)(script.src, { as, crossOrigin: "anonymous" });
100
+ }
101
+ return null;
102
+ }
103
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: scriptsWithSrc.map((script) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
104
+ "link",
105
+ {
106
+ rel: "preload",
107
+ href: script.src,
108
+ as,
109
+ crossOrigin: "anonymous"
110
+ },
111
+ script.src
112
+ )) });
81
113
  }
82
114
  // Annotate the CommonJS export names for ESM import in node:
83
115
  0 && (module.exports = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/host/nextjs/app.tsx"],"sourcesContent":["import 'remote-components/remote/defaults/wrapper';\nimport { Children, Suspense } from 'react';\nimport { ConsumeRemoteComponentClient } from '#internal/host/nextjs/app-client';\nimport { fetchRemoteComponent } from '#internal/host/server/fetch-remote-component';\nimport type { ConsumeServerConfig } from '#internal/host/shared/config';\n\n/**\n * Props for the Next.js App Router remote component host (server component).\n */\nexport interface ConsumeRemoteComponentProps extends ConsumeServerConfig {\n /** The source URL of the remote component. Required for server rendering. */\n src: string | URL;\n /** Loading fallback content to display while the remote component is being fetched. */\n children?: React.ReactNode;\n}\n\n/**\n * Next.js App Router server component that fetches and renders a remote component.\n * Props are documented on {@link ConsumeRemoteComponentProps} (extends {@link ConsumeServerConfig}).\n *\n * @example\n * ```tsx\n * import { ConsumeRemoteComponent } from 'remote-components/host/nextjs/app';\n *\n * export default function MyPage() {\n * return <ConsumeRemoteComponent src=\"/nextjs-app-remote/components/header\" />;\n * }\n * ```\n */\nexport async function ConsumeRemoteComponent({\n src,\n name: nameProp,\n isolate,\n mode,\n reset,\n children,\n onRequest,\n onResponse,\n}: ConsumeRemoteComponentProps): Promise<React.ReactElement> {\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n serverUrl,\n } = await fetchRemoteComponent(src, {\n name: nameProp,\n rsc: true,\n appRouter: true,\n onRequest,\n onResponse,\n });\n\n const { name, bundle, route, runtime, type } = metadata;\n const remoteComponentClient = (\n <ConsumeRemoteComponentClient\n bundle={bundle}\n data={hydrationData}\n isolate={isolate}\n links={links}\n mode={mode}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n reset={reset}\n route={route}\n runtime={runtime}\n scripts={scripts}\n type={type}\n src={typeof src === 'string' ? src : src.href}\n serverUrl={serverUrl.href}\n >\n {component}\n </ConsumeRemoteComponentClient>\n );\n\n if (Children.count(children) > 0) {\n // if there are children, render them inside the remote component\n return <Suspense fallback={children}>{remoteComponentClient}</Suspense>;\n }\n\n return remoteComponentClient;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0DI;AA1DJ,qBAAO;AACP,mBAAmC;AACnC,wBAA6C;AAC7C,oCAAqC;AA0BrC,eAAsB,uBAAuB;AAAA,EAC3C;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA6D;AAC3D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,UAAM,oDAAqB,KAAK;AAAA,IAClC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,EAAE,MAAM,QAAQ,OAAO,SAAS,KAAK,IAAI;AAC/C,QAAM,wBACJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,OAAO,QAAQ,WAAW,MAAM,IAAI;AAAA,MACzC,WAAW,UAAU;AAAA,MAEpB;AAAA;AAAA,EACH;AAGF,MAAI,sBAAS,MAAM,QAAQ,IAAI,GAAG;AAEhC,WAAO,4CAAC,yBAAS,UAAU,UAAW,iCAAsB;AAAA,EAC9D;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/host/nextjs/app.tsx"],"sourcesContent":["import 'remote-components/remote/defaults/wrapper';\nimport { Children, Suspense } from 'react';\nimport { preload as reactDomPreload } from 'react-dom';\nimport { ConsumeRemoteComponentClient } from '#internal/host/nextjs/app-client';\nimport { fetchRemoteComponent } from '#internal/host/server/fetch-remote-component';\nimport type { ScriptDescriptor } from '#internal/host/shared/asset-descriptors';\nimport type { ConsumeServerConfig } from '#internal/host/shared/config';\nimport { RUNTIME_TURBOPACK } from '#internal/runtime/constants';\n\n/**\n * Props for the Next.js App Router remote component host (server component).\n */\nexport interface ConsumeRemoteComponentProps extends ConsumeServerConfig {\n /** The source URL of the remote component. Required for server rendering. */\n src: string | URL;\n /** Loading fallback content to display while the remote component is being fetched. */\n children?: React.ReactNode;\n}\n\n/**\n * Next.js App Router server component that fetches and renders a remote component.\n * Props are documented on {@link ConsumeRemoteComponentProps} (extends {@link ConsumeServerConfig}).\n *\n * @example\n * ```tsx\n * import { ConsumeRemoteComponent } from 'remote-components/host/nextjs/app';\n *\n * export default function MyPage() {\n * return <ConsumeRemoteComponent src=\"/nextjs-app-remote/components/header\" />;\n * }\n * ```\n */\nexport async function ConsumeRemoteComponent({\n src,\n name: nameProp,\n isolate,\n mode,\n reset,\n children,\n onRequest,\n onResponse,\n}: ConsumeRemoteComponentProps): Promise<React.ReactElement> {\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n serverUrl,\n } = await fetchRemoteComponent(src, {\n name: nameProp,\n rsc: true,\n appRouter: true,\n onRequest,\n onResponse,\n });\n\n const { name, bundle, route, runtime, type } = metadata;\n const remoteComponentClient = (\n <ConsumeRemoteComponentClient\n bundle={bundle}\n data={hydrationData}\n isolate={isolate}\n links={links}\n mode={mode}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n reset={reset}\n route={route}\n runtime={runtime}\n scripts={scripts}\n type={type}\n src={typeof src === 'string' ? src : src.href}\n serverUrl={serverUrl.href}\n >\n {component}\n </ConsumeRemoteComponentClient>\n );\n\n const preloadHints = (\n <ChunkPreloadHints scripts={scripts} runtime={runtime} />\n );\n\n if (Children.count(children) > 0) {\n return (\n <Suspense fallback={children}>\n {preloadHints}\n {remoteComponentClient}\n </Suspense>\n );\n }\n\n return (\n <>\n {preloadHints}\n {remoteComponentClient}\n </>\n );\n}\n\n/**\n * Emits preload hints for chunk scripts so the browser starts fetching them\n * during HTML parsing, before any client JS executes. Uses the React DOM\n * `preload()` API when available, falling back to `<link rel=\"preload\">`.\n *\n * Preload hints use the direct asset URLs — if the client rewrites URLs\n * (e.g. through a proxy via `resolveClientUrl`), the preloads won't\n * cache-match but fail silently and cause no harm.\n */\nfunction ChunkPreloadHints({\n scripts,\n runtime,\n}: {\n scripts: ScriptDescriptor[];\n runtime: string | undefined;\n}) {\n const scriptsWithSrc = scripts.filter((script) => script.src);\n // Turbopack loads chunks via fetch() rather than <script> tags\n const as = runtime === RUNTIME_TURBOPACK ? 'fetch' : 'script';\n\n if (typeof reactDomPreload === 'function') {\n for (const script of scriptsWithSrc) {\n reactDomPreload(script.src, { as, crossOrigin: 'anonymous' });\n }\n return null;\n }\n\n return (\n <>\n {scriptsWithSrc.map((script) => (\n <link\n key={script.src}\n rel=\"preload\"\n href={script.src}\n as={as}\n crossOrigin=\"anonymous\"\n />\n ))}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA6DI;AA7DJ,qBAAO;AACP,mBAAmC;AACnC,uBAA2C;AAC3C,wBAA6C;AAC7C,oCAAqC;AAGrC,uBAAkC;AAyBlC,eAAsB,uBAAuB;AAAA,EAC3C;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA6D;AAC3D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,UAAM,oDAAqB,KAAK;AAAA,IAClC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,EAAE,MAAM,QAAQ,OAAO,SAAS,KAAK,IAAI;AAC/C,QAAM,wBACJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,OAAO,QAAQ,WAAW,MAAM,IAAI;AAAA,MACzC,WAAW,UAAU;AAAA,MAEpB;AAAA;AAAA,EACH;AAGF,QAAM,eACJ,4CAAC,qBAAkB,SAAkB,SAAkB;AAGzD,MAAI,sBAAS,MAAM,QAAQ,IAAI,GAAG;AAChC,WACE,6CAAC,yBAAS,UAAU,UACjB;AAAA;AAAA,MACA;AAAA,OACH;AAAA,EAEJ;AAEA,SACE,4EACG;AAAA;AAAA,IACA;AAAA,KACH;AAEJ;AAWA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AACF,GAGG;AACD,QAAM,iBAAiB,QAAQ,OAAO,CAAC,WAAW,OAAO,GAAG;AAE5D,QAAM,KAAK,YAAY,qCAAoB,UAAU;AAErD,MAAI,OAAO,iBAAAA,YAAoB,YAAY;AACzC,eAAW,UAAU,gBAAgB;AACnC,2BAAAA,SAAgB,OAAO,KAAK,EAAE,IAAI,aAAa,YAAY,CAAC;AAAA,IAC9D;AACA,WAAO;AAAA,EACT;AAEA,SACE,2EACG,yBAAe,IAAI,CAAC,WACnB;AAAA,IAAC;AAAA;AAAA,MAEC,KAAI;AAAA,MACJ,MAAM,OAAO;AAAA,MACb;AAAA,MACA,aAAY;AAAA;AAAA,IAJP,OAAO;AAAA,EAKd,CACD,GACH;AAEJ;","names":["reactDomPreload"]}
@@ -1,8 +1,10 @@
1
- import { jsx } from "react/jsx-runtime";
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import "remote-components/remote/defaults/wrapper";
3
3
  import { Children, Suspense } from "react";
4
+ import { preload as reactDomPreload } from "react-dom";
4
5
  import { ConsumeRemoteComponentClient } from "#internal/host/nextjs/app-client";
5
6
  import { fetchRemoteComponent } from "#internal/host/server/fetch-remote-component";
7
+ import { RUNTIME_TURBOPACK } from "#internal/runtime/constants";
6
8
  async function ConsumeRemoteComponent({
7
9
  src,
8
10
  name: nameProp,
@@ -51,10 +53,40 @@ async function ConsumeRemoteComponent({
51
53
  children: component
52
54
  }
53
55
  );
56
+ const preloadHints = /* @__PURE__ */ jsx(ChunkPreloadHints, { scripts, runtime });
54
57
  if (Children.count(children) > 0) {
55
- return /* @__PURE__ */ jsx(Suspense, { fallback: children, children: remoteComponentClient });
58
+ return /* @__PURE__ */ jsxs(Suspense, { fallback: children, children: [
59
+ preloadHints,
60
+ remoteComponentClient
61
+ ] });
56
62
  }
57
- return remoteComponentClient;
63
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
64
+ preloadHints,
65
+ remoteComponentClient
66
+ ] });
67
+ }
68
+ function ChunkPreloadHints({
69
+ scripts,
70
+ runtime
71
+ }) {
72
+ const scriptsWithSrc = scripts.filter((script) => script.src);
73
+ const as = runtime === RUNTIME_TURBOPACK ? "fetch" : "script";
74
+ if (typeof reactDomPreload === "function") {
75
+ for (const script of scriptsWithSrc) {
76
+ reactDomPreload(script.src, { as, crossOrigin: "anonymous" });
77
+ }
78
+ return null;
79
+ }
80
+ return /* @__PURE__ */ jsx(Fragment, { children: scriptsWithSrc.map((script) => /* @__PURE__ */ jsx(
81
+ "link",
82
+ {
83
+ rel: "preload",
84
+ href: script.src,
85
+ as,
86
+ crossOrigin: "anonymous"
87
+ },
88
+ script.src
89
+ )) });
58
90
  }
59
91
  export {
60
92
  ConsumeRemoteComponent
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/host/nextjs/app.tsx"],"sourcesContent":["import 'remote-components/remote/defaults/wrapper';\nimport { Children, Suspense } from 'react';\nimport { ConsumeRemoteComponentClient } from '#internal/host/nextjs/app-client';\nimport { fetchRemoteComponent } from '#internal/host/server/fetch-remote-component';\nimport type { ConsumeServerConfig } from '#internal/host/shared/config';\n\n/**\n * Props for the Next.js App Router remote component host (server component).\n */\nexport interface ConsumeRemoteComponentProps extends ConsumeServerConfig {\n /** The source URL of the remote component. Required for server rendering. */\n src: string | URL;\n /** Loading fallback content to display while the remote component is being fetched. */\n children?: React.ReactNode;\n}\n\n/**\n * Next.js App Router server component that fetches and renders a remote component.\n * Props are documented on {@link ConsumeRemoteComponentProps} (extends {@link ConsumeServerConfig}).\n *\n * @example\n * ```tsx\n * import { ConsumeRemoteComponent } from 'remote-components/host/nextjs/app';\n *\n * export default function MyPage() {\n * return <ConsumeRemoteComponent src=\"/nextjs-app-remote/components/header\" />;\n * }\n * ```\n */\nexport async function ConsumeRemoteComponent({\n src,\n name: nameProp,\n isolate,\n mode,\n reset,\n children,\n onRequest,\n onResponse,\n}: ConsumeRemoteComponentProps): Promise<React.ReactElement> {\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n serverUrl,\n } = await fetchRemoteComponent(src, {\n name: nameProp,\n rsc: true,\n appRouter: true,\n onRequest,\n onResponse,\n });\n\n const { name, bundle, route, runtime, type } = metadata;\n const remoteComponentClient = (\n <ConsumeRemoteComponentClient\n bundle={bundle}\n data={hydrationData}\n isolate={isolate}\n links={links}\n mode={mode}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n reset={reset}\n route={route}\n runtime={runtime}\n scripts={scripts}\n type={type}\n src={typeof src === 'string' ? src : src.href}\n serverUrl={serverUrl.href}\n >\n {component}\n </ConsumeRemoteComponentClient>\n );\n\n if (Children.count(children) > 0) {\n // if there are children, render them inside the remote component\n return <Suspense fallback={children}>{remoteComponentClient}</Suspense>;\n }\n\n return remoteComponentClient;\n}\n"],"mappings":"AA0DI;AA1DJ,OAAO;AACP,SAAS,UAAU,gBAAgB;AACnC,SAAS,oCAAoC;AAC7C,SAAS,4BAA4B;AA0BrC,eAAsB,uBAAuB;AAAA,EAC3C;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA6D;AAC3D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,MAAM,qBAAqB,KAAK;AAAA,IAClC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,EAAE,MAAM,QAAQ,OAAO,SAAS,KAAK,IAAI;AAC/C,QAAM,wBACJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,OAAO,QAAQ,WAAW,MAAM,IAAI;AAAA,MACzC,WAAW,UAAU;AAAA,MAEpB;AAAA;AAAA,EACH;AAGF,MAAI,SAAS,MAAM,QAAQ,IAAI,GAAG;AAEhC,WAAO,oBAAC,YAAS,UAAU,UAAW,iCAAsB;AAAA,EAC9D;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/host/nextjs/app.tsx"],"sourcesContent":["import 'remote-components/remote/defaults/wrapper';\nimport { Children, Suspense } from 'react';\nimport { preload as reactDomPreload } from 'react-dom';\nimport { ConsumeRemoteComponentClient } from '#internal/host/nextjs/app-client';\nimport { fetchRemoteComponent } from '#internal/host/server/fetch-remote-component';\nimport type { ScriptDescriptor } from '#internal/host/shared/asset-descriptors';\nimport type { ConsumeServerConfig } from '#internal/host/shared/config';\nimport { RUNTIME_TURBOPACK } from '#internal/runtime/constants';\n\n/**\n * Props for the Next.js App Router remote component host (server component).\n */\nexport interface ConsumeRemoteComponentProps extends ConsumeServerConfig {\n /** The source URL of the remote component. Required for server rendering. */\n src: string | URL;\n /** Loading fallback content to display while the remote component is being fetched. */\n children?: React.ReactNode;\n}\n\n/**\n * Next.js App Router server component that fetches and renders a remote component.\n * Props are documented on {@link ConsumeRemoteComponentProps} (extends {@link ConsumeServerConfig}).\n *\n * @example\n * ```tsx\n * import { ConsumeRemoteComponent } from 'remote-components/host/nextjs/app';\n *\n * export default function MyPage() {\n * return <ConsumeRemoteComponent src=\"/nextjs-app-remote/components/header\" />;\n * }\n * ```\n */\nexport async function ConsumeRemoteComponent({\n src,\n name: nameProp,\n isolate,\n mode,\n reset,\n children,\n onRequest,\n onResponse,\n}: ConsumeRemoteComponentProps): Promise<React.ReactElement> {\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n serverUrl,\n } = await fetchRemoteComponent(src, {\n name: nameProp,\n rsc: true,\n appRouter: true,\n onRequest,\n onResponse,\n });\n\n const { name, bundle, route, runtime, type } = metadata;\n const remoteComponentClient = (\n <ConsumeRemoteComponentClient\n bundle={bundle}\n data={hydrationData}\n isolate={isolate}\n links={links}\n mode={mode}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n reset={reset}\n route={route}\n runtime={runtime}\n scripts={scripts}\n type={type}\n src={typeof src === 'string' ? src : src.href}\n serverUrl={serverUrl.href}\n >\n {component}\n </ConsumeRemoteComponentClient>\n );\n\n const preloadHints = (\n <ChunkPreloadHints scripts={scripts} runtime={runtime} />\n );\n\n if (Children.count(children) > 0) {\n return (\n <Suspense fallback={children}>\n {preloadHints}\n {remoteComponentClient}\n </Suspense>\n );\n }\n\n return (\n <>\n {preloadHints}\n {remoteComponentClient}\n </>\n );\n}\n\n/**\n * Emits preload hints for chunk scripts so the browser starts fetching them\n * during HTML parsing, before any client JS executes. Uses the React DOM\n * `preload()` API when available, falling back to `<link rel=\"preload\">`.\n *\n * Preload hints use the direct asset URLs — if the client rewrites URLs\n * (e.g. through a proxy via `resolveClientUrl`), the preloads won't\n * cache-match but fail silently and cause no harm.\n */\nfunction ChunkPreloadHints({\n scripts,\n runtime,\n}: {\n scripts: ScriptDescriptor[];\n runtime: string | undefined;\n}) {\n const scriptsWithSrc = scripts.filter((script) => script.src);\n // Turbopack loads chunks via fetch() rather than <script> tags\n const as = runtime === RUNTIME_TURBOPACK ? 'fetch' : 'script';\n\n if (typeof reactDomPreload === 'function') {\n for (const script of scriptsWithSrc) {\n reactDomPreload(script.src, { as, crossOrigin: 'anonymous' });\n }\n return null;\n }\n\n return (\n <>\n {scriptsWithSrc.map((script) => (\n <link\n key={script.src}\n rel=\"preload\"\n href={script.src}\n as={as}\n crossOrigin=\"anonymous\"\n />\n ))}\n </>\n );\n}\n"],"mappings":"AA6DI,SAmCA,UAnCA,KA2BE,YA3BF;AA7DJ,OAAO;AACP,SAAS,UAAU,gBAAgB;AACnC,SAAS,WAAW,uBAAuB;AAC3C,SAAS,oCAAoC;AAC7C,SAAS,4BAA4B;AAGrC,SAAS,yBAAyB;AAyBlC,eAAsB,uBAAuB;AAAA,EAC3C;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA6D;AAC3D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,MAAM,qBAAqB,KAAK;AAAA,IAClC,MAAM;AAAA,IACN,KAAK;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,EAAE,MAAM,QAAQ,OAAO,SAAS,KAAK,IAAI;AAC/C,QAAM,wBACJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,OAAO,QAAQ,WAAW,MAAM,IAAI;AAAA,MACzC,WAAW,UAAU;AAAA,MAEpB;AAAA;AAAA,EACH;AAGF,QAAM,eACJ,oBAAC,qBAAkB,SAAkB,SAAkB;AAGzD,MAAI,SAAS,MAAM,QAAQ,IAAI,GAAG;AAChC,WACE,qBAAC,YAAS,UAAU,UACjB;AAAA;AAAA,MACA;AAAA,OACH;AAAA,EAEJ;AAEA,SACE,iCACG;AAAA;AAAA,IACA;AAAA,KACH;AAEJ;AAWA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AACF,GAGG;AACD,QAAM,iBAAiB,QAAQ,OAAO,CAAC,WAAW,OAAO,GAAG;AAE5D,QAAM,KAAK,YAAY,oBAAoB,UAAU;AAErD,MAAI,OAAO,oBAAoB,YAAY;AACzC,eAAW,UAAU,gBAAgB;AACnC,sBAAgB,OAAO,KAAK,EAAE,IAAI,aAAa,YAAY,CAAC;AAAA,IAC9D;AACA,WAAO;AAAA,EACT;AAEA,SACE,gCACG,yBAAe,IAAI,CAAC,WACnB;AAAA,IAAC;AAAA;AAAA,MAEC,KAAI;AAAA,MACJ,MAAM,OAAO;AAAA,MACb;AAAA,MACA,aAAY;AAAA;AAAA,IAJP,OAAO;AAAA,EAKd,CACD,GACH;AAEJ;","names":[]}
@@ -237,6 +237,24 @@ function getClientOrServerUrl(src, serverFallback) {
237
237
  return typeof src === "string" ? new URL(src, fallback) : src;
238
238
  }
239
239
 
240
+ // src/host/shared/lifecycle.ts
241
+ function makeReactEmitter(callbacks) {
242
+ return {
243
+ beforeLoad(src) {
244
+ callbacks.onBeforeLoad?.(src);
245
+ },
246
+ load(src) {
247
+ callbacks.onLoad?.(src);
248
+ },
249
+ error(error, _src) {
250
+ callbacks.onError?.(error);
251
+ },
252
+ change(info) {
253
+ callbacks.onChange?.(info);
254
+ }
255
+ };
256
+ }
257
+
240
258
  // src/utils/index.ts
241
259
  function escapeString(str) {
242
260
  return str.replace(/[^a-z0-9]/g, "_");
@@ -615,32 +633,6 @@ async function buildWebpackResolve(hostShared, remoteShared, bundle, reactModule
615
633
  return resolve;
616
634
  }
617
635
 
618
- // src/host/shared/state.ts
619
- function createHostState() {
620
- return {
621
- stage: "idle",
622
- prevSrc: void 0,
623
- prevUrl: void 0,
624
- prevName: void 0,
625
- prevIsRemoteComponent: false,
626
- abortController: void 0
627
- };
628
- }
629
-
630
- // src/host/utils/resolve-name-from-src.ts
631
- function resolveNameFromSrc(src, defaultName) {
632
- if (!src) {
633
- return defaultName;
634
- }
635
- const hash = typeof src === "string" ? src : src.hash;
636
- const hashIndex = hash.indexOf("#");
637
- if (hashIndex < 0) {
638
- return defaultName;
639
- }
640
- const name = hash.slice(hashIndex + 1);
641
- return name || defaultName;
642
- }
643
-
644
636
  // src/runtime/html/html-spec.ts
645
637
  var ORIGIN_REWRITE_TAGS = [
646
638
  "img",
@@ -843,48 +835,6 @@ function parseRemoteComponentDocument(doc, name, url) {
843
835
  };
844
836
  }
845
837
 
846
- // src/runtime/html/set-attributes-from-props.ts
847
- var DOMAttributeNames = {
848
- acceptCharset: "accept-charset",
849
- className: "class",
850
- htmlFor: "for",
851
- httpEquiv: "http-equiv",
852
- noModule: "noModule"
853
- };
854
- var ignoreProps = [
855
- "onLoad",
856
- "onReady",
857
- "dangerouslySetInnerHTML",
858
- "children",
859
- "onError",
860
- "strategy",
861
- "stylesheets"
862
- ];
863
- function isBooleanScriptAttribute(attr) {
864
- return ["async", "defer", "noModule"].includes(attr);
865
- }
866
- function setAttributesFromProps(el, props) {
867
- for (const [p, value] of Object.entries(props)) {
868
- if (!Object.hasOwn(props, p))
869
- continue;
870
- if (ignoreProps.includes(p))
871
- continue;
872
- if (value === void 0) {
873
- continue;
874
- }
875
- const attr = DOMAttributeNames[p] || p.toLowerCase();
876
- if (el.tagName === "SCRIPT" && isBooleanScriptAttribute(attr)) {
877
- el[attr] = Boolean(value);
878
- } else {
879
- el.setAttribute(attr, String(value));
880
- }
881
- if (value === false || el.tagName === "SCRIPT" && isBooleanScriptAttribute(attr) && (!value || value === "false")) {
882
- el.setAttribute(attr, "");
883
- el.removeAttribute(attr);
884
- }
885
- }
886
- }
887
-
888
838
  // src/runtime/loaders/component-loader.ts
889
839
  var React = __toESM(require("react"), 1);
890
840
  var JSXDevRuntime = __toESM(require("react/jsx-dev-runtime"), 1);
@@ -1165,7 +1115,7 @@ var REMOTE_SHARED_ASSIGNMENT_RE = new RegExp(
1165
1115
  `\\.TURBOPACK_REMOTE_SHARED\\s*=\\s*await (?:__turbopack_context__|[a-z])\\.A\\((?<sharedModuleId>${MODULE_ID_PATTERN})\\)`
1166
1116
  );
1167
1117
  var ASYNC_MODULE_LOADER_RE = new RegExp(
1168
- `(?:__turbopack_context__|e)\\.A\\((?<asyncSharedModuleId>${MODULE_ID_PATTERN})\\)`
1118
+ `(?:__turbopack_context__|[a-z])\\.A\\((?<asyncSharedModuleId>${MODULE_ID_PATTERN})\\)`
1169
1119
  );
1170
1120
  var ASYNC_MODULE_CALLBACK_RE = new RegExp(
1171
1121
  `(?:parentImport|[a-z])\\((?<sharedModuleId>${MODULE_ID_PATTERN})\\)`
@@ -2124,6 +2074,188 @@ async function loadStaticRemoteComponent(scripts, url, resolveClientUrl) {
2124
2074
  );
2125
2075
  }
2126
2076
 
2077
+ // src/host/shared/pipeline.ts
2078
+ function preparePipeline(input) {
2079
+ const parser = new DOMParser();
2080
+ const doc = parser.parseFromString(input.html, "text/html");
2081
+ const parsed = parseRemoteComponentDocument(doc, input.name, input.url);
2082
+ const remoteShared = input.remoteShared ?? parsed.remoteShared;
2083
+ if ("__remote_components_missing_shared__" in remoteShared) {
2084
+ throw new RemoteComponentsError(
2085
+ remoteShared.__remote_components_missing_shared__
2086
+ );
2087
+ }
2088
+ applyOriginToNodes(doc, input.url, input.resolveClientUrl);
2089
+ const scriptDescriptors = buildScriptDescriptors(parsed.scripts, input.url);
2090
+ return { doc, parsed, scriptDescriptors };
2091
+ }
2092
+ async function loadPrepared(input) {
2093
+ const { prepared, url, signal, resolveClientUrl, container, rscName } = input;
2094
+ const { doc, parsed, scriptDescriptors } = prepared;
2095
+ if (signal.aborted) {
2096
+ return { status: "aborted" };
2097
+ }
2098
+ const userShared = await input.shared;
2099
+ if (signal.aborted) {
2100
+ return { status: "aborted" };
2101
+ }
2102
+ if (parsed.isRemoteComponent) {
2103
+ return loadStaticPath({
2104
+ parsed,
2105
+ doc,
2106
+ url,
2107
+ resolveClientUrl
2108
+ });
2109
+ }
2110
+ return loadDynamicPath({
2111
+ parsed,
2112
+ doc,
2113
+ url,
2114
+ scriptDescriptors,
2115
+ shared: userShared,
2116
+ resolveClientUrl,
2117
+ container,
2118
+ rscName
2119
+ });
2120
+ }
2121
+ function buildScriptDescriptors(scripts, url) {
2122
+ return scripts.map((script) => {
2123
+ const scriptSrc = script.getAttribute("data-src") || script.getAttribute("src") || script.src;
2124
+ const { prefix, id: path } = REMOTE_COMPONENT_REGEX.exec(scriptSrc)?.groups ?? {
2125
+ prefix: void 0,
2126
+ id: scriptSrc
2127
+ };
2128
+ return {
2129
+ src: new URL(collapseDoubleSlashes(`${prefix ?? ""}${path}`), url).href
2130
+ };
2131
+ });
2132
+ }
2133
+ async function loadStaticPath(input) {
2134
+ const { parsed, doc, url, resolveClientUrl } = input;
2135
+ const scripts = Array.from(
2136
+ parsed.component.querySelectorAll("script")
2137
+ );
2138
+ const { mount, unmount } = await loadStaticRemoteComponent(
2139
+ scripts,
2140
+ url,
2141
+ resolveClientUrl
2142
+ );
2143
+ return {
2144
+ status: "static",
2145
+ mount,
2146
+ unmount,
2147
+ metadata: parsed.metadata,
2148
+ parsed,
2149
+ doc
2150
+ };
2151
+ }
2152
+ async function loadDynamicPath(input) {
2153
+ const {
2154
+ parsed,
2155
+ doc,
2156
+ url,
2157
+ scriptDescriptors,
2158
+ shared,
2159
+ resolveClientUrl,
2160
+ container
2161
+ } = input;
2162
+ const rscName = input.rscName ?? (parsed.rsc ? `__remote_component_rsc_${escapeString(url.href)}_${escapeString(parsed.name)}` : void 0);
2163
+ const rscData = parsed.rsc ? (parsed.rsc.textContent || "").split("\n").filter(Boolean) : [];
2164
+ const result = await loadRemoteComponent({
2165
+ url,
2166
+ name: parsed.name,
2167
+ rscName,
2168
+ bundle: parsed.metadata.bundle,
2169
+ route: parsed.metadata.route,
2170
+ runtime: parsed.metadata.runtime,
2171
+ data: rscData,
2172
+ nextData: parsed.nextData,
2173
+ scripts: scriptDescriptors,
2174
+ shared: buildHostShared(shared, resolveClientUrl),
2175
+ remoteShared: parsed.remoteShared,
2176
+ container,
2177
+ resolveClientUrl
2178
+ });
2179
+ if (result.error) {
2180
+ return { status: "error", error: result.error };
2181
+ }
2182
+ return {
2183
+ status: "loaded",
2184
+ component: result.component,
2185
+ metadata: parsed.metadata,
2186
+ parsed,
2187
+ doc
2188
+ };
2189
+ }
2190
+
2191
+ // src/host/shared/state.ts
2192
+ function createHostState() {
2193
+ return {
2194
+ stage: "idle",
2195
+ prevSrc: void 0,
2196
+ prevUrl: void 0,
2197
+ prevName: void 0,
2198
+ prevIsRemoteComponent: false,
2199
+ abortController: void 0
2200
+ };
2201
+ }
2202
+
2203
+ // src/host/utils/resolve-name-from-src.ts
2204
+ function resolveNameFromSrc(src, defaultName) {
2205
+ if (!src) {
2206
+ return defaultName;
2207
+ }
2208
+ const hash = typeof src === "string" ? src : src.hash;
2209
+ const hashIndex = hash.indexOf("#");
2210
+ if (hashIndex < 0) {
2211
+ return defaultName;
2212
+ }
2213
+ const name = hash.slice(hashIndex + 1);
2214
+ return name || defaultName;
2215
+ }
2216
+
2217
+ // src/runtime/html/set-attributes-from-props.ts
2218
+ var DOMAttributeNames = {
2219
+ acceptCharset: "accept-charset",
2220
+ className: "class",
2221
+ htmlFor: "for",
2222
+ httpEquiv: "http-equiv",
2223
+ noModule: "noModule"
2224
+ };
2225
+ var ignoreProps = [
2226
+ "onLoad",
2227
+ "onReady",
2228
+ "dangerouslySetInnerHTML",
2229
+ "children",
2230
+ "onError",
2231
+ "strategy",
2232
+ "stylesheets"
2233
+ ];
2234
+ function isBooleanScriptAttribute(attr) {
2235
+ return ["async", "defer", "noModule"].includes(attr);
2236
+ }
2237
+ function setAttributesFromProps(el, props) {
2238
+ for (const [p, value] of Object.entries(props)) {
2239
+ if (!Object.hasOwn(props, p))
2240
+ continue;
2241
+ if (ignoreProps.includes(p))
2242
+ continue;
2243
+ if (value === void 0) {
2244
+ continue;
2245
+ }
2246
+ const attr = DOMAttributeNames[p] || p.toLowerCase();
2247
+ if (el.tagName === "SCRIPT" && isBooleanScriptAttribute(attr)) {
2248
+ el[attr] = Boolean(value);
2249
+ } else {
2250
+ el.setAttribute(attr, String(value));
2251
+ }
2252
+ if (value === false || el.tagName === "SCRIPT" && isBooleanScriptAttribute(attr) && (!value || value === "false")) {
2253
+ el.setAttribute(attr, "");
2254
+ el.removeAttribute(attr);
2255
+ }
2256
+ }
2257
+ }
2258
+
2127
2259
  // src/host/react/hooks/use-resolve-client-url.ts
2128
2260
  var import_react = require("react");
2129
2261
  var import_context = require("#internal/host/react/context");
@@ -2253,6 +2385,10 @@ function ConsumeRemoteComponent({
2253
2385
  const { credentials: contextCredentials, shared: contextShared } = (0, import_context2.useRemoteComponentsContext)();
2254
2386
  const credentials = credentialsProp ?? contextCredentials ?? "same-origin";
2255
2387
  const shared = sharedProp ?? contextShared ?? {};
2388
+ const emitter = (0, import_react3.useMemo)(
2389
+ () => makeReactEmitter({ onBeforeLoad, onLoad, onError, onChange }),
2390
+ [onBeforeLoad, onLoad, onError, onChange]
2391
+ );
2256
2392
  const name = (0, import_react3.useMemo)(
2257
2393
  () => resolveNameFromSrc(src, nameProp),
2258
2394
  [src, nameProp]
@@ -2342,7 +2478,7 @@ function ConsumeRemoteComponent({
2342
2478
  hostStateRef.current.abortController?.abort();
2343
2479
  hostStateRef.current.abortController = new AbortController();
2344
2480
  const { signal } = hostStateRef.current.abortController;
2345
- onBeforeLoad?.(src);
2481
+ emitter.beforeLoad(src);
2346
2482
  hostStateRef.current.stage = "loading";
2347
2483
  (0, import_react3.startTransition)(async () => {
2348
2484
  try {
@@ -2373,19 +2509,26 @@ function ConsumeRemoteComponent({
2373
2509
  }
2374
2510
  if (signal.aborted)
2375
2511
  return;
2376
- const parser = new DOMParser();
2377
- const doc = parser.parseFromString(html, "text/html");
2512
+ const userShared = await shared;
2513
+ if (signal.aborted)
2514
+ return;
2515
+ const prepared = preparePipeline({
2516
+ html,
2517
+ name,
2518
+ url,
2519
+ shared: userShared,
2520
+ resolveClientUrl
2521
+ });
2522
+ const { doc, parsed } = prepared;
2378
2523
  const {
2379
2524
  component,
2380
2525
  name: remoteName,
2381
2526
  isRemoteComponent,
2382
2527
  metadata,
2383
- nextData,
2384
2528
  rsc,
2385
2529
  remoteShared,
2386
- links: linkElements,
2387
- scripts: scriptElements
2388
- } = parseRemoteComponentDocument(doc, name, url);
2530
+ links: linkElements
2531
+ } = parsed;
2389
2532
  if (hostStateRef.current.prevIsRemoteComponent) {
2390
2533
  if (shadowRoot) {
2391
2534
  shadowRoot.innerHTML = "";
@@ -2406,7 +2549,6 @@ function ConsumeRemoteComponent({
2406
2549
  hostStateRef.current.prevIsRemoteComponent = isRemoteComponent;
2407
2550
  hostStateRef.current.prevUrl = url;
2408
2551
  hostStateRef.current.prevName = remoteName;
2409
- applyOriginToNodes(doc, url, resolveClientUrl);
2410
2552
  const links = linkElements.map((link) => ({
2411
2553
  href: new URL(link.getAttribute("href") ?? link.href, url).href,
2412
2554
  ...link.getAttributeNames().reduce((acc, key) => {
@@ -2416,7 +2558,6 @@ function ConsumeRemoteComponent({
2416
2558
  return acc;
2417
2559
  }, {})
2418
2560
  }));
2419
- const scripts = scriptElements;
2420
2561
  const inlineScripts = (isRemoteComponent ? component : doc).querySelectorAll(
2421
2562
  "script:not([src]):not([data-src]):not([id*='_rsc']):not([id='__NEXT_DATA__']):not([id='__REMOTE_NEXT_DATA__'])"
2422
2563
  );
@@ -2495,20 +2636,10 @@ function ConsumeRemoteComponent({
2495
2636
  componentHydrationHtml.current = `${Array.from(
2496
2637
  doc.querySelectorAll("link,style")
2497
2638
  ).map((link) => link.outerHTML).join("")}${reset ? `<style data-remote-components-reset="">:host { all: initial; }</style>` : ""}${component.innerHTML}`;
2498
- const userShared = await shared;
2499
- if ("__remote_components_missing_shared__" in userShared) {
2500
- userShared.__remote_components_missing_shared__().catch((e) => {
2501
- throw e;
2502
- });
2503
- } else if ("__remote_components_missing_shared__" in remoteShared) {
2504
- throw new RemoteComponentsError(
2505
- remoteShared.__remote_components_missing_shared__
2506
- );
2507
- }
2508
2639
  if (isRemoteComponent) {
2509
2640
  if (previousSrc !== void 0) {
2510
- onChange?.({
2511
- previousSrc,
2641
+ emitter.change({
2642
+ previousSrc: previousSrc ?? null,
2512
2643
  nextSrc: src,
2513
2644
  previousName,
2514
2645
  nextName: remoteName
@@ -2529,7 +2660,7 @@ function ConsumeRemoteComponent({
2529
2660
  await Promise.all(
2530
2661
  Array.from(mount).map((mountFn) => mountFn(shadowRoot))
2531
2662
  );
2532
- onLoad?.(src);
2663
+ emitter.load(src);
2533
2664
  } else if (isolate === false) {
2534
2665
  setRemoteComponent(
2535
2666
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -2552,59 +2683,42 @@ function ConsumeRemoteComponent({
2552
2683
  (mountFn) => mountFn(prevRemoteComponentContainerRef.current)
2553
2684
  )
2554
2685
  );
2555
- onLoad?.(src);
2686
+ emitter.load(src);
2556
2687
  }
2557
2688
  hostStateRef.current.stage = "loaded";
2558
2689
  } else {
2559
- const result = await loadRemoteComponent({
2690
+ const result = await loadPrepared({
2691
+ prepared,
2560
2692
  url,
2561
- name: remoteName,
2562
- rscName,
2563
- bundle: metadata.bundle,
2564
- route: metadata.route,
2565
- runtime: metadata.runtime,
2566
- data: newData.data,
2567
- nextData,
2568
- scripts: Array.from(scripts).map((script) => {
2569
- const scriptSrc = script.getAttribute("data-src") || script.getAttribute("src") || script.src;
2570
- const { prefix, id: path } = REMOTE_COMPONENT_REGEX.exec(
2571
- scriptSrc
2572
- )?.groups ?? {
2573
- prefix: void 0,
2574
- id: scriptSrc
2575
- };
2576
- return {
2577
- src: new URL(
2578
- collapseDoubleSlashes(`${prefix ?? ""}${path}`),
2579
- url
2580
- ).href
2581
- };
2582
- }),
2583
- shared: buildHostShared(userShared, resolveClientUrl),
2584
- remoteShared,
2693
+ signal,
2694
+ shared: userShared,
2695
+ resolveClientUrl,
2585
2696
  container: shadowRoot,
2586
- resolveClientUrl
2697
+ rscName
2587
2698
  });
2588
2699
  if (rsc) {
2589
2700
  rsc.remove();
2590
2701
  }
2591
2702
  setData(newData);
2592
2703
  if (previousSrc !== void 0) {
2593
- onChange?.({
2594
- previousSrc,
2704
+ emitter.change({
2705
+ previousSrc: previousSrc ?? null,
2595
2706
  nextSrc: src,
2596
2707
  previousName,
2597
2708
  nextName: remoteName
2598
2709
  });
2599
2710
  }
2600
- if (result.error) {
2711
+ if (result.status === "aborted") {
2712
+ return;
2713
+ }
2714
+ if (result.status === "error") {
2601
2715
  hostStateRef.current.stage = "error";
2602
2716
  setRemoteComponent(result.error);
2603
- onError?.(result.error);
2604
- } else {
2717
+ emitter.error(result.error);
2718
+ } else if (result.status === "loaded") {
2605
2719
  hostStateRef.current.stage = "loaded";
2606
2720
  setRemoteComponent(result.component);
2607
- onLoad?.(src);
2721
+ emitter.load(src);
2608
2722
  }
2609
2723
  }
2610
2724
  } catch (error) {
@@ -2614,7 +2728,7 @@ function ConsumeRemoteComponent({
2614
2728
  }
2615
2729
  hostStateRef.current.stage = "error";
2616
2730
  setRemoteComponent(error);
2617
- onError?.(error);
2731
+ emitter.error(error);
2618
2732
  }
2619
2733
  });
2620
2734
  }
@@ -2628,10 +2742,10 @@ function ConsumeRemoteComponent({
2628
2742
  shadowRoot,
2629
2743
  reset,
2630
2744
  id,
2631
- onBeforeLoad,
2632
- onLoad,
2633
- onError,
2634
- onChange,
2745
+ emitter.beforeLoad,
2746
+ emitter.load,
2747
+ emitter.error,
2748
+ emitter.change,
2635
2749
  onRequest,
2636
2750
  onResponse,
2637
2751
  resolveClientUrl
@@ -2673,7 +2787,7 @@ function ConsumeRemoteComponent({
2673
2787
  );
2674
2788
  }).then(() => {
2675
2789
  if (src) {
2676
- onLoad?.(src);
2790
+ emitter.load(src);
2677
2791
  }
2678
2792
  }).catch((e) => {
2679
2793
  const error = new RemoteComponentsError(
@@ -2683,7 +2797,7 @@ function ConsumeRemoteComponent({
2683
2797
  }
2684
2798
  );
2685
2799
  setRemoteComponent(error);
2686
- onError?.(error);
2800
+ emitter.error(error);
2687
2801
  });
2688
2802
  }
2689
2803
  }