remote-components 0.0.36 → 0.0.37

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 (38) hide show
  1. package/dist/{component-loader-8951c052.d.ts → component-loader-2ca91ad8.d.ts} +4 -1
  2. package/dist/internal/next/host/app-router-client.cjs +51 -38
  3. package/dist/internal/next/host/app-router-client.cjs.map +1 -1
  4. package/dist/internal/next/host/app-router-client.d.ts +2 -2
  5. package/dist/internal/next/host/app-router-client.js +51 -38
  6. package/dist/internal/next/host/app-router-client.js.map +1 -1
  7. package/dist/internal/shared/client/remote-component.d.ts +2 -2
  8. package/dist/internal/shared/ssr/fetch-remote-component.cjs +14 -14
  9. package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
  10. package/dist/internal/shared/ssr/fetch-remote-component.d.ts +1 -1
  11. package/dist/internal/shared/ssr/fetch-remote-component.js +14 -14
  12. package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
  13. package/dist/internal/shared/ssr/get-client-or-server-url.cjs +35 -0
  14. package/dist/internal/shared/ssr/get-client-or-server-url.cjs.map +1 -0
  15. package/dist/internal/shared/ssr/get-client-or-server-url.d.ts +3 -0
  16. package/dist/internal/shared/ssr/get-client-or-server-url.js +11 -0
  17. package/dist/internal/shared/ssr/get-client-or-server-url.js.map +1 -0
  18. package/dist/next/host/app-router-server.cjs +3 -2
  19. package/dist/next/host/app-router-server.cjs.map +1 -1
  20. package/dist/next/host/app-router-server.js +3 -2
  21. package/dist/next/host/app-router-server.js.map +1 -1
  22. package/dist/next/host/client/index.cjs +31 -27
  23. package/dist/next/host/client/index.cjs.map +1 -1
  24. package/dist/next/host/client/index.d.ts +1 -1
  25. package/dist/next/host/client/index.js +31 -27
  26. package/dist/next/host/client/index.js.map +1 -1
  27. package/dist/next/host/pages-router-server.cjs +4 -8
  28. package/dist/next/host/pages-router-server.cjs.map +1 -1
  29. package/dist/next/host/pages-router-server.d.ts +0 -1
  30. package/dist/next/host/pages-router-server.js +4 -8
  31. package/dist/next/host/pages-router-server.js.map +1 -1
  32. package/dist/react/index.cjs +23 -27
  33. package/dist/react/index.cjs.map +1 -1
  34. package/dist/react/index.d.ts +1 -1
  35. package/dist/react/index.js +23 -27
  36. package/dist/react/index.js.map +1 -1
  37. package/dist/{types-4e7dea94.d.ts → types-235b68a5.d.ts} +4 -1
  38. package/package.json +1 -1
@@ -145,7 +145,7 @@ function RemoteComponent(props) {
145
145
  name: props.name,
146
146
  reset: props.reset,
147
147
  shared: shared(props.bundle ?? "default"),
148
- src: props.url ?? props.src,
148
+ src: props.src,
149
149
  children: props.children
150
150
  }
151
151
  );
@@ -159,7 +159,7 @@ function RemoteComponent(props) {
159
159
  name: props.name,
160
160
  reset: props.reset,
161
161
  shared: shared(props.bundle ?? "default"),
162
- src: props.url ?? props.src,
162
+ src: props.src,
163
163
  children: remoteComponent
164
164
  }
165
165
  );
@@ -171,12 +171,11 @@ async function getRemoteComponentProps(src, headers) {
171
171
  );
172
172
  }
173
173
  const {
174
- metadata: { bundle, route, runtime },
174
+ metadata: { bundle, route },
175
175
  name,
176
176
  links,
177
177
  component,
178
178
  nextData,
179
- url,
180
179
  remoteShared
181
180
  } = await (0, import_fetch_remote_component.fetchRemoteComponent)(
182
181
  src,
@@ -201,10 +200,7 @@ async function getRemoteComponentProps(src, headers) {
201
200
  src,
202
201
  bundle,
203
202
  name,
204
- route,
205
- runtime,
206
- buildId: nextData?.buildId ?? null,
207
- url: url.href
203
+ route
208
204
  };
209
205
  const key = getKey(props);
210
206
  if (nextData?.buildId !== "development") {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/next/host/pages-router-server.tsx"],"sourcesContent":["import type { IncomingHttpHeaders } from 'node:http';\nimport * as Form from 'next/form';\nimport * as Image from 'next/image';\nimport * as Link from 'next/link';\nimport * as Router from 'next/router';\nimport * as Script from 'next/script';\nimport { useEffect } from 'react';\nimport { shared as _shared } from 'remote-components/shared/host/pages';\nimport { RemoteComponentsError } from '#internal/shared/client/remote-component';\nimport { fetchRemoteComponent } from '#internal/shared/ssr/fetch-remote-component';\nimport { RemoteComponent as RemoteComponentReact } from '#remote-components/react/index';\n\nconst navigationImpl = {\n useRouter: () => Router.useRouter(),\n useSearchParams: () => {\n const router = Router.useRouter();\n return {\n get: (key: string) => router.query[key],\n has: (key: string) => key in router.query,\n };\n },\n};\n\nconst sharedCache = new Map<string, Record<string, () => Promise<unknown>>>();\nconst shared = (bundle: string) => {\n if (sharedCache.has(bundle)) {\n return sharedCache.get(bundle);\n }\n\n const remoteLoader = ({ src, width, quality }: Image.ImageLoaderProps) => {\n const self = globalThis as typeof globalThis & {\n __remote_bundle_url__?: Record<string, URL>;\n };\n const { assetPrefix } =\n /^(?<assetPrefix>.*?)\\/_next\\//.exec(src)?.groups ?? {};\n return `${self.__remote_bundle_url__?.[bundle]?.origin ?? ''}${assetPrefix}/_next/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality || 75}`;\n };\n\n const imageImpl = (ImageComponent: typeof Image.default) => {\n function RemoteImage(props: Image.ImageProps) {\n return <ImageComponent loader={remoteLoader} {...props} />;\n }\n RemoteImage.default = RemoteImage;\n RemoteImage.getImageProps = Image.getImageProps;\n return RemoteImage;\n };\n\n return {\n // polyfill Next.js App Router client API (minimal)\n // some API methods are not available when using a Next.js Pages Router application as host\n 'next/navigation': () =>\n Promise.resolve(navigationImpl) as Promise<unknown>,\n 'next/dist/client/components/navigation': () =>\n Promise.resolve(navigationImpl) as Promise<unknown>,\n 'next/dist/client/app-dir/link': () =>\n Promise.resolve(Link.default) as Promise<unknown>,\n 'next/link': () => Promise.resolve(Link.default) as Promise<unknown>,\n 'next/dist/client/app-dir/form': () =>\n Promise.resolve(Form.default) as Promise<unknown>,\n 'next/form': () => Promise.resolve(Form.default) as Promise<unknown>,\n 'next/dist/client/script': () =>\n Promise.resolve(Script.default) as Promise<unknown>,\n 'next/script': () => Promise.resolve(Script.default) as Promise<unknown>,\n 'next/dist/client/image-component': () =>\n Promise.resolve({\n // @ts-expect-error default.default\n // eslint-disable-next-line\n Image: imageImpl(Image.default.default ?? Image.default),\n }) as Promise<unknown>,\n 'next/dist/api/image': () =>\n Promise.resolve({\n // @ts-expect-error default.default\n // eslint-disable-next-line\n default: imageImpl(Image.default.default ?? Image.default),\n getImageProps: Image.getImageProps,\n }) as Promise<unknown>,\n 'next/router': () => Promise.resolve(Router) as Promise<unknown>,\n ..._shared,\n // always override next/image to use the remote loader\n 'next/image': () =>\n Promise.resolve(\n // @ts-expect-error default.default\n // eslint-disable-next-line\n imageImpl(Image.default.default ?? Image.default),\n ) as Promise<unknown>,\n };\n};\n\n// internal symbols to access global store\nconst REMOTE_COMPONENT_STORE = Symbol('REMOTE_COMPONENT_STORE');\nconst REMOTE_COMPONENT_KEY = '__REMOTE_COMPONENT_KEY__';\n\n// temporary global store for remote component HTML\n// the store is used to save the HTML of remote components for SSR without sending the content to the client\nconst self = globalThis as typeof globalThis & {\n [REMOTE_COMPONENT_STORE]?: Map<string, React.ReactNode>;\n};\n\nfunction getKey({\n bundle,\n route,\n name,\n}: {\n bundle?: string;\n route?: string;\n name?: string;\n}): string {\n return `${bundle ?? '__next'}:${route ?? '/'}:${name ?? '__vercel_remote_component'}__${crypto.randomUUID()}`;\n}\n\nfunction setComponent(key: string, component: React.ReactNode): void {\n if (!self[REMOTE_COMPONENT_STORE]) {\n self[REMOTE_COMPONENT_STORE] = new Map();\n }\n self[REMOTE_COMPONENT_STORE].set(key, component);\n}\n\nfunction getComponent(key: string): React.ReactNode | undefined {\n const component = self[REMOTE_COMPONENT_STORE]?.get(key);\n // remove the component from the store after retrieving it to prevent memory leaks\n // storing the HTML in the global store is only needed for SSR and it's temporary only used for a single render\n self[REMOTE_COMPONENT_STORE]?.delete(key);\n return component;\n}\n\nexport interface RemoteComponentProps {\n src: string;\n url?: string | URL;\n bundle?: string;\n route?: string;\n name?: string;\n isolate?: boolean;\n mode?: 'open' | 'closed';\n reset?: boolean;\n additionalHeaders?: Headers | Record<string, string>;\n [REMOTE_COMPONENT_KEY]?: string;\n children?: React.ReactNode;\n}\n\n/**\n * This component handles the rendering of remote microfrontends.\n *\n * @param props - The properties for the remote component.\n * @returns A React component that renders the remote component.\n */\nexport function RemoteComponent(props: RemoteComponentProps) {\n const remoteComponent =\n typeof document !== 'undefined'\n ? null\n : // retrieve the HTML from the global store\n getComponent(\n props[REMOTE_COMPONENT_KEY] ?? '__vercel_remote_component',\n );\n\n useEffect(() => {\n const clientSelf = globalThis as typeof globalThis & {\n __remote_component_shared__?: Record<string, () => Promise<unknown>>;\n };\n // eslint-disable-next-line camelcase\n clientSelf.__remote_component_shared__ = shared(props.bundle ?? 'default');\n }, [props.bundle]);\n\n if (!props[REMOTE_COMPONENT_KEY]) {\n return (\n <RemoteComponentReact\n additionalHeaders={props.additionalHeaders}\n isolate={props.isolate}\n mode={props.mode}\n name={props.name}\n reset={props.reset}\n shared={shared(props.bundle ?? 'default')}\n src={props.url ?? props.src}\n >\n {props.children}\n </RemoteComponentReact>\n );\n }\n\n return (\n <RemoteComponentReact\n additionalHeaders={props.additionalHeaders}\n isolate={props.isolate}\n mode={props.mode}\n name={props.name}\n reset={props.reset}\n shared={shared(props.bundle ?? 'default')}\n src={props.url ?? props.src}\n >\n {remoteComponent}\n </RemoteComponentReact>\n );\n}\n\n/**\n * Fetches the remote component properties from the server. You need to pass these properties to the `<RemoteComponent>` component to render the fetched remote component.\n *\n * @param src - The source URL of the remote component. When using the Vercel Microfrontends solution, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param headers - The HTTP headers used for supporting the Vercel Microfrontends proxy.\n * @returns The properties of the remote component.\n *\n * @example\n *\n * ```tsx\n * import { getRemoteComponentProps } from 'remote-components/next/host/pages';\n * import type { GetServerSideProps } from 'next';\n *\n * export const getServerSideProps: GetServerSideProps<PageProps> = async function getServerSideProps({ req }) {\n * const myRemoteComponent = await getRemoteComponentProps(\n * '/nextjs-app-remote/components/header',\n * req.headers,\n * );\n * return {\n * props: {\n * remoteComponents: {\n * myRemoteComponent,\n * },\n * },\n * };\n * }\n * ```\n */\nexport async function getRemoteComponentProps(\n src: string,\n headers: IncomingHttpHeaders,\n): Promise<RemoteComponentProps> {\n if (typeof document !== 'undefined') {\n throw new RemoteComponentsError(\n '`getRemoteComponentProps()` can only be used on the server side.',\n );\n }\n\n const {\n metadata: { bundle, route, runtime },\n name,\n links,\n component,\n nextData,\n url,\n remoteShared,\n } = await fetchRemoteComponent(\n src,\n headers instanceof Headers\n ? headers\n : // convert IncomingHttpHeaders to web standard Headers\n Object.entries(headers).reduce((acc, [key, value]) => {\n if (value) {\n if (Array.isArray(value)) {\n value.forEach((v) => acc.append(key, v));\n } else {\n acc.append(key, value);\n }\n }\n return acc;\n }, new Headers()),\n {\n rsc: true,\n },\n );\n\n const props = {\n src,\n bundle,\n name,\n route,\n runtime,\n buildId: nextData?.buildId ?? null,\n url: url.href,\n };\n\n const key = getKey(props);\n\n // do not render the HTML in development mode when remote is using Next.js Pages Router\n // this behavior is emulating the Next.js Pages Router FOUC as the styles are only applied on the client when running in development mode\n if (nextData?.buildId !== 'development') {\n // store the HTML in a global store\n setComponent(\n key,\n <>\n <script\n data-remote-components-shared=\"\"\n id={`${name}_shared`}\n type=\"application/json\"\n >\n {JSON.stringify(remoteShared)}\n </script>\n {links.map((link) => (\n <link\n key={`${link.as}_${link.href}`}\n {...link}\n precedence={undefined}\n />\n ))}\n {component}\n </>,\n );\n }\n\n return {\n ...props,\n // add remote component key to the props\n [REMOTE_COMPONENT_KEY]: key,\n };\n}\n"],"mappings":"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","names":["import_react","self","_shared","RemoteComponentReact","key"]}
1
+ {"version":3,"sources":["../../../src/next/host/pages-router-server.tsx"],"sourcesContent":["import type { IncomingHttpHeaders } from 'node:http';\nimport * as Form from 'next/form';\nimport * as Image from 'next/image';\nimport * as Link from 'next/link';\nimport * as Router from 'next/router';\nimport * as Script from 'next/script';\nimport { useEffect } from 'react';\nimport { shared as _shared } from 'remote-components/shared/host/pages';\nimport { RemoteComponentsError } from '#internal/shared/client/remote-component';\nimport { fetchRemoteComponent } from '#internal/shared/ssr/fetch-remote-component';\nimport { RemoteComponent as RemoteComponentReact } from '#remote-components/react/index';\n\nconst navigationImpl = {\n useRouter: () => Router.useRouter(),\n useSearchParams: () => {\n const router = Router.useRouter();\n return {\n get: (key: string) => router.query[key],\n has: (key: string) => key in router.query,\n };\n },\n};\n\nconst sharedCache = new Map<string, Record<string, () => Promise<unknown>>>();\nconst shared = (bundle: string) => {\n if (sharedCache.has(bundle)) {\n return sharedCache.get(bundle);\n }\n\n const remoteLoader = ({ src, width, quality }: Image.ImageLoaderProps) => {\n const self = globalThis as typeof globalThis & {\n __remote_bundle_url__?: Record<string, URL>;\n };\n const { assetPrefix } =\n /^(?<assetPrefix>.*?)\\/_next\\//.exec(src)?.groups ?? {};\n return `${\n self.__remote_bundle_url__?.[bundle]?.origin ?? ''\n }${assetPrefix}/_next/image?url=${encodeURIComponent(src)}&w=${width}&q=${\n quality || 75\n }`;\n };\n\n const imageImpl = (ImageComponent: typeof Image.default) => {\n function RemoteImage(props: Image.ImageProps) {\n return <ImageComponent loader={remoteLoader} {...props} />;\n }\n RemoteImage.default = RemoteImage;\n RemoteImage.getImageProps = Image.getImageProps;\n return RemoteImage;\n };\n\n return {\n // polyfill Next.js App Router client API (minimal)\n // some API methods are not available when using a Next.js Pages Router application as host\n 'next/navigation': () =>\n Promise.resolve(navigationImpl) as Promise<unknown>,\n 'next/dist/client/components/navigation': () =>\n Promise.resolve(navigationImpl) as Promise<unknown>,\n 'next/dist/client/app-dir/link': () =>\n Promise.resolve(Link.default) as Promise<unknown>,\n 'next/link': () => Promise.resolve(Link.default) as Promise<unknown>,\n 'next/dist/client/app-dir/form': () =>\n Promise.resolve(Form.default) as Promise<unknown>,\n 'next/form': () => Promise.resolve(Form.default) as Promise<unknown>,\n 'next/dist/client/script': () =>\n Promise.resolve(Script.default) as Promise<unknown>,\n 'next/script': () => Promise.resolve(Script.default) as Promise<unknown>,\n 'next/dist/client/image-component': () =>\n Promise.resolve({\n // @ts-expect-error default.default\n // eslint-disable-next-line\n Image: imageImpl(Image.default.default ?? Image.default),\n }) as Promise<unknown>,\n 'next/dist/api/image': () =>\n Promise.resolve({\n // @ts-expect-error default.default\n // eslint-disable-next-line\n default: imageImpl(Image.default.default ?? Image.default),\n getImageProps: Image.getImageProps,\n }) as Promise<unknown>,\n 'next/router': () => Promise.resolve(Router) as Promise<unknown>,\n ..._shared,\n // always override next/image to use the remote loader\n 'next/image': () =>\n Promise.resolve(\n // @ts-expect-error default.default\n // eslint-disable-next-line\n imageImpl(Image.default.default ?? Image.default),\n ) as Promise<unknown>,\n };\n};\n\n// internal symbols to access global store\nconst REMOTE_COMPONENT_STORE = Symbol('REMOTE_COMPONENT_STORE');\nconst REMOTE_COMPONENT_KEY = '__REMOTE_COMPONENT_KEY__';\n\n// temporary global store for remote component HTML\n// the store is used to save the HTML of remote components for SSR without sending the content to the client\nconst self = globalThis as typeof globalThis & {\n [REMOTE_COMPONENT_STORE]?: Map<string, React.ReactNode>;\n};\n\nfunction getKey({\n bundle,\n route,\n name,\n}: {\n bundle?: string;\n route?: string;\n name?: string;\n}): string {\n return `${bundle ?? '__next'}:${route ?? '/'}:${\n name ?? '__vercel_remote_component'\n }__${crypto.randomUUID()}`;\n}\n\nfunction setComponent(key: string, component: React.ReactNode): void {\n if (!self[REMOTE_COMPONENT_STORE]) {\n self[REMOTE_COMPONENT_STORE] = new Map();\n }\n self[REMOTE_COMPONENT_STORE].set(key, component);\n}\n\nfunction getComponent(key: string): React.ReactNode | undefined {\n const component = self[REMOTE_COMPONENT_STORE]?.get(key);\n // remove the component from the store after retrieving it to prevent memory leaks\n // storing the HTML in the global store is only needed for SSR and it's temporary only used for a single render\n self[REMOTE_COMPONENT_STORE]?.delete(key);\n return component;\n}\n\nexport interface RemoteComponentProps {\n src: string;\n bundle?: string;\n route?: string;\n name?: string;\n isolate?: boolean;\n mode?: 'open' | 'closed';\n reset?: boolean;\n additionalHeaders?: Headers | Record<string, string>;\n [REMOTE_COMPONENT_KEY]?: string;\n children?: React.ReactNode;\n}\n\n/**\n * This component handles the rendering of remote microfrontends.\n *\n * @param props - The properties for the remote component.\n * @returns A React component that renders the remote component.\n */\nexport function RemoteComponent(props: RemoteComponentProps) {\n const remoteComponent =\n typeof document !== 'undefined'\n ? null\n : // retrieve the HTML from the global store\n getComponent(\n props[REMOTE_COMPONENT_KEY] ?? '__vercel_remote_component',\n );\n\n useEffect(() => {\n const clientSelf = globalThis as typeof globalThis & {\n __remote_component_shared__?: Record<string, () => Promise<unknown>>;\n };\n // eslint-disable-next-line camelcase\n clientSelf.__remote_component_shared__ = shared(props.bundle ?? 'default');\n }, [props.bundle]);\n\n if (!props[REMOTE_COMPONENT_KEY]) {\n return (\n <RemoteComponentReact\n additionalHeaders={props.additionalHeaders}\n isolate={props.isolate}\n mode={props.mode}\n name={props.name}\n reset={props.reset}\n shared={shared(props.bundle ?? 'default')}\n src={props.src}\n >\n {props.children}\n </RemoteComponentReact>\n );\n }\n\n return (\n <RemoteComponentReact\n additionalHeaders={props.additionalHeaders}\n isolate={props.isolate}\n mode={props.mode}\n name={props.name}\n reset={props.reset}\n shared={shared(props.bundle ?? 'default')}\n src={props.src}\n >\n {remoteComponent}\n </RemoteComponentReact>\n );\n}\n\n/**\n * Fetches the remote component properties from the server. You need to pass these properties to the `<RemoteComponent>` component to render the fetched remote component.\n *\n * @param src - The source URL of the remote component. When using the Vercel Microfrontends solution, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param headers - The HTTP headers used for supporting the Vercel Microfrontends proxy.\n * @returns The properties of the remote component.\n *\n * @example\n *\n * ```tsx\n * import { getRemoteComponentProps } from 'remote-components/next/host/pages';\n * import type { GetServerSideProps } from 'next';\n *\n * export const getServerSideProps: GetServerSideProps<PageProps> = async function getServerSideProps({ req }) {\n * const myRemoteComponent = await getRemoteComponentProps(\n * '/nextjs-app-remote/components/header',\n * req.headers,\n * );\n * return {\n * props: {\n * remoteComponents: {\n * myRemoteComponent,\n * },\n * },\n * };\n * }\n * ```\n */\nexport async function getRemoteComponentProps(\n src: string,\n headers: IncomingHttpHeaders,\n): Promise<RemoteComponentProps> {\n if (typeof document !== 'undefined') {\n throw new RemoteComponentsError(\n '`getRemoteComponentProps()` can only be used on the server side.',\n );\n }\n\n const {\n metadata: { bundle, route },\n name,\n links,\n component,\n nextData,\n remoteShared,\n } = await fetchRemoteComponent(\n src,\n headers instanceof Headers\n ? headers\n : // convert IncomingHttpHeaders to web standard Headers\n Object.entries(headers).reduce((acc, [key, value]) => {\n if (value) {\n if (Array.isArray(value)) {\n value.forEach((v) => acc.append(key, v));\n } else {\n acc.append(key, value);\n }\n }\n return acc;\n }, new Headers()),\n {\n rsc: true,\n },\n );\n\n const props: RemoteComponentProps = {\n src,\n bundle,\n name,\n route,\n };\n\n const key = getKey(props);\n\n // do not render the HTML in development mode when remote is using Next.js Pages Router\n // this behavior is emulating the Next.js Pages Router FOUC as the styles are only applied on the client when running in development mode\n if (nextData?.buildId !== 'development') {\n // store the HTML in a global store\n setComponent(\n key,\n <>\n <script\n data-remote-components-shared=\"\"\n id={`${name}_shared`}\n type=\"application/json\"\n >\n {JSON.stringify(remoteShared)}\n </script>\n {links.map((link) => (\n <link\n key={`${link.as}_${link.href}`}\n {...link}\n precedence={undefined}\n />\n ))}\n {component}\n </>,\n );\n }\n\n return {\n ...props,\n // add remote component key to the props\n [REMOTE_COMPONENT_KEY]: key,\n };\n}\n"],"mappings":"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","names":["import_react","self","_shared","RemoteComponentReact","key"]}
@@ -4,7 +4,6 @@ import { IncomingHttpHeaders } from 'node:http';
4
4
  declare const REMOTE_COMPONENT_KEY = "__REMOTE_COMPONENT_KEY__";
5
5
  interface RemoteComponentProps {
6
6
  src: string;
7
- url?: string | URL;
8
7
  bundle?: string;
9
8
  route?: string;
10
9
  name?: string;
@@ -111,7 +111,7 @@ function RemoteComponent(props) {
111
111
  name: props.name,
112
112
  reset: props.reset,
113
113
  shared: shared(props.bundle ?? "default"),
114
- src: props.url ?? props.src,
114
+ src: props.src,
115
115
  children: props.children
116
116
  }
117
117
  );
@@ -125,7 +125,7 @@ function RemoteComponent(props) {
125
125
  name: props.name,
126
126
  reset: props.reset,
127
127
  shared: shared(props.bundle ?? "default"),
128
- src: props.url ?? props.src,
128
+ src: props.src,
129
129
  children: remoteComponent
130
130
  }
131
131
  );
@@ -137,12 +137,11 @@ async function getRemoteComponentProps(src, headers) {
137
137
  );
138
138
  }
139
139
  const {
140
- metadata: { bundle, route, runtime },
140
+ metadata: { bundle, route },
141
141
  name,
142
142
  links,
143
143
  component,
144
144
  nextData,
145
- url,
146
145
  remoteShared
147
146
  } = await fetchRemoteComponent(
148
147
  src,
@@ -167,10 +166,7 @@ async function getRemoteComponentProps(src, headers) {
167
166
  src,
168
167
  bundle,
169
168
  name,
170
- route,
171
- runtime,
172
- buildId: nextData?.buildId ?? null,
173
- url: url.href
169
+ route
174
170
  };
175
171
  const key = getKey(props);
176
172
  if (nextData?.buildId !== "development") {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/next/host/pages-router-server.tsx"],"sourcesContent":["import type { IncomingHttpHeaders } from 'node:http';\nimport * as Form from 'next/form';\nimport * as Image from 'next/image';\nimport * as Link from 'next/link';\nimport * as Router from 'next/router';\nimport * as Script from 'next/script';\nimport { useEffect } from 'react';\nimport { shared as _shared } from 'remote-components/shared/host/pages';\nimport { RemoteComponentsError } from '#internal/shared/client/remote-component';\nimport { fetchRemoteComponent } from '#internal/shared/ssr/fetch-remote-component';\nimport { RemoteComponent as RemoteComponentReact } from '#remote-components/react/index';\n\nconst navigationImpl = {\n useRouter: () => Router.useRouter(),\n useSearchParams: () => {\n const router = Router.useRouter();\n return {\n get: (key: string) => router.query[key],\n has: (key: string) => key in router.query,\n };\n },\n};\n\nconst sharedCache = new Map<string, Record<string, () => Promise<unknown>>>();\nconst shared = (bundle: string) => {\n if (sharedCache.has(bundle)) {\n return sharedCache.get(bundle);\n }\n\n const remoteLoader = ({ src, width, quality }: Image.ImageLoaderProps) => {\n const self = globalThis as typeof globalThis & {\n __remote_bundle_url__?: Record<string, URL>;\n };\n const { assetPrefix } =\n /^(?<assetPrefix>.*?)\\/_next\\//.exec(src)?.groups ?? {};\n return `${self.__remote_bundle_url__?.[bundle]?.origin ?? ''}${assetPrefix}/_next/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality || 75}`;\n };\n\n const imageImpl = (ImageComponent: typeof Image.default) => {\n function RemoteImage(props: Image.ImageProps) {\n return <ImageComponent loader={remoteLoader} {...props} />;\n }\n RemoteImage.default = RemoteImage;\n RemoteImage.getImageProps = Image.getImageProps;\n return RemoteImage;\n };\n\n return {\n // polyfill Next.js App Router client API (minimal)\n // some API methods are not available when using a Next.js Pages Router application as host\n 'next/navigation': () =>\n Promise.resolve(navigationImpl) as Promise<unknown>,\n 'next/dist/client/components/navigation': () =>\n Promise.resolve(navigationImpl) as Promise<unknown>,\n 'next/dist/client/app-dir/link': () =>\n Promise.resolve(Link.default) as Promise<unknown>,\n 'next/link': () => Promise.resolve(Link.default) as Promise<unknown>,\n 'next/dist/client/app-dir/form': () =>\n Promise.resolve(Form.default) as Promise<unknown>,\n 'next/form': () => Promise.resolve(Form.default) as Promise<unknown>,\n 'next/dist/client/script': () =>\n Promise.resolve(Script.default) as Promise<unknown>,\n 'next/script': () => Promise.resolve(Script.default) as Promise<unknown>,\n 'next/dist/client/image-component': () =>\n Promise.resolve({\n // @ts-expect-error default.default\n // eslint-disable-next-line\n Image: imageImpl(Image.default.default ?? Image.default),\n }) as Promise<unknown>,\n 'next/dist/api/image': () =>\n Promise.resolve({\n // @ts-expect-error default.default\n // eslint-disable-next-line\n default: imageImpl(Image.default.default ?? Image.default),\n getImageProps: Image.getImageProps,\n }) as Promise<unknown>,\n 'next/router': () => Promise.resolve(Router) as Promise<unknown>,\n ..._shared,\n // always override next/image to use the remote loader\n 'next/image': () =>\n Promise.resolve(\n // @ts-expect-error default.default\n // eslint-disable-next-line\n imageImpl(Image.default.default ?? Image.default),\n ) as Promise<unknown>,\n };\n};\n\n// internal symbols to access global store\nconst REMOTE_COMPONENT_STORE = Symbol('REMOTE_COMPONENT_STORE');\nconst REMOTE_COMPONENT_KEY = '__REMOTE_COMPONENT_KEY__';\n\n// temporary global store for remote component HTML\n// the store is used to save the HTML of remote components for SSR without sending the content to the client\nconst self = globalThis as typeof globalThis & {\n [REMOTE_COMPONENT_STORE]?: Map<string, React.ReactNode>;\n};\n\nfunction getKey({\n bundle,\n route,\n name,\n}: {\n bundle?: string;\n route?: string;\n name?: string;\n}): string {\n return `${bundle ?? '__next'}:${route ?? '/'}:${name ?? '__vercel_remote_component'}__${crypto.randomUUID()}`;\n}\n\nfunction setComponent(key: string, component: React.ReactNode): void {\n if (!self[REMOTE_COMPONENT_STORE]) {\n self[REMOTE_COMPONENT_STORE] = new Map();\n }\n self[REMOTE_COMPONENT_STORE].set(key, component);\n}\n\nfunction getComponent(key: string): React.ReactNode | undefined {\n const component = self[REMOTE_COMPONENT_STORE]?.get(key);\n // remove the component from the store after retrieving it to prevent memory leaks\n // storing the HTML in the global store is only needed for SSR and it's temporary only used for a single render\n self[REMOTE_COMPONENT_STORE]?.delete(key);\n return component;\n}\n\nexport interface RemoteComponentProps {\n src: string;\n url?: string | URL;\n bundle?: string;\n route?: string;\n name?: string;\n isolate?: boolean;\n mode?: 'open' | 'closed';\n reset?: boolean;\n additionalHeaders?: Headers | Record<string, string>;\n [REMOTE_COMPONENT_KEY]?: string;\n children?: React.ReactNode;\n}\n\n/**\n * This component handles the rendering of remote microfrontends.\n *\n * @param props - The properties for the remote component.\n * @returns A React component that renders the remote component.\n */\nexport function RemoteComponent(props: RemoteComponentProps) {\n const remoteComponent =\n typeof document !== 'undefined'\n ? null\n : // retrieve the HTML from the global store\n getComponent(\n props[REMOTE_COMPONENT_KEY] ?? '__vercel_remote_component',\n );\n\n useEffect(() => {\n const clientSelf = globalThis as typeof globalThis & {\n __remote_component_shared__?: Record<string, () => Promise<unknown>>;\n };\n // eslint-disable-next-line camelcase\n clientSelf.__remote_component_shared__ = shared(props.bundle ?? 'default');\n }, [props.bundle]);\n\n if (!props[REMOTE_COMPONENT_KEY]) {\n return (\n <RemoteComponentReact\n additionalHeaders={props.additionalHeaders}\n isolate={props.isolate}\n mode={props.mode}\n name={props.name}\n reset={props.reset}\n shared={shared(props.bundle ?? 'default')}\n src={props.url ?? props.src}\n >\n {props.children}\n </RemoteComponentReact>\n );\n }\n\n return (\n <RemoteComponentReact\n additionalHeaders={props.additionalHeaders}\n isolate={props.isolate}\n mode={props.mode}\n name={props.name}\n reset={props.reset}\n shared={shared(props.bundle ?? 'default')}\n src={props.url ?? props.src}\n >\n {remoteComponent}\n </RemoteComponentReact>\n );\n}\n\n/**\n * Fetches the remote component properties from the server. You need to pass these properties to the `<RemoteComponent>` component to render the fetched remote component.\n *\n * @param src - The source URL of the remote component. When using the Vercel Microfrontends solution, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param headers - The HTTP headers used for supporting the Vercel Microfrontends proxy.\n * @returns The properties of the remote component.\n *\n * @example\n *\n * ```tsx\n * import { getRemoteComponentProps } from 'remote-components/next/host/pages';\n * import type { GetServerSideProps } from 'next';\n *\n * export const getServerSideProps: GetServerSideProps<PageProps> = async function getServerSideProps({ req }) {\n * const myRemoteComponent = await getRemoteComponentProps(\n * '/nextjs-app-remote/components/header',\n * req.headers,\n * );\n * return {\n * props: {\n * remoteComponents: {\n * myRemoteComponent,\n * },\n * },\n * };\n * }\n * ```\n */\nexport async function getRemoteComponentProps(\n src: string,\n headers: IncomingHttpHeaders,\n): Promise<RemoteComponentProps> {\n if (typeof document !== 'undefined') {\n throw new RemoteComponentsError(\n '`getRemoteComponentProps()` can only be used on the server side.',\n );\n }\n\n const {\n metadata: { bundle, route, runtime },\n name,\n links,\n component,\n nextData,\n url,\n remoteShared,\n } = await fetchRemoteComponent(\n src,\n headers instanceof Headers\n ? headers\n : // convert IncomingHttpHeaders to web standard Headers\n Object.entries(headers).reduce((acc, [key, value]) => {\n if (value) {\n if (Array.isArray(value)) {\n value.forEach((v) => acc.append(key, v));\n } else {\n acc.append(key, value);\n }\n }\n return acc;\n }, new Headers()),\n {\n rsc: true,\n },\n );\n\n const props = {\n src,\n bundle,\n name,\n route,\n runtime,\n buildId: nextData?.buildId ?? null,\n url: url.href,\n };\n\n const key = getKey(props);\n\n // do not render the HTML in development mode when remote is using Next.js Pages Router\n // this behavior is emulating the Next.js Pages Router FOUC as the styles are only applied on the client when running in development mode\n if (nextData?.buildId !== 'development') {\n // store the HTML in a global store\n setComponent(\n key,\n <>\n <script\n data-remote-components-shared=\"\"\n id={`${name}_shared`}\n type=\"application/json\"\n >\n {JSON.stringify(remoteShared)}\n </script>\n {links.map((link) => (\n <link\n key={`${link.as}_${link.href}`}\n {...link}\n precedence={undefined}\n />\n ))}\n {component}\n </>,\n );\n }\n\n return {\n ...props,\n // add remote component key to the props\n [REMOTE_COMPONENT_KEY]: key,\n };\n}\n"],"mappings":"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","names":["self","key"]}
1
+ {"version":3,"sources":["../../../src/next/host/pages-router-server.tsx"],"sourcesContent":["import type { IncomingHttpHeaders } from 'node:http';\nimport * as Form from 'next/form';\nimport * as Image from 'next/image';\nimport * as Link from 'next/link';\nimport * as Router from 'next/router';\nimport * as Script from 'next/script';\nimport { useEffect } from 'react';\nimport { shared as _shared } from 'remote-components/shared/host/pages';\nimport { RemoteComponentsError } from '#internal/shared/client/remote-component';\nimport { fetchRemoteComponent } from '#internal/shared/ssr/fetch-remote-component';\nimport { RemoteComponent as RemoteComponentReact } from '#remote-components/react/index';\n\nconst navigationImpl = {\n useRouter: () => Router.useRouter(),\n useSearchParams: () => {\n const router = Router.useRouter();\n return {\n get: (key: string) => router.query[key],\n has: (key: string) => key in router.query,\n };\n },\n};\n\nconst sharedCache = new Map<string, Record<string, () => Promise<unknown>>>();\nconst shared = (bundle: string) => {\n if (sharedCache.has(bundle)) {\n return sharedCache.get(bundle);\n }\n\n const remoteLoader = ({ src, width, quality }: Image.ImageLoaderProps) => {\n const self = globalThis as typeof globalThis & {\n __remote_bundle_url__?: Record<string, URL>;\n };\n const { assetPrefix } =\n /^(?<assetPrefix>.*?)\\/_next\\//.exec(src)?.groups ?? {};\n return `${\n self.__remote_bundle_url__?.[bundle]?.origin ?? ''\n }${assetPrefix}/_next/image?url=${encodeURIComponent(src)}&w=${width}&q=${\n quality || 75\n }`;\n };\n\n const imageImpl = (ImageComponent: typeof Image.default) => {\n function RemoteImage(props: Image.ImageProps) {\n return <ImageComponent loader={remoteLoader} {...props} />;\n }\n RemoteImage.default = RemoteImage;\n RemoteImage.getImageProps = Image.getImageProps;\n return RemoteImage;\n };\n\n return {\n // polyfill Next.js App Router client API (minimal)\n // some API methods are not available when using a Next.js Pages Router application as host\n 'next/navigation': () =>\n Promise.resolve(navigationImpl) as Promise<unknown>,\n 'next/dist/client/components/navigation': () =>\n Promise.resolve(navigationImpl) as Promise<unknown>,\n 'next/dist/client/app-dir/link': () =>\n Promise.resolve(Link.default) as Promise<unknown>,\n 'next/link': () => Promise.resolve(Link.default) as Promise<unknown>,\n 'next/dist/client/app-dir/form': () =>\n Promise.resolve(Form.default) as Promise<unknown>,\n 'next/form': () => Promise.resolve(Form.default) as Promise<unknown>,\n 'next/dist/client/script': () =>\n Promise.resolve(Script.default) as Promise<unknown>,\n 'next/script': () => Promise.resolve(Script.default) as Promise<unknown>,\n 'next/dist/client/image-component': () =>\n Promise.resolve({\n // @ts-expect-error default.default\n // eslint-disable-next-line\n Image: imageImpl(Image.default.default ?? Image.default),\n }) as Promise<unknown>,\n 'next/dist/api/image': () =>\n Promise.resolve({\n // @ts-expect-error default.default\n // eslint-disable-next-line\n default: imageImpl(Image.default.default ?? Image.default),\n getImageProps: Image.getImageProps,\n }) as Promise<unknown>,\n 'next/router': () => Promise.resolve(Router) as Promise<unknown>,\n ..._shared,\n // always override next/image to use the remote loader\n 'next/image': () =>\n Promise.resolve(\n // @ts-expect-error default.default\n // eslint-disable-next-line\n imageImpl(Image.default.default ?? Image.default),\n ) as Promise<unknown>,\n };\n};\n\n// internal symbols to access global store\nconst REMOTE_COMPONENT_STORE = Symbol('REMOTE_COMPONENT_STORE');\nconst REMOTE_COMPONENT_KEY = '__REMOTE_COMPONENT_KEY__';\n\n// temporary global store for remote component HTML\n// the store is used to save the HTML of remote components for SSR without sending the content to the client\nconst self = globalThis as typeof globalThis & {\n [REMOTE_COMPONENT_STORE]?: Map<string, React.ReactNode>;\n};\n\nfunction getKey({\n bundle,\n route,\n name,\n}: {\n bundle?: string;\n route?: string;\n name?: string;\n}): string {\n return `${bundle ?? '__next'}:${route ?? '/'}:${\n name ?? '__vercel_remote_component'\n }__${crypto.randomUUID()}`;\n}\n\nfunction setComponent(key: string, component: React.ReactNode): void {\n if (!self[REMOTE_COMPONENT_STORE]) {\n self[REMOTE_COMPONENT_STORE] = new Map();\n }\n self[REMOTE_COMPONENT_STORE].set(key, component);\n}\n\nfunction getComponent(key: string): React.ReactNode | undefined {\n const component = self[REMOTE_COMPONENT_STORE]?.get(key);\n // remove the component from the store after retrieving it to prevent memory leaks\n // storing the HTML in the global store is only needed for SSR and it's temporary only used for a single render\n self[REMOTE_COMPONENT_STORE]?.delete(key);\n return component;\n}\n\nexport interface RemoteComponentProps {\n src: string;\n bundle?: string;\n route?: string;\n name?: string;\n isolate?: boolean;\n mode?: 'open' | 'closed';\n reset?: boolean;\n additionalHeaders?: Headers | Record<string, string>;\n [REMOTE_COMPONENT_KEY]?: string;\n children?: React.ReactNode;\n}\n\n/**\n * This component handles the rendering of remote microfrontends.\n *\n * @param props - The properties for the remote component.\n * @returns A React component that renders the remote component.\n */\nexport function RemoteComponent(props: RemoteComponentProps) {\n const remoteComponent =\n typeof document !== 'undefined'\n ? null\n : // retrieve the HTML from the global store\n getComponent(\n props[REMOTE_COMPONENT_KEY] ?? '__vercel_remote_component',\n );\n\n useEffect(() => {\n const clientSelf = globalThis as typeof globalThis & {\n __remote_component_shared__?: Record<string, () => Promise<unknown>>;\n };\n // eslint-disable-next-line camelcase\n clientSelf.__remote_component_shared__ = shared(props.bundle ?? 'default');\n }, [props.bundle]);\n\n if (!props[REMOTE_COMPONENT_KEY]) {\n return (\n <RemoteComponentReact\n additionalHeaders={props.additionalHeaders}\n isolate={props.isolate}\n mode={props.mode}\n name={props.name}\n reset={props.reset}\n shared={shared(props.bundle ?? 'default')}\n src={props.src}\n >\n {props.children}\n </RemoteComponentReact>\n );\n }\n\n return (\n <RemoteComponentReact\n additionalHeaders={props.additionalHeaders}\n isolate={props.isolate}\n mode={props.mode}\n name={props.name}\n reset={props.reset}\n shared={shared(props.bundle ?? 'default')}\n src={props.src}\n >\n {remoteComponent}\n </RemoteComponentReact>\n );\n}\n\n/**\n * Fetches the remote component properties from the server. You need to pass these properties to the `<RemoteComponent>` component to render the fetched remote component.\n *\n * @param src - The source URL of the remote component. When using the Vercel Microfrontends solution, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param headers - The HTTP headers used for supporting the Vercel Microfrontends proxy.\n * @returns The properties of the remote component.\n *\n * @example\n *\n * ```tsx\n * import { getRemoteComponentProps } from 'remote-components/next/host/pages';\n * import type { GetServerSideProps } from 'next';\n *\n * export const getServerSideProps: GetServerSideProps<PageProps> = async function getServerSideProps({ req }) {\n * const myRemoteComponent = await getRemoteComponentProps(\n * '/nextjs-app-remote/components/header',\n * req.headers,\n * );\n * return {\n * props: {\n * remoteComponents: {\n * myRemoteComponent,\n * },\n * },\n * };\n * }\n * ```\n */\nexport async function getRemoteComponentProps(\n src: string,\n headers: IncomingHttpHeaders,\n): Promise<RemoteComponentProps> {\n if (typeof document !== 'undefined') {\n throw new RemoteComponentsError(\n '`getRemoteComponentProps()` can only be used on the server side.',\n );\n }\n\n const {\n metadata: { bundle, route },\n name,\n links,\n component,\n nextData,\n remoteShared,\n } = await fetchRemoteComponent(\n src,\n headers instanceof Headers\n ? headers\n : // convert IncomingHttpHeaders to web standard Headers\n Object.entries(headers).reduce((acc, [key, value]) => {\n if (value) {\n if (Array.isArray(value)) {\n value.forEach((v) => acc.append(key, v));\n } else {\n acc.append(key, value);\n }\n }\n return acc;\n }, new Headers()),\n {\n rsc: true,\n },\n );\n\n const props: RemoteComponentProps = {\n src,\n bundle,\n name,\n route,\n };\n\n const key = getKey(props);\n\n // do not render the HTML in development mode when remote is using Next.js Pages Router\n // this behavior is emulating the Next.js Pages Router FOUC as the styles are only applied on the client when running in development mode\n if (nextData?.buildId !== 'development') {\n // store the HTML in a global store\n setComponent(\n key,\n <>\n <script\n data-remote-components-shared=\"\"\n id={`${name}_shared`}\n type=\"application/json\"\n >\n {JSON.stringify(remoteShared)}\n </script>\n {links.map((link) => (\n <link\n key={`${link.as}_${link.href}`}\n {...link}\n precedence={undefined}\n />\n ))}\n {component}\n </>,\n );\n }\n\n return {\n ...props,\n // add remote component key to the props\n [REMOTE_COMPONENT_KEY]: key,\n };\n}\n"],"mappings":"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","names":["self","key"]}
@@ -33,6 +33,7 @@ var import_polyfill = require("#internal/shared/client/polyfill");
33
33
  var import_remote_component = require("#internal/shared/client/remote-component");
34
34
  var import_error = require("#internal/shared/error");
35
35
  var import_fetch_headers = require("#internal/shared/ssr/fetch-headers");
36
+ var import_get_client_or_server_url = require("#internal/shared/ssr/get-client-or-server-url");
36
37
  var import_utils = require("#internal/shared/utils");
37
38
  function getRemoteComponentHtml(html) {
38
39
  if (typeof document === "undefined")
@@ -53,6 +54,7 @@ function getRemoteComponentHtml(html) {
53
54
  }
54
55
  return "";
55
56
  }
57
+ const DUMMY_FALLBACK = "http://remote-components-dummy-fallback";
56
58
  function RemoteComponent({
57
59
  src,
58
60
  isolate,
@@ -68,7 +70,7 @@ function RemoteComponent({
68
70
  if (typeof src === "string") {
69
71
  const url2 = new URL(
70
72
  src,
71
- typeof document !== "undefined" ? location.href : "http://localhost"
73
+ typeof document !== "undefined" ? location.href : DUMMY_FALLBACK
72
74
  );
73
75
  if (url2.hash) {
74
76
  return url2.hash.slice(1);
@@ -79,20 +81,23 @@ function RemoteComponent({
79
81
  return nameProp;
80
82
  }, [src, nameProp]);
81
83
  const [data, setData] = (0, import_react2.useState)(null);
84
+ const url = (0, import_react2.useMemo)(() => (0, import_get_client_or_server_url.getClientOrServerUrl)(src, DUMMY_FALLBACK), [src]);
85
+ const id = url.origin === (typeof location !== "undefined" ? location.origin : DUMMY_FALLBACK) ? url.pathname : url.href;
86
+ const keySuffix = `${(0, import_utils.escapeString)(id)}_${(0, import_utils.escapeString)(data?.name ?? name)}`;
82
87
  const [remoteComponent, setRemoteComponent] = (0, import_react2.useState)(null);
83
88
  const shadowRootContainerRef = (0, import_react2.useRef)(null);
84
89
  const [shadowRoot, setShadowRoot] = (0, import_react2.useState)(() => {
85
90
  const self = globalThis;
86
- const shadowRootKey = `__remote_components_shadowroot_${src ? (0, import_utils.escapeString)(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${(0, import_utils.escapeString)(data?.name ?? name)}`;
91
+ const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
87
92
  const ssrShadowRoot = typeof document !== "undefined" ? document.querySelector(
88
- `[data-remote-component-id="shadowroot_${src ? (0, import_utils.escapeString)(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${(0, import_utils.escapeString)(data?.name ?? name)}"]`
93
+ `[data-remote-component-id="shadowroot_${keySuffix}"]`
89
94
  )?.shadowRoot ?? self[shadowRootKey] ?? null : null;
90
95
  self[shadowRootKey] = null;
91
96
  return ssrShadowRoot;
92
97
  });
93
98
  const htmlRef = (0, import_react2.useRef)(
94
99
  typeof document !== "undefined" ? document.querySelector(
95
- `[data-remote-component-id="shadowroot_${src ? (0, import_utils.escapeString)(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${(0, import_utils.escapeString)(data?.name ?? name)}"]`
100
+ `[data-remote-component-id="shadowroot_${keySuffix}"]`
96
101
  )?.shadowRoot?.innerHTML ?? document.getElementById(`__REMOTE_COMPONENT${name}`)?.innerHTML ?? document.querySelector(`div[data-bundle][data-route][id^="${name}"]`)?.innerHTML ?? document.querySelector("div[data-bundle][data-route]")?.innerHTML : null
97
102
  );
98
103
  const endTemplateRef = (0, import_react2.useRef)(null);
@@ -124,10 +129,10 @@ function RemoteComponent({
124
129
  }
125
130
  if (isolate !== false && typeof document !== "undefined" && !shadowRoot) {
126
131
  const self = globalThis;
127
- const shadowRootKey = `__remote_components_shadowroot_${src ? (0, import_utils.escapeString)(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${(0, import_utils.escapeString)(data?.name ?? name)}`;
132
+ const shadowRootKey = `__remote_components_shadowroot_${keySuffix}`;
128
133
  let shadowRootElement = null;
129
134
  const element = document.querySelector(
130
- `[data-remote-component-id="shadowroot_${src ? (0, import_utils.escapeString)(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${(0, import_utils.escapeString)(data?.name ?? name)}"]`
135
+ `[data-remote-component-id="shadowroot_${keySuffix}"]`
131
136
  );
132
137
  shadowRootElement = self[shadowRootKey] ?? element?.shadowRoot ?? null;
133
138
  if (!shadowRootElement && element) {
@@ -144,7 +149,7 @@ function RemoteComponent({
144
149
  setShadowRoot(shadowRootElement);
145
150
  }
146
151
  }
147
- }, [name, isolate, shadowRoot, remoteComponent, mode, src, data]);
152
+ }, [isolate, shadowRoot, remoteComponent, mode, keySuffix]);
148
153
  (0, import_react2.useLayoutEffect)(() => {
149
154
  if (shadowRoot && remoteComponent) {
150
155
  const resetStyles = shadowRoot.querySelectorAll(
@@ -168,17 +173,6 @@ function RemoteComponent({
168
173
  }
169
174
  }
170
175
  }, [shadowRoot, remoteComponent, name]);
171
- const url = (0, import_react2.useMemo)(() => {
172
- if (typeof src !== "string")
173
- return new URL(
174
- typeof document !== "undefined" ? location.href : "http://localhost"
175
- );
176
- try {
177
- return typeof document !== "undefined" ? new URL(src, location.href) : new URL(src);
178
- } catch {
179
- return new URL(src, "http://localhost");
180
- }
181
- }, [src]);
182
176
  (0, import_react2.useEffect)(() => {
183
177
  if (src && src !== prevSrcRef.current) {
184
178
  prevSrcRef.current = src;
@@ -353,7 +347,9 @@ function RemoteComponent({
353
347
  }
354
348
  let rscName;
355
349
  if (rsc) {
356
- rscName = `__remote_component_rsc_${(0, import_utils.escapeString)(url.href)}_${(0, import_utils.escapeString)(remoteName)}`;
350
+ rscName = `__remote_component_rsc_${(0, import_utils.escapeString)(
351
+ id
352
+ )}_${(0, import_utils.escapeString)(remoteName)}`;
357
353
  rsc.textContent = rsc.textContent?.replace(
358
354
  new RegExp(`self\\["${remoteName}"\\]`, "g"),
359
355
  `self["${rscName}"]`
@@ -364,14 +360,13 @@ function RemoteComponent({
364
360
  ...metadata,
365
361
  links,
366
362
  remoteShared,
367
- url: url.href,
363
+ src: typeof src === "string" ? src : src.href,
364
+ serverUrl: url.href,
368
365
  data: rsc ? (rsc.textContent || "").split("\n").filter(Boolean) : []
369
366
  };
370
367
  componentHydrationHtml.current = `${Array.from(
371
368
  doc.querySelectorAll("link,style")
372
- ).map((link) => link.outerHTML).join(
373
- ""
374
- )}${reset ? `<style data-remote-components-reset="">:host { all: initial; }</style>` : ""}${component.innerHTML}`;
369
+ ).map((link) => link.outerHTML).join("")}${reset ? `<style data-remote-components-reset="">:host { all: initial; }</style>` : ""}${component.innerHTML}`;
375
370
  const userShared = await shared;
376
371
  if ("__remote_components_missing_shared__" in userShared) {
377
372
  userShared.__remote_components_missing_shared__().catch((e) => {
@@ -422,7 +417,7 @@ function RemoteComponent({
422
417
  }
423
418
  } else {
424
419
  const result = await (0, import_remote_component.loadRemoteComponent)({
425
- url: new URL(url, location.origin),
420
+ url,
426
421
  name: remoteName,
427
422
  rscName,
428
423
  bundle,
@@ -479,7 +474,8 @@ function RemoteComponent({
479
474
  shared,
480
475
  shadowRoot,
481
476
  additionalHeaders,
482
- reset
477
+ reset,
478
+ id
483
479
  ]);
484
480
  if (remoteComponent instanceof Error) {
485
481
  throw remoteComponent;
@@ -536,7 +532,7 @@ function RemoteComponent({
536
532
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
537
533
  "div",
538
534
  {
539
- "data-remote-component-id": `shadowroot_${src ? (0, import_utils.escapeString)(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${(0, import_utils.escapeString)(data?.name ?? name)}`,
535
+ "data-remote-component-id": `shadowroot_${keySuffix}`,
540
536
  id: `shadowroot_${data?.name ?? name}`,
541
537
  ref: shadowRootContainerRef,
542
538
  children: [
@@ -552,7 +548,7 @@ function RemoteComponent({
552
548
  src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="
553
549
  onload="(function(el){
554
550
  const root = el.getRootNode();
555
- globalThis.__remote_components_shadowroot_${src ? (0, import_utils.escapeString)(new URL(src, typeof location !== "undefined" ? location.origin : "http://localhost").href) : ""}_${(0, import_utils.escapeString)(data?.name ?? name)} = root;
551
+ globalThis.__remote_components_shadowroot_${keySuffix} = root;
556
552
  el.parentElement.remove();
557
553
  })(this)"
558
554
  />`