remote-components 0.0.37 → 0.0.38
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.
- package/dist/internal/next/host/app-router-client.cjs +5 -1
- package/dist/internal/next/host/app-router-client.cjs.map +1 -1
- package/dist/internal/next/host/app-router-client.js +5 -1
- package/dist/internal/next/host/app-router-client.js.map +1 -1
- package/dist/internal/shared/client/get-client-src.cjs +39 -0
- package/dist/internal/shared/client/get-client-src.cjs.map +1 -0
- package/dist/internal/shared/client/get-client-src.d.ts +7 -0
- package/dist/internal/shared/client/get-client-src.js +15 -0
- package/dist/internal/shared/client/get-client-src.js.map +1 -0
- package/dist/internal/shared/ssr/fetch-remote-component.cjs +14 -10
- package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
- package/dist/internal/shared/ssr/fetch-remote-component.js +14 -10
- package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
- package/dist/internal/shared/ssr/get-ssr-relative-path-base-url.cjs +34 -0
- package/dist/internal/shared/ssr/get-ssr-relative-path-base-url.cjs.map +1 -0
- package/dist/internal/shared/ssr/get-ssr-relative-path-base-url.d.ts +10 -0
- package/dist/internal/shared/ssr/get-ssr-relative-path-base-url.js +10 -0
- package/dist/internal/shared/ssr/get-ssr-relative-path-base-url.js.map +1 -0
- package/package.json +1 -1
|
@@ -37,6 +37,7 @@ var Image = __toESM(require("next/image"), 1);
|
|
|
37
37
|
var import_react = require("react");
|
|
38
38
|
var import_react_dom = require("react-dom");
|
|
39
39
|
var import_app_router_compat = require("#internal/next/host/app-router-compat");
|
|
40
|
+
var import_get_client_src = require("#internal/shared/client/get-client-src");
|
|
40
41
|
var import_remote_component = require("#internal/shared/client/remote-component");
|
|
41
42
|
var import_get_client_or_server_url = require("#internal/shared/ssr/get-client-or-server-url");
|
|
42
43
|
var import_utils = require("#internal/shared/utils");
|
|
@@ -290,6 +291,7 @@ function RemoteComponentClient({
|
|
|
290
291
|
{
|
|
291
292
|
link,
|
|
292
293
|
url,
|
|
294
|
+
serverUrl,
|
|
293
295
|
"data-wait": link.rel === "stylesheet" && link.href ? "" : void 0
|
|
294
296
|
},
|
|
295
297
|
JSON.stringify(link)
|
|
@@ -298,6 +300,7 @@ function RemoteComponentClient({
|
|
|
298
300
|
RenderLink,
|
|
299
301
|
{
|
|
300
302
|
link,
|
|
303
|
+
serverUrl,
|
|
301
304
|
url,
|
|
302
305
|
as: "style",
|
|
303
306
|
fetchPriority: "high",
|
|
@@ -378,6 +381,7 @@ function RemoteComponentClient({
|
|
|
378
381
|
function RenderLink({
|
|
379
382
|
link,
|
|
380
383
|
url,
|
|
384
|
+
serverUrl,
|
|
381
385
|
...rest
|
|
382
386
|
}) {
|
|
383
387
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -392,7 +396,7 @@ function RenderLink({
|
|
|
392
396
|
},
|
|
393
397
|
{}
|
|
394
398
|
),
|
|
395
|
-
href:
|
|
399
|
+
href: (0, import_get_client_src.getClientSrc)(link.href, serverUrl),
|
|
396
400
|
...rest
|
|
397
401
|
}
|
|
398
402
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/next/host/app-router-client.tsx"],"sourcesContent":["'use client';\n\nimport * as Image from 'next/image';\nimport {\n startTransition,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { imageImpl, routerImpl } from '#internal/next/host/app-router-compat';\nimport type { RemoteComponentProps } from '#internal/shared/client/remote-component';\nimport {\n DEFAULT_ROUTE,\n loadRemoteComponent,\n loadStaticRemoteComponent,\n RUNTIME_WEBPACK,\n} from '#internal/shared/client/remote-component';\nimport type { MountOrUnmountFunction } from '#internal/shared/client/types';\nimport { getClientOrServerUrl } from '#internal/shared/ssr/get-client-or-server-url';\nimport { attrToProp, escapeString } from '#internal/shared/utils';\n\n// patch react/jsx-runtime to support the shadowrootmode attribute on template elements\ndeclare module 'react/jsx-runtime' {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n template: {\n shadowrootmode?: 'open' | 'closed';\n id?: string;\n ref?: React.Ref<HTMLTemplateElement>;\n dangerouslySetInnerHTML?: {\n __html: string;\n };\n children?: React.ReactNode;\n };\n }\n }\n}\n\n// import { shared } from 'remote-components/shared/host';\nasync function tryImportShared() {\n try {\n const { shared } = await import('remote-components/shared/host/app');\n return shared;\n } catch {\n return {};\n }\n}\n\n/**\n * RemoteComponentClient - Main component for rendering remote components\n *\n * This component handles the loading and rendering of remote microfrontends.\n * It supports both RSC (React Server Components) and Next.js Pages Router based components.\n */\nexport function RemoteComponentClient({\n src,\n serverUrl,\n name,\n bundle,\n route = DEFAULT_ROUTE,\n runtime = RUNTIME_WEBPACK,\n data,\n nextData,\n scripts = [],\n links = [],\n remoteShared = {},\n isolate,\n mode = 'open',\n reset,\n type,\n children,\n}: RemoteComponentProps) {\n const remoteComponentId = useId();\n const [component, setComponent] = useState<React.ReactNode | Error>(null);\n const url = getClientOrServerUrl(src, serverUrl);\n const metadataRef = useRef<{\n name: string;\n bundle: string;\n route: string;\n url: string;\n loading: boolean;\n }>({\n name,\n bundle,\n route,\n url: url.href,\n loading: false,\n });\n const startRef = useRef<HTMLTemplateElement | null>(null);\n const endRef = useRef<HTMLTemplateElement | null>(null);\n const prevRemoteComponentUnmountRef = useRef<{\n unmount: Set<MountOrUnmountFunction>;\n root: ShadowRoot | DocumentFragment | null;\n } | null>(null);\n\n // Handle errors by re-throwing them\n if (component instanceof Error) {\n throw component;\n }\n\n // determine whether to use children or loaded component\n const shouldUseChildren =\n (!component ||\n (component &&\n !nextData &&\n type !== 'remote-component' &&\n typeof (component as unknown as Promise<unknown>).then !==\n 'function')) &&\n // if the remote Next.js Pages Router application is in development mode\n // we don't use the provided static HTML\n // to mitigate layout shift when loading CSS using JavaScript on the client\n nextData?.buildId !== 'development';\n\n // The pathname is used so this URL is the same across server and client requests for relative src's\n const keySuffix = `${escapeString(bundle)}_${escapeString(\n url.pathname,\n )}_${escapeString(name)}`;\n\n const self = globalThis as Record<\n `__remote_components_shadowroot_${string}`,\n ShadowRoot | null\n > &\n Record<`__remote_components_container_${string}`, HTMLDivElement | null>;\n const shadowRootKey = `__remote_components_shadowroot_${keySuffix}` as const;\n const shadowContainerRef = useRef<HTMLDivElement | null>(\n typeof document === 'undefined'\n ? null\n : document.querySelector(\n `[data-remote-component-id=\"shadowroot_${remoteComponentId}\"]`,\n ),\n );\n const shadowRootRef = useRef<ShadowRoot | null>(\n self[shadowRootKey] ?? shadowContainerRef.current?.shadowRoot ?? null,\n );\n const ssrShadowRootContentRef = useRef<NodeListOf<ChildNode> | null>(\n shadowRootRef.current?.querySelectorAll('*') ?? null,\n );\n const ssrLinksStylesRef = useRef<(HTMLLinkElement | HTMLStyleElement)[]>([]);\n\n if (self[shadowRootKey] && shadowRootRef.current) {\n self[shadowRootKey] = null;\n }\n\n useLayoutEffect(() => {\n if (\n !shadowContainerRef.current ||\n shadowContainerRef.current !== shadowRootRef.current?.host\n ) {\n shadowRootRef.current = null;\n }\n\n if (\n isolate !== false &&\n typeof document !== 'undefined' &&\n !shadowRootRef.current\n ) {\n let shadowRootElement: ShadowRoot | null = null;\n const element = shadowContainerRef.current;\n\n shadowRootElement = self[shadowRootKey] ?? element?.shadowRoot ?? null;\n self[shadowRootKey] = null;\n\n if (!shadowRootElement && element) {\n // create a shadow root if it doesn't exist\n // this is a fallback for browsers that don't support declarative shadow DOM\n try {\n shadowRootElement = element.attachShadow({ mode });\n } catch {\n // do nothing if attachShadow fails because of existing shadow root\n }\n }\n\n if (shadowRootElement) {\n shadowRootRef.current = shadowRootElement;\n }\n }\n\n if (\n shadowRootRef.current &&\n ssrShadowRootContentRef.current &&\n !shouldUseChildren\n ) {\n // remove all nodes from the shadow root except links\n ssrShadowRootContentRef.current.forEach((node) => {\n if (node.nodeName !== 'LINK' && node.nodeName !== 'STYLE') {\n node.parentNode?.removeChild(node);\n } else {\n ssrLinksStylesRef.current.push(\n node as HTMLLinkElement | HTMLStyleElement,\n );\n }\n });\n ssrShadowRootContentRef.current = null;\n }\n\n if (ssrLinksStylesRef.current.length > 0 && shadowRootRef.current) {\n const waitForLoad =\n shadowRootRef.current.querySelectorAll('link[data-wait]');\n if (waitForLoad.length > 0) {\n Promise.all(\n Array.from(waitForLoad).map(\n (link) =>\n new Promise<void>((resolve) => {\n link.addEventListener('load', () => resolve());\n link.addEventListener('error', () => resolve());\n }),\n ),\n )\n .then(() => {\n waitForLoad.forEach((el) => {\n el.removeAttribute('data-wait');\n });\n\n // remove SSR injected styles and links\n ssrLinksStylesRef.current.forEach((el) => {\n el.parentNode?.removeChild(el);\n });\n ssrLinksStylesRef.current = [];\n })\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n });\n }\n }\n }, [isolate, mode, self, shadowRootKey, shouldUseChildren]);\n\n useEffect(() => {\n // run unmount functions when the component changes or unmounts\n if (prevRemoteComponentUnmountRef.current && component !== children) {\n const { unmount, root } = prevRemoteComponentUnmountRef.current;\n prevRemoteComponentUnmountRef.current = null;\n Promise.all(\n Array.from(unmount).map(async (unmountFn) => {\n try {\n await unmountFn(root);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n }\n }),\n ).catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n });\n }\n }, [component, children]);\n\n useEffect(() => {\n startTransition(async () => {\n try {\n // if we have a component, we don't need to load it again\n if (\n (!metadataRef.current.loading &&\n !component &&\n (isolate === false || shadowRootRef.current)) ||\n metadataRef.current.url !== url.href ||\n metadataRef.current.name !== name ||\n metadataRef.current.bundle !== bundle ||\n metadataRef.current.route !== route\n ) {\n metadataRef.current = {\n name,\n bundle,\n route,\n url: url.href,\n loading: true,\n };\n\n // use the children as the component when type is remote-component\n if (type === 'remote-component') {\n setComponent(children);\n // load static scripts and execute mount functions\n // run this async but don't await it as we render children immediately\n loadStaticRemoteComponent(scripts as HTMLScriptElement[], url)\n .then(({ mount, unmount }) => {\n if (mount.size > 0) {\n let root: ShadowRoot | DocumentFragment | null =\n shadowRootRef.current;\n try {\n if (!root && startRef.current && endRef.current) {\n root = document.querySelectorAll(\n `#${startRef.current.id} ~ *:not(#${endRef.current.id}):has(~ #${endRef.current.id})`,\n ) as unknown as DocumentFragment;\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n }\n if (unmount.size > 0) {\n prevRemoteComponentUnmountRef.current = { unmount, root };\n }\n return Promise.all(\n Array.from(mount).map((mountFn) => mountFn(root)),\n );\n }\n })\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n setComponent(e as Error);\n });\n return;\n }\n\n const rscName = `__remote_components_rsc_${keySuffix}`;\n const result = await loadRemoteComponent({\n url,\n name,\n bundle,\n route,\n runtime,\n rscName,\n data,\n nextData,\n scripts,\n shared: (async () => {\n const shared = await tryImportShared();\n\n if ('__remote_components_missing_shared__' in shared) {\n await shared.__remote_components_missing_shared__();\n }\n\n return {\n 'next/router': routerImpl,\n ...shared,\n 'next/image': () =>\n Promise.resolve(imageImpl(Image.default, bundle)),\n 'next/dist/client/image-component': () =>\n Promise.resolve({ Image: imageImpl(Image.default, bundle) }),\n };\n })(),\n remoteShared,\n container: shadowRootRef.current,\n });\n metadataRef.current.loading = false;\n if (result.error) {\n setComponent(result.error);\n } else {\n setComponent(result.component);\n }\n }\n } catch (error: unknown) {\n metadataRef.current.loading = false;\n setComponent(error as Error);\n }\n });\n }, [\n component,\n name,\n bundle,\n route,\n runtime,\n scripts,\n data,\n nextData,\n remoteShared,\n children,\n isolate,\n type,\n keySuffix,\n url,\n ]);\n\n if (\n nextData?.buildId === 'development' &&\n shadowRootRef.current &&\n isolate !== false &&\n reset &&\n !shadowRootRef.current.querySelector('[data-remote-components-reset]')\n ) {\n // inject reset styles into the shadow root\n const style = document.createElement('style');\n style.setAttribute('data-remote-components-reset', '');\n style.textContent = `:host { all: initial; }`;\n shadowRootRef.current.insertBefore(style, shadowRootRef.current.firstChild);\n } else if (\n shadowRootRef.current &&\n isolate !== false &&\n !reset &&\n shadowRootRef.current.querySelector('[data-remote-components-reset]')\n ) {\n // ensure reset styles are the first child in the shadow root\n const style = shadowRootRef.current.querySelector(\n '[data-remote-components-reset]',\n );\n if (style && shadowRootRef.current.firstChild !== style) {\n shadowRootRef.current.removeChild(style);\n }\n }\n\n const linksToRender = (\n <>\n {(!nextData || nextData.buildId !== 'development') &&\n isolate !== false &&\n reset ? (\n <style data-remote-components-reset=\"\">{`:host { all: initial; }`}</style>\n ) : null}\n {links.map((link) => (\n <RenderLink\n key={JSON.stringify(link)}\n link={link}\n url={url}\n data-wait={link.rel === 'stylesheet' && link.href ? '' : undefined}\n />\n ))}\n {links\n .filter((link) => link.rel === 'stylesheet')\n .map((link) => (\n <RenderLink\n key={JSON.stringify(link)}\n link={link}\n url={url}\n as=\"style\"\n fetchPriority=\"high\"\n precedence={bundle}\n rel=\"preload\"\n />\n ))}\n </>\n );\n\n let componentToRender = shouldUseChildren\n ? children\n : (component as React.ReactNode);\n\n if (isolate !== false) {\n componentToRender = (\n <div\n data-remote-component-id={`shadowroot_${remoteComponentId}`}\n data-remote-component-isolation-root=\"\"\n id={`shadowroot_${name}`}\n ref={shadowContainerRef}\n >\n {typeof document === 'undefined' ? (\n // eslint-disable-next-line react/no-unknown-property\n <template shadowrootmode={mode}>\n {mode === 'closed' ? (\n <div\n dangerouslySetInnerHTML={{\n __html: `<img\n alt=\"\" decoding=\"async\" style=\"display:none\"\n src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==\"\n onload=\"(function(el){\n const root = el.getRootNode();\n globalThis.${shadowRootKey} = root;\n el.parentElement.remove();\n })(this)\"\n />`,\n }}\n />\n ) : null}\n {linksToRender}\n {shouldUseChildren ? children : null}\n </template>\n ) : null}\n {typeof document !== 'undefined' &&\n shadowRootRef.current &&\n !shouldUseChildren\n ? createPortal(\n <>\n {linksToRender}\n {componentToRender}\n </>,\n shadowRootRef.current,\n )\n : null}\n </div>\n );\n }\n\n return (\n <>\n {isolate === false ? (\n <template id={`${name}_start`} ref={startRef} />\n ) : null}\n <script data-remote-component type=\"application/json\">\n {JSON.stringify({\n name,\n bundle,\n route,\n runtime,\n })}\n </script>\n {isolate === false ? linksToRender : null}\n {componentToRender}\n {nextData ? (\n <script\n id={`${bundle}_${route.replace(\n /[^a-zA-Z0-9]+/g,\n '_',\n )}${name}_next_data`}\n type=\"application/json\"\n >\n {JSON.stringify(nextData)}\n </script>\n ) : null}\n {isolate === false ? <template id={`${name}_end`} ref={endRef} /> : null}\n </>\n );\n}\n\nfunction RenderLink({\n link,\n url,\n ...rest\n}: {\n link: Record<string, string | boolean | undefined>;\n url: URL;\n} & React.LinkHTMLAttributes<HTMLLinkElement>) {\n return (\n <link\n {...Object.entries(link).reduce<Record<string, string>>(\n (acc, [key, value]) => {\n if (\n key !== 'href' &&\n key !== 'precedence' &&\n typeof value === 'string'\n ) {\n acc[attrToProp[key] ?? key] = value;\n }\n return acc;\n },\n {},\n )}\n href={\n typeof link.href === 'string' ? new URL(link.href, url).href : undefined\n }\n {...rest}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/next/host/app-router-client.tsx"],"sourcesContent":["'use client';\n\nimport * as Image from 'next/image';\nimport {\n startTransition,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { imageImpl, routerImpl } from '#internal/next/host/app-router-compat';\nimport { getClientSrc } from '#internal/shared/client/get-client-src';\nimport type { RemoteComponentProps } from '#internal/shared/client/remote-component';\nimport {\n DEFAULT_ROUTE,\n loadRemoteComponent,\n loadStaticRemoteComponent,\n RUNTIME_WEBPACK,\n} from '#internal/shared/client/remote-component';\nimport type { MountOrUnmountFunction } from '#internal/shared/client/types';\nimport { getClientOrServerUrl } from '#internal/shared/ssr/get-client-or-server-url';\nimport { attrToProp, escapeString } from '#internal/shared/utils';\n\n// patch react/jsx-runtime to support the shadowrootmode attribute on template elements\ndeclare module 'react/jsx-runtime' {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n template: {\n shadowrootmode?: 'open' | 'closed';\n id?: string;\n ref?: React.Ref<HTMLTemplateElement>;\n dangerouslySetInnerHTML?: {\n __html: string;\n };\n children?: React.ReactNode;\n };\n }\n }\n}\n\n// import { shared } from 'remote-components/shared/host';\nasync function tryImportShared() {\n try {\n const { shared } = await import('remote-components/shared/host/app');\n return shared;\n } catch {\n return {};\n }\n}\n\n/**\n * RemoteComponentClient - Main component for rendering remote components\n *\n * This component handles the loading and rendering of remote microfrontends.\n * It supports both RSC (React Server Components) and Next.js Pages Router based components.\n */\nexport function RemoteComponentClient({\n src,\n serverUrl,\n name,\n bundle,\n route = DEFAULT_ROUTE,\n runtime = RUNTIME_WEBPACK,\n data,\n nextData,\n scripts = [],\n links = [],\n remoteShared = {},\n isolate,\n mode = 'open',\n reset,\n type,\n children,\n}: RemoteComponentProps) {\n const remoteComponentId = useId();\n const [component, setComponent] = useState<React.ReactNode | Error>(null);\n const url = getClientOrServerUrl(src, serverUrl);\n const metadataRef = useRef<{\n name: string;\n bundle: string;\n route: string;\n url: string;\n loading: boolean;\n }>({\n name,\n bundle,\n route,\n url: url.href,\n loading: false,\n });\n const startRef = useRef<HTMLTemplateElement | null>(null);\n const endRef = useRef<HTMLTemplateElement | null>(null);\n const prevRemoteComponentUnmountRef = useRef<{\n unmount: Set<MountOrUnmountFunction>;\n root: ShadowRoot | DocumentFragment | null;\n } | null>(null);\n\n // Handle errors by re-throwing them\n if (component instanceof Error) {\n throw component;\n }\n\n // determine whether to use children or loaded component\n const shouldUseChildren =\n (!component ||\n (component &&\n !nextData &&\n type !== 'remote-component' &&\n typeof (component as unknown as Promise<unknown>).then !==\n 'function')) &&\n // if the remote Next.js Pages Router application is in development mode\n // we don't use the provided static HTML\n // to mitigate layout shift when loading CSS using JavaScript on the client\n nextData?.buildId !== 'development';\n\n // The pathname is used so this URL is the same across server and client requests for relative src's\n const keySuffix = `${escapeString(bundle)}_${escapeString(\n url.pathname,\n )}_${escapeString(name)}`;\n\n const self = globalThis as Record<\n `__remote_components_shadowroot_${string}`,\n ShadowRoot | null\n > &\n Record<`__remote_components_container_${string}`, HTMLDivElement | null>;\n const shadowRootKey = `__remote_components_shadowroot_${keySuffix}` as const;\n const shadowContainerRef = useRef<HTMLDivElement | null>(\n typeof document === 'undefined'\n ? null\n : document.querySelector(\n `[data-remote-component-id=\"shadowroot_${remoteComponentId}\"]`,\n ),\n );\n const shadowRootRef = useRef<ShadowRoot | null>(\n self[shadowRootKey] ?? shadowContainerRef.current?.shadowRoot ?? null,\n );\n const ssrShadowRootContentRef = useRef<NodeListOf<ChildNode> | null>(\n shadowRootRef.current?.querySelectorAll('*') ?? null,\n );\n const ssrLinksStylesRef = useRef<(HTMLLinkElement | HTMLStyleElement)[]>([]);\n\n if (self[shadowRootKey] && shadowRootRef.current) {\n self[shadowRootKey] = null;\n }\n\n useLayoutEffect(() => {\n if (\n !shadowContainerRef.current ||\n shadowContainerRef.current !== shadowRootRef.current?.host\n ) {\n shadowRootRef.current = null;\n }\n\n if (\n isolate !== false &&\n typeof document !== 'undefined' &&\n !shadowRootRef.current\n ) {\n let shadowRootElement: ShadowRoot | null = null;\n const element = shadowContainerRef.current;\n\n shadowRootElement = self[shadowRootKey] ?? element?.shadowRoot ?? null;\n self[shadowRootKey] = null;\n\n if (!shadowRootElement && element) {\n // create a shadow root if it doesn't exist\n // this is a fallback for browsers that don't support declarative shadow DOM\n try {\n shadowRootElement = element.attachShadow({ mode });\n } catch {\n // do nothing if attachShadow fails because of existing shadow root\n }\n }\n\n if (shadowRootElement) {\n shadowRootRef.current = shadowRootElement;\n }\n }\n\n if (\n shadowRootRef.current &&\n ssrShadowRootContentRef.current &&\n !shouldUseChildren\n ) {\n // remove all nodes from the shadow root except links\n ssrShadowRootContentRef.current.forEach((node) => {\n if (node.nodeName !== 'LINK' && node.nodeName !== 'STYLE') {\n node.parentNode?.removeChild(node);\n } else {\n ssrLinksStylesRef.current.push(\n node as HTMLLinkElement | HTMLStyleElement,\n );\n }\n });\n ssrShadowRootContentRef.current = null;\n }\n\n if (ssrLinksStylesRef.current.length > 0 && shadowRootRef.current) {\n const waitForLoad =\n shadowRootRef.current.querySelectorAll('link[data-wait]');\n if (waitForLoad.length > 0) {\n Promise.all(\n Array.from(waitForLoad).map(\n (link) =>\n new Promise<void>((resolve) => {\n link.addEventListener('load', () => resolve());\n link.addEventListener('error', () => resolve());\n }),\n ),\n )\n .then(() => {\n waitForLoad.forEach((el) => {\n el.removeAttribute('data-wait');\n });\n\n // remove SSR injected styles and links\n ssrLinksStylesRef.current.forEach((el) => {\n el.parentNode?.removeChild(el);\n });\n ssrLinksStylesRef.current = [];\n })\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n });\n }\n }\n }, [isolate, mode, self, shadowRootKey, shouldUseChildren]);\n\n useEffect(() => {\n // run unmount functions when the component changes or unmounts\n if (prevRemoteComponentUnmountRef.current && component !== children) {\n const { unmount, root } = prevRemoteComponentUnmountRef.current;\n prevRemoteComponentUnmountRef.current = null;\n Promise.all(\n Array.from(unmount).map(async (unmountFn) => {\n try {\n await unmountFn(root);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n }\n }),\n ).catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n });\n }\n }, [component, children]);\n\n useEffect(() => {\n startTransition(async () => {\n try {\n // if we have a component, we don't need to load it again\n if (\n (!metadataRef.current.loading &&\n !component &&\n (isolate === false || shadowRootRef.current)) ||\n metadataRef.current.url !== url.href ||\n metadataRef.current.name !== name ||\n metadataRef.current.bundle !== bundle ||\n metadataRef.current.route !== route\n ) {\n metadataRef.current = {\n name,\n bundle,\n route,\n url: url.href,\n loading: true,\n };\n\n // use the children as the component when type is remote-component\n if (type === 'remote-component') {\n setComponent(children);\n // load static scripts and execute mount functions\n // run this async but don't await it as we render children immediately\n loadStaticRemoteComponent(scripts as HTMLScriptElement[], url)\n .then(({ mount, unmount }) => {\n if (mount.size > 0) {\n let root: ShadowRoot | DocumentFragment | null =\n shadowRootRef.current;\n try {\n if (!root && startRef.current && endRef.current) {\n root = document.querySelectorAll(\n `#${startRef.current.id} ~ *:not(#${endRef.current.id}):has(~ #${endRef.current.id})`,\n ) as unknown as DocumentFragment;\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n }\n if (unmount.size > 0) {\n prevRemoteComponentUnmountRef.current = { unmount, root };\n }\n return Promise.all(\n Array.from(mount).map((mountFn) => mountFn(root)),\n );\n }\n })\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n setComponent(e as Error);\n });\n return;\n }\n\n const rscName = `__remote_components_rsc_${keySuffix}`;\n const result = await loadRemoteComponent({\n url,\n name,\n bundle,\n route,\n runtime,\n rscName,\n data,\n nextData,\n scripts,\n shared: (async () => {\n const shared = await tryImportShared();\n\n if ('__remote_components_missing_shared__' in shared) {\n await shared.__remote_components_missing_shared__();\n }\n\n return {\n 'next/router': routerImpl,\n ...shared,\n 'next/image': () =>\n Promise.resolve(imageImpl(Image.default, bundle)),\n 'next/dist/client/image-component': () =>\n Promise.resolve({ Image: imageImpl(Image.default, bundle) }),\n };\n })(),\n remoteShared,\n container: shadowRootRef.current,\n });\n metadataRef.current.loading = false;\n if (result.error) {\n setComponent(result.error);\n } else {\n setComponent(result.component);\n }\n }\n } catch (error: unknown) {\n metadataRef.current.loading = false;\n setComponent(error as Error);\n }\n });\n }, [\n component,\n name,\n bundle,\n route,\n runtime,\n scripts,\n data,\n nextData,\n remoteShared,\n children,\n isolate,\n type,\n keySuffix,\n url,\n ]);\n\n if (\n nextData?.buildId === 'development' &&\n shadowRootRef.current &&\n isolate !== false &&\n reset &&\n !shadowRootRef.current.querySelector('[data-remote-components-reset]')\n ) {\n // inject reset styles into the shadow root\n const style = document.createElement('style');\n style.setAttribute('data-remote-components-reset', '');\n style.textContent = `:host { all: initial; }`;\n shadowRootRef.current.insertBefore(style, shadowRootRef.current.firstChild);\n } else if (\n shadowRootRef.current &&\n isolate !== false &&\n !reset &&\n shadowRootRef.current.querySelector('[data-remote-components-reset]')\n ) {\n // ensure reset styles are the first child in the shadow root\n const style = shadowRootRef.current.querySelector(\n '[data-remote-components-reset]',\n );\n if (style && shadowRootRef.current.firstChild !== style) {\n shadowRootRef.current.removeChild(style);\n }\n }\n\n const linksToRender = (\n <>\n {(!nextData || nextData.buildId !== 'development') &&\n isolate !== false &&\n reset ? (\n <style data-remote-components-reset=\"\">{`:host { all: initial; }`}</style>\n ) : null}\n {links.map((link) => (\n <RenderLink\n key={JSON.stringify(link)}\n link={link}\n url={url}\n serverUrl={serverUrl}\n data-wait={link.rel === 'stylesheet' && link.href ? '' : undefined}\n />\n ))}\n {links\n .filter((link) => link.rel === 'stylesheet')\n .map((link) => (\n <RenderLink\n key={JSON.stringify(link)}\n link={link}\n serverUrl={serverUrl}\n url={url}\n as=\"style\"\n fetchPriority=\"high\"\n precedence={bundle}\n rel=\"preload\"\n />\n ))}\n </>\n );\n\n let componentToRender = shouldUseChildren\n ? children\n : (component as React.ReactNode);\n\n if (isolate !== false) {\n componentToRender = (\n <div\n data-remote-component-id={`shadowroot_${remoteComponentId}`}\n data-remote-component-isolation-root=\"\"\n id={`shadowroot_${name}`}\n ref={shadowContainerRef}\n >\n {typeof document === 'undefined' ? (\n // eslint-disable-next-line react/no-unknown-property\n <template shadowrootmode={mode}>\n {mode === 'closed' ? (\n <div\n dangerouslySetInnerHTML={{\n __html: `<img\n alt=\"\" decoding=\"async\" style=\"display:none\"\n src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==\"\n onload=\"(function(el){\n const root = el.getRootNode();\n globalThis.${shadowRootKey} = root;\n el.parentElement.remove();\n })(this)\"\n />`,\n }}\n />\n ) : null}\n {linksToRender}\n {shouldUseChildren ? children : null}\n </template>\n ) : null}\n {typeof document !== 'undefined' &&\n shadowRootRef.current &&\n !shouldUseChildren\n ? createPortal(\n <>\n {linksToRender}\n {componentToRender}\n </>,\n shadowRootRef.current,\n )\n : null}\n </div>\n );\n }\n\n return (\n <>\n {isolate === false ? (\n <template id={`${name}_start`} ref={startRef} />\n ) : null}\n <script data-remote-component type=\"application/json\">\n {JSON.stringify({\n name,\n bundle,\n route,\n runtime,\n })}\n </script>\n {isolate === false ? linksToRender : null}\n {componentToRender}\n {nextData ? (\n <script\n id={`${bundle}_${route.replace(\n /[^a-zA-Z0-9]+/g,\n '_',\n )}${name}_next_data`}\n type=\"application/json\"\n >\n {JSON.stringify(nextData)}\n </script>\n ) : null}\n {isolate === false ? <template id={`${name}_end`} ref={endRef} /> : null}\n </>\n );\n}\n\nfunction RenderLink({\n link,\n url,\n serverUrl,\n ...rest\n}: {\n link: Record<string, string | boolean | undefined>;\n url: URL;\n serverUrl: string;\n} & React.LinkHTMLAttributes<HTMLLinkElement>) {\n return (\n <link\n {...Object.entries(link).reduce<Record<string, string>>(\n (acc, [key, value]) => {\n if (\n key !== 'href' &&\n key !== 'precedence' &&\n typeof value === 'string'\n ) {\n acc[attrToProp[key] ?? key] = value;\n }\n return acc;\n },\n {},\n )}\n href={getClientSrc(link.href, serverUrl)}\n {...rest}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from "react";
|
|
12
12
|
import { createPortal } from "react-dom";
|
|
13
13
|
import { imageImpl, routerImpl } from "#internal/next/host/app-router-compat";
|
|
14
|
+
import { getClientSrc } from "#internal/shared/client/get-client-src";
|
|
14
15
|
import {
|
|
15
16
|
DEFAULT_ROUTE,
|
|
16
17
|
loadRemoteComponent,
|
|
@@ -269,6 +270,7 @@ function RemoteComponentClient({
|
|
|
269
270
|
{
|
|
270
271
|
link,
|
|
271
272
|
url,
|
|
273
|
+
serverUrl,
|
|
272
274
|
"data-wait": link.rel === "stylesheet" && link.href ? "" : void 0
|
|
273
275
|
},
|
|
274
276
|
JSON.stringify(link)
|
|
@@ -277,6 +279,7 @@ function RemoteComponentClient({
|
|
|
277
279
|
RenderLink,
|
|
278
280
|
{
|
|
279
281
|
link,
|
|
282
|
+
serverUrl,
|
|
280
283
|
url,
|
|
281
284
|
as: "style",
|
|
282
285
|
fetchPriority: "high",
|
|
@@ -357,6 +360,7 @@ function RemoteComponentClient({
|
|
|
357
360
|
function RenderLink({
|
|
358
361
|
link,
|
|
359
362
|
url,
|
|
363
|
+
serverUrl,
|
|
360
364
|
...rest
|
|
361
365
|
}) {
|
|
362
366
|
return /* @__PURE__ */ jsx(
|
|
@@ -371,7 +375,7 @@ function RenderLink({
|
|
|
371
375
|
},
|
|
372
376
|
{}
|
|
373
377
|
),
|
|
374
|
-
href:
|
|
378
|
+
href: getClientSrc(link.href, serverUrl),
|
|
375
379
|
...rest
|
|
376
380
|
}
|
|
377
381
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/next/host/app-router-client.tsx"],"sourcesContent":["'use client';\n\nimport * as Image from 'next/image';\nimport {\n startTransition,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { imageImpl, routerImpl } from '#internal/next/host/app-router-compat';\nimport type { RemoteComponentProps } from '#internal/shared/client/remote-component';\nimport {\n DEFAULT_ROUTE,\n loadRemoteComponent,\n loadStaticRemoteComponent,\n RUNTIME_WEBPACK,\n} from '#internal/shared/client/remote-component';\nimport type { MountOrUnmountFunction } from '#internal/shared/client/types';\nimport { getClientOrServerUrl } from '#internal/shared/ssr/get-client-or-server-url';\nimport { attrToProp, escapeString } from '#internal/shared/utils';\n\n// patch react/jsx-runtime to support the shadowrootmode attribute on template elements\ndeclare module 'react/jsx-runtime' {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n template: {\n shadowrootmode?: 'open' | 'closed';\n id?: string;\n ref?: React.Ref<HTMLTemplateElement>;\n dangerouslySetInnerHTML?: {\n __html: string;\n };\n children?: React.ReactNode;\n };\n }\n }\n}\n\n// import { shared } from 'remote-components/shared/host';\nasync function tryImportShared() {\n try {\n const { shared } = await import('remote-components/shared/host/app');\n return shared;\n } catch {\n return {};\n }\n}\n\n/**\n * RemoteComponentClient - Main component for rendering remote components\n *\n * This component handles the loading and rendering of remote microfrontends.\n * It supports both RSC (React Server Components) and Next.js Pages Router based components.\n */\nexport function RemoteComponentClient({\n src,\n serverUrl,\n name,\n bundle,\n route = DEFAULT_ROUTE,\n runtime = RUNTIME_WEBPACK,\n data,\n nextData,\n scripts = [],\n links = [],\n remoteShared = {},\n isolate,\n mode = 'open',\n reset,\n type,\n children,\n}: RemoteComponentProps) {\n const remoteComponentId = useId();\n const [component, setComponent] = useState<React.ReactNode | Error>(null);\n const url = getClientOrServerUrl(src, serverUrl);\n const metadataRef = useRef<{\n name: string;\n bundle: string;\n route: string;\n url: string;\n loading: boolean;\n }>({\n name,\n bundle,\n route,\n url: url.href,\n loading: false,\n });\n const startRef = useRef<HTMLTemplateElement | null>(null);\n const endRef = useRef<HTMLTemplateElement | null>(null);\n const prevRemoteComponentUnmountRef = useRef<{\n unmount: Set<MountOrUnmountFunction>;\n root: ShadowRoot | DocumentFragment | null;\n } | null>(null);\n\n // Handle errors by re-throwing them\n if (component instanceof Error) {\n throw component;\n }\n\n // determine whether to use children or loaded component\n const shouldUseChildren =\n (!component ||\n (component &&\n !nextData &&\n type !== 'remote-component' &&\n typeof (component as unknown as Promise<unknown>).then !==\n 'function')) &&\n // if the remote Next.js Pages Router application is in development mode\n // we don't use the provided static HTML\n // to mitigate layout shift when loading CSS using JavaScript on the client\n nextData?.buildId !== 'development';\n\n // The pathname is used so this URL is the same across server and client requests for relative src's\n const keySuffix = `${escapeString(bundle)}_${escapeString(\n url.pathname,\n )}_${escapeString(name)}`;\n\n const self = globalThis as Record<\n `__remote_components_shadowroot_${string}`,\n ShadowRoot | null\n > &\n Record<`__remote_components_container_${string}`, HTMLDivElement | null>;\n const shadowRootKey = `__remote_components_shadowroot_${keySuffix}` as const;\n const shadowContainerRef = useRef<HTMLDivElement | null>(\n typeof document === 'undefined'\n ? null\n : document.querySelector(\n `[data-remote-component-id=\"shadowroot_${remoteComponentId}\"]`,\n ),\n );\n const shadowRootRef = useRef<ShadowRoot | null>(\n self[shadowRootKey] ?? shadowContainerRef.current?.shadowRoot ?? null,\n );\n const ssrShadowRootContentRef = useRef<NodeListOf<ChildNode> | null>(\n shadowRootRef.current?.querySelectorAll('*') ?? null,\n );\n const ssrLinksStylesRef = useRef<(HTMLLinkElement | HTMLStyleElement)[]>([]);\n\n if (self[shadowRootKey] && shadowRootRef.current) {\n self[shadowRootKey] = null;\n }\n\n useLayoutEffect(() => {\n if (\n !shadowContainerRef.current ||\n shadowContainerRef.current !== shadowRootRef.current?.host\n ) {\n shadowRootRef.current = null;\n }\n\n if (\n isolate !== false &&\n typeof document !== 'undefined' &&\n !shadowRootRef.current\n ) {\n let shadowRootElement: ShadowRoot | null = null;\n const element = shadowContainerRef.current;\n\n shadowRootElement = self[shadowRootKey] ?? element?.shadowRoot ?? null;\n self[shadowRootKey] = null;\n\n if (!shadowRootElement && element) {\n // create a shadow root if it doesn't exist\n // this is a fallback for browsers that don't support declarative shadow DOM\n try {\n shadowRootElement = element.attachShadow({ mode });\n } catch {\n // do nothing if attachShadow fails because of existing shadow root\n }\n }\n\n if (shadowRootElement) {\n shadowRootRef.current = shadowRootElement;\n }\n }\n\n if (\n shadowRootRef.current &&\n ssrShadowRootContentRef.current &&\n !shouldUseChildren\n ) {\n // remove all nodes from the shadow root except links\n ssrShadowRootContentRef.current.forEach((node) => {\n if (node.nodeName !== 'LINK' && node.nodeName !== 'STYLE') {\n node.parentNode?.removeChild(node);\n } else {\n ssrLinksStylesRef.current.push(\n node as HTMLLinkElement | HTMLStyleElement,\n );\n }\n });\n ssrShadowRootContentRef.current = null;\n }\n\n if (ssrLinksStylesRef.current.length > 0 && shadowRootRef.current) {\n const waitForLoad =\n shadowRootRef.current.querySelectorAll('link[data-wait]');\n if (waitForLoad.length > 0) {\n Promise.all(\n Array.from(waitForLoad).map(\n (link) =>\n new Promise<void>((resolve) => {\n link.addEventListener('load', () => resolve());\n link.addEventListener('error', () => resolve());\n }),\n ),\n )\n .then(() => {\n waitForLoad.forEach((el) => {\n el.removeAttribute('data-wait');\n });\n\n // remove SSR injected styles and links\n ssrLinksStylesRef.current.forEach((el) => {\n el.parentNode?.removeChild(el);\n });\n ssrLinksStylesRef.current = [];\n })\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n });\n }\n }\n }, [isolate, mode, self, shadowRootKey, shouldUseChildren]);\n\n useEffect(() => {\n // run unmount functions when the component changes or unmounts\n if (prevRemoteComponentUnmountRef.current && component !== children) {\n const { unmount, root } = prevRemoteComponentUnmountRef.current;\n prevRemoteComponentUnmountRef.current = null;\n Promise.all(\n Array.from(unmount).map(async (unmountFn) => {\n try {\n await unmountFn(root);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n }\n }),\n ).catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n });\n }\n }, [component, children]);\n\n useEffect(() => {\n startTransition(async () => {\n try {\n // if we have a component, we don't need to load it again\n if (\n (!metadataRef.current.loading &&\n !component &&\n (isolate === false || shadowRootRef.current)) ||\n metadataRef.current.url !== url.href ||\n metadataRef.current.name !== name ||\n metadataRef.current.bundle !== bundle ||\n metadataRef.current.route !== route\n ) {\n metadataRef.current = {\n name,\n bundle,\n route,\n url: url.href,\n loading: true,\n };\n\n // use the children as the component when type is remote-component\n if (type === 'remote-component') {\n setComponent(children);\n // load static scripts and execute mount functions\n // run this async but don't await it as we render children immediately\n loadStaticRemoteComponent(scripts as HTMLScriptElement[], url)\n .then(({ mount, unmount }) => {\n if (mount.size > 0) {\n let root: ShadowRoot | DocumentFragment | null =\n shadowRootRef.current;\n try {\n if (!root && startRef.current && endRef.current) {\n root = document.querySelectorAll(\n `#${startRef.current.id} ~ *:not(#${endRef.current.id}):has(~ #${endRef.current.id})`,\n ) as unknown as DocumentFragment;\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n }\n if (unmount.size > 0) {\n prevRemoteComponentUnmountRef.current = { unmount, root };\n }\n return Promise.all(\n Array.from(mount).map((mountFn) => mountFn(root)),\n );\n }\n })\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n setComponent(e as Error);\n });\n return;\n }\n\n const rscName = `__remote_components_rsc_${keySuffix}`;\n const result = await loadRemoteComponent({\n url,\n name,\n bundle,\n route,\n runtime,\n rscName,\n data,\n nextData,\n scripts,\n shared: (async () => {\n const shared = await tryImportShared();\n\n if ('__remote_components_missing_shared__' in shared) {\n await shared.__remote_components_missing_shared__();\n }\n\n return {\n 'next/router': routerImpl,\n ...shared,\n 'next/image': () =>\n Promise.resolve(imageImpl(Image.default, bundle)),\n 'next/dist/client/image-component': () =>\n Promise.resolve({ Image: imageImpl(Image.default, bundle) }),\n };\n })(),\n remoteShared,\n container: shadowRootRef.current,\n });\n metadataRef.current.loading = false;\n if (result.error) {\n setComponent(result.error);\n } else {\n setComponent(result.component);\n }\n }\n } catch (error: unknown) {\n metadataRef.current.loading = false;\n setComponent(error as Error);\n }\n });\n }, [\n component,\n name,\n bundle,\n route,\n runtime,\n scripts,\n data,\n nextData,\n remoteShared,\n children,\n isolate,\n type,\n keySuffix,\n url,\n ]);\n\n if (\n nextData?.buildId === 'development' &&\n shadowRootRef.current &&\n isolate !== false &&\n reset &&\n !shadowRootRef.current.querySelector('[data-remote-components-reset]')\n ) {\n // inject reset styles into the shadow root\n const style = document.createElement('style');\n style.setAttribute('data-remote-components-reset', '');\n style.textContent = `:host { all: initial; }`;\n shadowRootRef.current.insertBefore(style, shadowRootRef.current.firstChild);\n } else if (\n shadowRootRef.current &&\n isolate !== false &&\n !reset &&\n shadowRootRef.current.querySelector('[data-remote-components-reset]')\n ) {\n // ensure reset styles are the first child in the shadow root\n const style = shadowRootRef.current.querySelector(\n '[data-remote-components-reset]',\n );\n if (style && shadowRootRef.current.firstChild !== style) {\n shadowRootRef.current.removeChild(style);\n }\n }\n\n const linksToRender = (\n <>\n {(!nextData || nextData.buildId !== 'development') &&\n isolate !== false &&\n reset ? (\n <style data-remote-components-reset=\"\">{`:host { all: initial; }`}</style>\n ) : null}\n {links.map((link) => (\n <RenderLink\n key={JSON.stringify(link)}\n link={link}\n url={url}\n data-wait={link.rel === 'stylesheet' && link.href ? '' : undefined}\n />\n ))}\n {links\n .filter((link) => link.rel === 'stylesheet')\n .map((link) => (\n <RenderLink\n key={JSON.stringify(link)}\n link={link}\n url={url}\n as=\"style\"\n fetchPriority=\"high\"\n precedence={bundle}\n rel=\"preload\"\n />\n ))}\n </>\n );\n\n let componentToRender = shouldUseChildren\n ? children\n : (component as React.ReactNode);\n\n if (isolate !== false) {\n componentToRender = (\n <div\n data-remote-component-id={`shadowroot_${remoteComponentId}`}\n data-remote-component-isolation-root=\"\"\n id={`shadowroot_${name}`}\n ref={shadowContainerRef}\n >\n {typeof document === 'undefined' ? (\n // eslint-disable-next-line react/no-unknown-property\n <template shadowrootmode={mode}>\n {mode === 'closed' ? (\n <div\n dangerouslySetInnerHTML={{\n __html: `<img\n alt=\"\" decoding=\"async\" style=\"display:none\"\n src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==\"\n onload=\"(function(el){\n const root = el.getRootNode();\n globalThis.${shadowRootKey} = root;\n el.parentElement.remove();\n })(this)\"\n />`,\n }}\n />\n ) : null}\n {linksToRender}\n {shouldUseChildren ? children : null}\n </template>\n ) : null}\n {typeof document !== 'undefined' &&\n shadowRootRef.current &&\n !shouldUseChildren\n ? createPortal(\n <>\n {linksToRender}\n {componentToRender}\n </>,\n shadowRootRef.current,\n )\n : null}\n </div>\n );\n }\n\n return (\n <>\n {isolate === false ? (\n <template id={`${name}_start`} ref={startRef} />\n ) : null}\n <script data-remote-component type=\"application/json\">\n {JSON.stringify({\n name,\n bundle,\n route,\n runtime,\n })}\n </script>\n {isolate === false ? linksToRender : null}\n {componentToRender}\n {nextData ? (\n <script\n id={`${bundle}_${route.replace(\n /[^a-zA-Z0-9]+/g,\n '_',\n )}${name}_next_data`}\n type=\"application/json\"\n >\n {JSON.stringify(nextData)}\n </script>\n ) : null}\n {isolate === false ? <template id={`${name}_end`} ref={endRef} /> : null}\n </>\n );\n}\n\nfunction RenderLink({\n link,\n url,\n ...rest\n}: {\n link: Record<string, string | boolean | undefined>;\n url: URL;\n} & React.LinkHTMLAttributes<HTMLLinkElement>) {\n return (\n <link\n {...Object.entries(link).reduce<Record<string, string>>(\n (acc, [key, value]) => {\n if (\n key !== 'href' &&\n key !== 'precedence' &&\n typeof value === 'string'\n ) {\n acc[attrToProp[key] ?? key] = value;\n }\n return acc;\n },\n {},\n )}\n href={\n typeof link.href === 'string' ? new URL(link.href, url).href : undefined\n }\n {...rest}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/next/host/app-router-client.tsx"],"sourcesContent":["'use client';\n\nimport * as Image from 'next/image';\nimport {\n startTransition,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { imageImpl, routerImpl } from '#internal/next/host/app-router-compat';\nimport { getClientSrc } from '#internal/shared/client/get-client-src';\nimport type { RemoteComponentProps } from '#internal/shared/client/remote-component';\nimport {\n DEFAULT_ROUTE,\n loadRemoteComponent,\n loadStaticRemoteComponent,\n RUNTIME_WEBPACK,\n} from '#internal/shared/client/remote-component';\nimport type { MountOrUnmountFunction } from '#internal/shared/client/types';\nimport { getClientOrServerUrl } from '#internal/shared/ssr/get-client-or-server-url';\nimport { attrToProp, escapeString } from '#internal/shared/utils';\n\n// patch react/jsx-runtime to support the shadowrootmode attribute on template elements\ndeclare module 'react/jsx-runtime' {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n template: {\n shadowrootmode?: 'open' | 'closed';\n id?: string;\n ref?: React.Ref<HTMLTemplateElement>;\n dangerouslySetInnerHTML?: {\n __html: string;\n };\n children?: React.ReactNode;\n };\n }\n }\n}\n\n// import { shared } from 'remote-components/shared/host';\nasync function tryImportShared() {\n try {\n const { shared } = await import('remote-components/shared/host/app');\n return shared;\n } catch {\n return {};\n }\n}\n\n/**\n * RemoteComponentClient - Main component for rendering remote components\n *\n * This component handles the loading and rendering of remote microfrontends.\n * It supports both RSC (React Server Components) and Next.js Pages Router based components.\n */\nexport function RemoteComponentClient({\n src,\n serverUrl,\n name,\n bundle,\n route = DEFAULT_ROUTE,\n runtime = RUNTIME_WEBPACK,\n data,\n nextData,\n scripts = [],\n links = [],\n remoteShared = {},\n isolate,\n mode = 'open',\n reset,\n type,\n children,\n}: RemoteComponentProps) {\n const remoteComponentId = useId();\n const [component, setComponent] = useState<React.ReactNode | Error>(null);\n const url = getClientOrServerUrl(src, serverUrl);\n const metadataRef = useRef<{\n name: string;\n bundle: string;\n route: string;\n url: string;\n loading: boolean;\n }>({\n name,\n bundle,\n route,\n url: url.href,\n loading: false,\n });\n const startRef = useRef<HTMLTemplateElement | null>(null);\n const endRef = useRef<HTMLTemplateElement | null>(null);\n const prevRemoteComponentUnmountRef = useRef<{\n unmount: Set<MountOrUnmountFunction>;\n root: ShadowRoot | DocumentFragment | null;\n } | null>(null);\n\n // Handle errors by re-throwing them\n if (component instanceof Error) {\n throw component;\n }\n\n // determine whether to use children or loaded component\n const shouldUseChildren =\n (!component ||\n (component &&\n !nextData &&\n type !== 'remote-component' &&\n typeof (component as unknown as Promise<unknown>).then !==\n 'function')) &&\n // if the remote Next.js Pages Router application is in development mode\n // we don't use the provided static HTML\n // to mitigate layout shift when loading CSS using JavaScript on the client\n nextData?.buildId !== 'development';\n\n // The pathname is used so this URL is the same across server and client requests for relative src's\n const keySuffix = `${escapeString(bundle)}_${escapeString(\n url.pathname,\n )}_${escapeString(name)}`;\n\n const self = globalThis as Record<\n `__remote_components_shadowroot_${string}`,\n ShadowRoot | null\n > &\n Record<`__remote_components_container_${string}`, HTMLDivElement | null>;\n const shadowRootKey = `__remote_components_shadowroot_${keySuffix}` as const;\n const shadowContainerRef = useRef<HTMLDivElement | null>(\n typeof document === 'undefined'\n ? null\n : document.querySelector(\n `[data-remote-component-id=\"shadowroot_${remoteComponentId}\"]`,\n ),\n );\n const shadowRootRef = useRef<ShadowRoot | null>(\n self[shadowRootKey] ?? shadowContainerRef.current?.shadowRoot ?? null,\n );\n const ssrShadowRootContentRef = useRef<NodeListOf<ChildNode> | null>(\n shadowRootRef.current?.querySelectorAll('*') ?? null,\n );\n const ssrLinksStylesRef = useRef<(HTMLLinkElement | HTMLStyleElement)[]>([]);\n\n if (self[shadowRootKey] && shadowRootRef.current) {\n self[shadowRootKey] = null;\n }\n\n useLayoutEffect(() => {\n if (\n !shadowContainerRef.current ||\n shadowContainerRef.current !== shadowRootRef.current?.host\n ) {\n shadowRootRef.current = null;\n }\n\n if (\n isolate !== false &&\n typeof document !== 'undefined' &&\n !shadowRootRef.current\n ) {\n let shadowRootElement: ShadowRoot | null = null;\n const element = shadowContainerRef.current;\n\n shadowRootElement = self[shadowRootKey] ?? element?.shadowRoot ?? null;\n self[shadowRootKey] = null;\n\n if (!shadowRootElement && element) {\n // create a shadow root if it doesn't exist\n // this is a fallback for browsers that don't support declarative shadow DOM\n try {\n shadowRootElement = element.attachShadow({ mode });\n } catch {\n // do nothing if attachShadow fails because of existing shadow root\n }\n }\n\n if (shadowRootElement) {\n shadowRootRef.current = shadowRootElement;\n }\n }\n\n if (\n shadowRootRef.current &&\n ssrShadowRootContentRef.current &&\n !shouldUseChildren\n ) {\n // remove all nodes from the shadow root except links\n ssrShadowRootContentRef.current.forEach((node) => {\n if (node.nodeName !== 'LINK' && node.nodeName !== 'STYLE') {\n node.parentNode?.removeChild(node);\n } else {\n ssrLinksStylesRef.current.push(\n node as HTMLLinkElement | HTMLStyleElement,\n );\n }\n });\n ssrShadowRootContentRef.current = null;\n }\n\n if (ssrLinksStylesRef.current.length > 0 && shadowRootRef.current) {\n const waitForLoad =\n shadowRootRef.current.querySelectorAll('link[data-wait]');\n if (waitForLoad.length > 0) {\n Promise.all(\n Array.from(waitForLoad).map(\n (link) =>\n new Promise<void>((resolve) => {\n link.addEventListener('load', () => resolve());\n link.addEventListener('error', () => resolve());\n }),\n ),\n )\n .then(() => {\n waitForLoad.forEach((el) => {\n el.removeAttribute('data-wait');\n });\n\n // remove SSR injected styles and links\n ssrLinksStylesRef.current.forEach((el) => {\n el.parentNode?.removeChild(el);\n });\n ssrLinksStylesRef.current = [];\n })\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n });\n }\n }\n }, [isolate, mode, self, shadowRootKey, shouldUseChildren]);\n\n useEffect(() => {\n // run unmount functions when the component changes or unmounts\n if (prevRemoteComponentUnmountRef.current && component !== children) {\n const { unmount, root } = prevRemoteComponentUnmountRef.current;\n prevRemoteComponentUnmountRef.current = null;\n Promise.all(\n Array.from(unmount).map(async (unmountFn) => {\n try {\n await unmountFn(root);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n }\n }),\n ).catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n });\n }\n }, [component, children]);\n\n useEffect(() => {\n startTransition(async () => {\n try {\n // if we have a component, we don't need to load it again\n if (\n (!metadataRef.current.loading &&\n !component &&\n (isolate === false || shadowRootRef.current)) ||\n metadataRef.current.url !== url.href ||\n metadataRef.current.name !== name ||\n metadataRef.current.bundle !== bundle ||\n metadataRef.current.route !== route\n ) {\n metadataRef.current = {\n name,\n bundle,\n route,\n url: url.href,\n loading: true,\n };\n\n // use the children as the component when type is remote-component\n if (type === 'remote-component') {\n setComponent(children);\n // load static scripts and execute mount functions\n // run this async but don't await it as we render children immediately\n loadStaticRemoteComponent(scripts as HTMLScriptElement[], url)\n .then(({ mount, unmount }) => {\n if (mount.size > 0) {\n let root: ShadowRoot | DocumentFragment | null =\n shadowRootRef.current;\n try {\n if (!root && startRef.current && endRef.current) {\n root = document.querySelectorAll(\n `#${startRef.current.id} ~ *:not(#${endRef.current.id}):has(~ #${endRef.current.id})`,\n ) as unknown as DocumentFragment;\n }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(e);\n }\n if (unmount.size > 0) {\n prevRemoteComponentUnmountRef.current = { unmount, root };\n }\n return Promise.all(\n Array.from(mount).map((mountFn) => mountFn(root)),\n );\n }\n })\n .catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e);\n setComponent(e as Error);\n });\n return;\n }\n\n const rscName = `__remote_components_rsc_${keySuffix}`;\n const result = await loadRemoteComponent({\n url,\n name,\n bundle,\n route,\n runtime,\n rscName,\n data,\n nextData,\n scripts,\n shared: (async () => {\n const shared = await tryImportShared();\n\n if ('__remote_components_missing_shared__' in shared) {\n await shared.__remote_components_missing_shared__();\n }\n\n return {\n 'next/router': routerImpl,\n ...shared,\n 'next/image': () =>\n Promise.resolve(imageImpl(Image.default, bundle)),\n 'next/dist/client/image-component': () =>\n Promise.resolve({ Image: imageImpl(Image.default, bundle) }),\n };\n })(),\n remoteShared,\n container: shadowRootRef.current,\n });\n metadataRef.current.loading = false;\n if (result.error) {\n setComponent(result.error);\n } else {\n setComponent(result.component);\n }\n }\n } catch (error: unknown) {\n metadataRef.current.loading = false;\n setComponent(error as Error);\n }\n });\n }, [\n component,\n name,\n bundle,\n route,\n runtime,\n scripts,\n data,\n nextData,\n remoteShared,\n children,\n isolate,\n type,\n keySuffix,\n url,\n ]);\n\n if (\n nextData?.buildId === 'development' &&\n shadowRootRef.current &&\n isolate !== false &&\n reset &&\n !shadowRootRef.current.querySelector('[data-remote-components-reset]')\n ) {\n // inject reset styles into the shadow root\n const style = document.createElement('style');\n style.setAttribute('data-remote-components-reset', '');\n style.textContent = `:host { all: initial; }`;\n shadowRootRef.current.insertBefore(style, shadowRootRef.current.firstChild);\n } else if (\n shadowRootRef.current &&\n isolate !== false &&\n !reset &&\n shadowRootRef.current.querySelector('[data-remote-components-reset]')\n ) {\n // ensure reset styles are the first child in the shadow root\n const style = shadowRootRef.current.querySelector(\n '[data-remote-components-reset]',\n );\n if (style && shadowRootRef.current.firstChild !== style) {\n shadowRootRef.current.removeChild(style);\n }\n }\n\n const linksToRender = (\n <>\n {(!nextData || nextData.buildId !== 'development') &&\n isolate !== false &&\n reset ? (\n <style data-remote-components-reset=\"\">{`:host { all: initial; }`}</style>\n ) : null}\n {links.map((link) => (\n <RenderLink\n key={JSON.stringify(link)}\n link={link}\n url={url}\n serverUrl={serverUrl}\n data-wait={link.rel === 'stylesheet' && link.href ? '' : undefined}\n />\n ))}\n {links\n .filter((link) => link.rel === 'stylesheet')\n .map((link) => (\n <RenderLink\n key={JSON.stringify(link)}\n link={link}\n serverUrl={serverUrl}\n url={url}\n as=\"style\"\n fetchPriority=\"high\"\n precedence={bundle}\n rel=\"preload\"\n />\n ))}\n </>\n );\n\n let componentToRender = shouldUseChildren\n ? children\n : (component as React.ReactNode);\n\n if (isolate !== false) {\n componentToRender = (\n <div\n data-remote-component-id={`shadowroot_${remoteComponentId}`}\n data-remote-component-isolation-root=\"\"\n id={`shadowroot_${name}`}\n ref={shadowContainerRef}\n >\n {typeof document === 'undefined' ? (\n // eslint-disable-next-line react/no-unknown-property\n <template shadowrootmode={mode}>\n {mode === 'closed' ? (\n <div\n dangerouslySetInnerHTML={{\n __html: `<img\n alt=\"\" decoding=\"async\" style=\"display:none\"\n src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==\"\n onload=\"(function(el){\n const root = el.getRootNode();\n globalThis.${shadowRootKey} = root;\n el.parentElement.remove();\n })(this)\"\n />`,\n }}\n />\n ) : null}\n {linksToRender}\n {shouldUseChildren ? children : null}\n </template>\n ) : null}\n {typeof document !== 'undefined' &&\n shadowRootRef.current &&\n !shouldUseChildren\n ? createPortal(\n <>\n {linksToRender}\n {componentToRender}\n </>,\n shadowRootRef.current,\n )\n : null}\n </div>\n );\n }\n\n return (\n <>\n {isolate === false ? (\n <template id={`${name}_start`} ref={startRef} />\n ) : null}\n <script data-remote-component type=\"application/json\">\n {JSON.stringify({\n name,\n bundle,\n route,\n runtime,\n })}\n </script>\n {isolate === false ? linksToRender : null}\n {componentToRender}\n {nextData ? (\n <script\n id={`${bundle}_${route.replace(\n /[^a-zA-Z0-9]+/g,\n '_',\n )}${name}_next_data`}\n type=\"application/json\"\n >\n {JSON.stringify(nextData)}\n </script>\n ) : null}\n {isolate === false ? <template id={`${name}_end`} ref={endRef} /> : null}\n </>\n );\n}\n\nfunction RenderLink({\n link,\n url,\n serverUrl,\n ...rest\n}: {\n link: Record<string, string | boolean | undefined>;\n url: URL;\n serverUrl: string;\n} & React.LinkHTMLAttributes<HTMLLinkElement>) {\n return (\n <link\n {...Object.entries(link).reduce<Record<string, string>>(\n (acc, [key, value]) => {\n if (\n key !== 'href' &&\n key !== 'precedence' &&\n typeof value === 'string'\n ) {\n acc[attrToProp[key] ?? key] = value;\n }\n return acc;\n },\n {},\n )}\n href={getClientSrc(link.href, serverUrl)}\n {...rest}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var get_client_src_exports = {};
|
|
20
|
+
__export(get_client_src_exports, {
|
|
21
|
+
getClientSrc: () => getClientSrc
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(get_client_src_exports);
|
|
24
|
+
var import_get_ssr_relative_path_base_url = require("#internal/shared/ssr/get-ssr-relative-path-base-url");
|
|
25
|
+
function getClientSrc(src, serverUrl) {
|
|
26
|
+
if (typeof src !== "string") {
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
29
|
+
const url = new URL(src, serverUrl);
|
|
30
|
+
if (url.origin === (0, import_get_ssr_relative_path_base_url.getSSRRelativePathBaseUrl)()) {
|
|
31
|
+
return `${url.pathname}${url.search}`;
|
|
32
|
+
}
|
|
33
|
+
return url.href;
|
|
34
|
+
}
|
|
35
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
36
|
+
0 && (module.exports = {
|
|
37
|
+
getClientSrc
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=get-client-src.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/shared/client/get-client-src.ts"],"sourcesContent":["import { getSSRRelativePathBaseUrl } from '#internal/shared/ssr/get-ssr-relative-path-base-url';\n\n/**\n * If a relative src was provided, but the server url base was used for SSR,\n * use the relative path as the src.\n */\nexport function getClientSrc(\n src: string | boolean | undefined,\n serverUrl: string,\n): string {\n if (typeof src !== 'string') {\n return '';\n }\n\n const url = new URL(src, serverUrl);\n\n if (url.origin === getSSRRelativePathBaseUrl()) {\n return `${url.pathname}${url.search}`;\n }\n\n return url.href;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4CAA0C;AAMnC,SAAS,aACd,KACA,WACQ;AACR,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,IAAI,IAAI,KAAK,SAAS;AAElC,MAAI,IAAI,eAAW,iEAA0B,GAAG;AAC9C,WAAO,GAAG,IAAI,WAAW,IAAI;AAAA,EAC/B;AAEA,SAAO,IAAI;AACb;","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getSSRRelativePathBaseUrl } from "#internal/shared/ssr/get-ssr-relative-path-base-url";
|
|
2
|
+
function getClientSrc(src, serverUrl) {
|
|
3
|
+
if (typeof src !== "string") {
|
|
4
|
+
return "";
|
|
5
|
+
}
|
|
6
|
+
const url = new URL(src, serverUrl);
|
|
7
|
+
if (url.origin === getSSRRelativePathBaseUrl()) {
|
|
8
|
+
return `${url.pathname}${url.search}`;
|
|
9
|
+
}
|
|
10
|
+
return url.href;
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
getClientSrc
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=get-client-src.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/shared/client/get-client-src.ts"],"sourcesContent":["import { getSSRRelativePathBaseUrl } from '#internal/shared/ssr/get-ssr-relative-path-base-url';\n\n/**\n * If a relative src was provided, but the server url base was used for SSR,\n * use the relative path as the src.\n */\nexport function getClientSrc(\n src: string | boolean | undefined,\n serverUrl: string,\n): string {\n if (typeof src !== 'string') {\n return '';\n }\n\n const url = new URL(src, serverUrl);\n\n if (url.origin === getSSRRelativePathBaseUrl()) {\n return `${url.pathname}${url.search}`;\n }\n\n return url.href;\n}\n"],"mappings":"AAAA,SAAS,iCAAiC;AAMnC,SAAS,aACd,KACA,WACQ;AACR,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,IAAI,IAAI,KAAK,SAAS;AAElC,MAAI,IAAI,WAAW,0BAA0B,GAAG;AAC9C,WAAO,GAAG,IAAI,WAAW,IAAI;AAAA,EAC/B;AAEA,SAAO,IAAI;AACb;","names":[]}
|
|
@@ -33,9 +33,11 @@ __export(fetch_remote_component_exports, {
|
|
|
33
33
|
});
|
|
34
34
|
module.exports = __toCommonJS(fetch_remote_component_exports);
|
|
35
35
|
var import_parse5 = require("parse5");
|
|
36
|
+
var import_get_client_src = require("#internal/shared/client/get-client-src");
|
|
36
37
|
var import_error = require("#internal/shared/error");
|
|
37
38
|
var import_dom_flight = require("#internal/shared/ssr/dom-flight");
|
|
38
39
|
var import_fetch_headers = require("#internal/shared/ssr/fetch-headers");
|
|
40
|
+
var import_get_ssr_relative_path_base_url = require("#internal/shared/ssr/get-ssr-relative-path-base-url");
|
|
39
41
|
const CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;
|
|
40
42
|
function getBaseUrl(reqHeaders) {
|
|
41
43
|
const host = reqHeaders.get("host");
|
|
@@ -46,10 +48,7 @@ function getBaseUrl(reqHeaders) {
|
|
|
46
48
|
if (forwardedHost) {
|
|
47
49
|
return `https://${forwardedHost}`;
|
|
48
50
|
}
|
|
49
|
-
|
|
50
|
-
return `https://${process.env.VERCEL_URL}`;
|
|
51
|
-
}
|
|
52
|
-
return `http://localhost:${process.env.MFE_LOCAL_PROXY_PORT || 3024}`;
|
|
51
|
+
return (0, import_get_ssr_relative_path_base_url.getSSRRelativePathBaseUrl)();
|
|
53
52
|
}
|
|
54
53
|
async function fetchRemoteComponent(src, headers = new Headers(), options = {
|
|
55
54
|
rsc: false
|
|
@@ -109,19 +108,24 @@ async function fetchRemoteComponent(src, headers = new Headers(), options = {
|
|
|
109
108
|
hasRemoteComponent = true;
|
|
110
109
|
},
|
|
111
110
|
onScript(attrs) {
|
|
111
|
+
const clientSrc = (0, import_get_client_src.getClientSrc)(attrs.src, serverUrl.href);
|
|
112
112
|
if (!scripts.find(
|
|
113
|
-
(it) => it.src ===
|
|
113
|
+
(it) => it.src === clientSrc || attrs.textContent && it.textContent === attrs.textContent
|
|
114
114
|
)) {
|
|
115
|
-
scripts.push(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
scripts.push(
|
|
116
|
+
typeof attrs.textContent === "string" ? {
|
|
117
|
+
src: "",
|
|
118
|
+
textContent: attrs.textContent
|
|
119
|
+
} : {
|
|
120
|
+
src: clientSrc
|
|
121
|
+
}
|
|
122
|
+
);
|
|
119
123
|
}
|
|
120
124
|
},
|
|
121
125
|
onLink(attrs) {
|
|
122
126
|
const relativeAttrs = {
|
|
123
127
|
...attrs,
|
|
124
|
-
href:
|
|
128
|
+
href: (0, import_get_client_src.getClientSrc)(attrs.href, serverUrl.href)
|
|
125
129
|
};
|
|
126
130
|
if (!links.find(
|
|
127
131
|
(it) => it.href === relativeAttrs.href && it.rel === attrs.rel
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/shared/ssr/fetch-remote-component.ts"],"sourcesContent":["import { type DefaultTreeAdapterMap, Parser } from 'parse5';\nimport {\n failedToFetchRemoteComponentError,\n multipleRemoteComponentsError,\n RemoteComponentsError,\n} from '#internal/shared/error';\nimport { visit } from '#internal/shared/ssr/dom-flight';\nimport { remoteFetchHeaders } from '#internal/shared/ssr/fetch-headers';\nimport type { RemoteComponentMetadata } from './types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * Resolves the base URL that should be used to fetch the remote component.\n * This function must support local development, Vercel environments, and SSG\n * and dynamic rendering.\n */\nexport function getBaseUrl(reqHeaders: Headers): string {\n const host = reqHeaders.get('host');\n if (host) {\n return host.startsWith('localhost') ? `http://${host}` : `https://${host}`;\n }\n const forwardedHost = reqHeaders.get('x-forwarded-host');\n if (forwardedHost) {\n return `https://${forwardedHost}`;\n }\n // This is the deployment URL. When using deployment protection the\n // automation bypass header can be provided using additionalHeaders.\n if (process.env.VERCEL_URL) {\n return `https://${process.env.VERCEL_URL}`;\n }\n // TODO: Resolve the correct URL in local development when the proxy is not running.\n return `http://localhost:${process.env.MFE_LOCAL_PROXY_PORT || 3024}`;\n}\n\nexport async function fetchRemoteComponent(\n src: string | URL,\n headers: Headers = new Headers(),\n options: {\n name?: string;\n rsc?: boolean;\n } = {\n rsc: false,\n },\n) {\n const serverUrl = new URL(src, getBaseUrl(headers));\n\n const fetchInit = {\n method: 'GET',\n // pass all headers to the remote component\n headers: remoteFetchHeaders(headers),\n credentials: 'include',\n } as RequestInit;\n\n const res = await fetch(serverUrl, fetchInit);\n\n if (!res.ok && !res.body) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n new Error(`${res.status} ${res.statusText}`),\n );\n }\n\n // create a parser for the HTML response\n const parser = Parser.getFragmentParser<DefaultTreeAdapterMap>();\n\n if (!res.body) {\n throw new Error(\n `Response is empty for Remote Component \"${serverUrl.href}\". Check if you can open it in the browser and you see the Remote Component content.`,\n );\n }\n\n const decoder = new TextDecoder();\n // read the response body as a stream and parse it using the parse5 fragment parser\n for await (const chunk of res.body as unknown as AsyncIterable<Uint8Array>) {\n parser.tokenizer.write(decoder.decode(chunk), false);\n }\n const fragment = parser.getFragment();\n\n let metadata: RemoteComponentMetadata = {\n bundle: CURRENT_ZONE ?? '__vercel_remote_component',\n route: '/',\n runtime: 'webpack',\n id: '__vercel_remote_component',\n type: 'unknown',\n };\n let remoteShared: Record<string, string> = {};\n const scripts: { src: string; textContent?: string }[] = [];\n const links: Record<string, string | boolean>[] = [];\n const hydrationData: string[] = [];\n let nextData:\n | {\n props: {\n pageProps: Record<string, unknown>;\n __REMOTE_COMPONENT__?: {\n bundle: string;\n runtime: string;\n shared?: Record<string, string>;\n };\n };\n page?: string;\n buildId?: string;\n }\n | undefined;\n let html = '';\n\n const remoteName =\n options.name || serverUrl.hash ? serverUrl.hash.substring(1) : undefined;\n // convert the parsed HTML fragment into an RSC flight data\n // and extract the metadata, scripts, links and remote component RSC flight data\n let hasRemoteComponent = false;\n let hasRSC = false;\n let hasShared = false;\n let hasMultipleRemoteComponents = false;\n let error: Error | undefined;\n const rsc = visit(fragment, {\n url: serverUrl,\n name: remoteName,\n onMetadata(_metadata) {\n metadata = _metadata;\n if (hasRemoteComponent && metadata.id !== _metadata.id) {\n hasMultipleRemoteComponents = true;\n }\n hasRemoteComponent = true;\n },\n onScript(attrs) {\n if (\n !scripts.find(\n (it) =>\n it.src === attrs.src ||\n (attrs.textContent && it.textContent === attrs.textContent),\n )\n ) {\n scripts.push({\n src:\n typeof attrs.textContent === 'string'\n ? ''\n : new URL(attrs.src as string, new URL(serverUrl).origin).href,\n textContent:\n typeof attrs.textContent === 'string'\n ? attrs.textContent\n : undefined,\n });\n }\n },\n onLink(attrs) {\n const relativeAttrs = {\n ...attrs,\n href: new URL(attrs.href as string, new URL(serverUrl).origin).href,\n };\n if (\n !links.find(\n (it) => it.href === relativeAttrs.href && it.rel === attrs.rel,\n )\n ) {\n links.push(relativeAttrs);\n }\n },\n onRSC(chunk) {\n hydrationData.push(chunk);\n hasRSC = true;\n },\n onNextData(data) {\n nextData = data;\n\n // use the Next.js Pages Router props data to extract remote component metadata\n if (data.props.__REMOTE_COMPONENT__) {\n Object.assign(metadata, data.props.__REMOTE_COMPONENT__);\n // only a singleton remote component is supported per page when using the Next.js Pages Router\n metadata.id = '__next';\n metadata.route = data.page ?? '/';\n }\n },\n onHTML(_html) {\n if (!html.includes(_html)) {\n html += _html;\n }\n },\n onShared(_shared) {\n remoteShared = _shared;\n hasShared = true;\n },\n onError(message, stack) {\n error = new RemoteComponentsError(message);\n if (stack) {\n error.stack = stack;\n }\n },\n });\n\n if (error) {\n throw error;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRemoteComponent) {\n throw new Error(\n `No Remote Component found at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (hasMultipleRemoteComponents && !remoteName) {\n throw multipleRemoteComponentsError(serverUrl.href);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRSC && !nextData && metadata.type === 'nextjs') {\n throw new Error(\n `The Remote Component at \"${serverUrl.href}\" seems to be a Next.js component but it does not contain any RSC flight data or Next.js props data. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n if (\n metadata.type === 'nextjs' &&\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n !hasShared &&\n !nextData?.props.__REMOTE_COMPONENT__?.shared\n ) {\n throw new Error(\n `No shared dependencies found for Remote Component at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component with shared dependencies.`,\n );\n }\n\n let component: React.ReactNode | undefined;\n\n // only create a React component if requested\n if (options.rsc) {\n // RSC flight data for the static HTML in a single RSC line\n const componentRSC = `0:${JSON.stringify(rsc)}\\n`;\n\n const { createFromReadableStream } = await import(\n 'next/dist/compiled/react-server-dom-webpack/client.edge'\n );\n\n // create a React tree from the RSC flight data\n component = await createFromReadableStream(\n new ReadableStream({\n type: 'bytes',\n start(controller) {\n const encoder = new TextEncoder();\n controller.enqueue(encoder.encode(componentRSC));\n controller.close();\n },\n }),\n {\n serverConsumerManifest: {\n moduleLoading: {\n prefix: serverUrl.origin,\n crossOrigin: true,\n },\n moduleMap: {},\n },\n },\n );\n }\n\n const name = metadata.id.replace(/_ssr$/, '');\n return {\n name,\n serverUrl,\n metadata,\n rsc,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n html,\n remoteShared: nextData?.props.__REMOTE_COMPONENT__?.shared ?? remoteShared,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/shared/ssr/fetch-remote-component.ts"],"sourcesContent":["import { type DefaultTreeAdapterMap, Parser } from 'parse5';\nimport { getClientSrc } from '#internal/shared/client/get-client-src';\nimport {\n failedToFetchRemoteComponentError,\n multipleRemoteComponentsError,\n RemoteComponentsError,\n} from '#internal/shared/error';\nimport { visit } from '#internal/shared/ssr/dom-flight';\nimport { remoteFetchHeaders } from '#internal/shared/ssr/fetch-headers';\nimport { getSSRRelativePathBaseUrl } from '#internal/shared/ssr/get-ssr-relative-path-base-url';\nimport type { RemoteComponentMetadata } from './types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * Resolves the base URL that should be used to fetch the remote component.\n * This function must support local development, Vercel environments, and SSG\n * and dynamic rendering.\n */\nexport function getBaseUrl(reqHeaders: Headers): string {\n const host = reqHeaders.get('host');\n if (host) {\n return host.startsWith('localhost') ? `http://${host}` : `https://${host}`;\n }\n const forwardedHost = reqHeaders.get('x-forwarded-host');\n if (forwardedHost) {\n return `https://${forwardedHost}`;\n }\n return getSSRRelativePathBaseUrl();\n}\n\nexport async function fetchRemoteComponent(\n src: string | URL,\n headers: Headers = new Headers(),\n options: {\n name?: string;\n rsc?: boolean;\n } = {\n rsc: false,\n },\n) {\n const serverUrl = new URL(src, getBaseUrl(headers));\n\n const fetchInit = {\n method: 'GET',\n // pass all headers to the remote component\n headers: remoteFetchHeaders(headers),\n credentials: 'include',\n } as RequestInit;\n\n const res = await fetch(serverUrl, fetchInit);\n\n if (!res.ok && !res.body) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n new Error(`${res.status} ${res.statusText}`),\n );\n }\n\n // create a parser for the HTML response\n const parser = Parser.getFragmentParser<DefaultTreeAdapterMap>();\n\n if (!res.body) {\n throw new Error(\n `Response is empty for Remote Component \"${serverUrl.href}\". Check if you can open it in the browser and you see the Remote Component content.`,\n );\n }\n\n const decoder = new TextDecoder();\n // read the response body as a stream and parse it using the parse5 fragment parser\n for await (const chunk of res.body as unknown as AsyncIterable<Uint8Array>) {\n parser.tokenizer.write(decoder.decode(chunk), false);\n }\n const fragment = parser.getFragment();\n\n let metadata: RemoteComponentMetadata = {\n bundle: CURRENT_ZONE ?? '__vercel_remote_component',\n route: '/',\n runtime: 'webpack',\n id: '__vercel_remote_component',\n type: 'unknown',\n };\n let remoteShared: Record<string, string> = {};\n const scripts: { src: string; textContent?: string }[] = [];\n const links: Record<string, string | boolean>[] = [];\n const hydrationData: string[] = [];\n let nextData:\n | {\n props: {\n pageProps: Record<string, unknown>;\n __REMOTE_COMPONENT__?: {\n bundle: string;\n runtime: string;\n shared?: Record<string, string>;\n };\n };\n page?: string;\n buildId?: string;\n }\n | undefined;\n let html = '';\n\n const remoteName =\n options.name || serverUrl.hash ? serverUrl.hash.substring(1) : undefined;\n // convert the parsed HTML fragment into an RSC flight data\n // and extract the metadata, scripts, links and remote component RSC flight data\n let hasRemoteComponent = false;\n let hasRSC = false;\n let hasShared = false;\n let hasMultipleRemoteComponents = false;\n let error: Error | undefined;\n const rsc = visit(fragment, {\n url: serverUrl,\n name: remoteName,\n onMetadata(_metadata) {\n metadata = _metadata;\n if (hasRemoteComponent && metadata.id !== _metadata.id) {\n hasMultipleRemoteComponents = true;\n }\n hasRemoteComponent = true;\n },\n onScript(attrs) {\n const clientSrc = getClientSrc(attrs.src, serverUrl.href);\n if (\n !scripts.find(\n (it) =>\n it.src === clientSrc ||\n (attrs.textContent && it.textContent === attrs.textContent),\n )\n ) {\n scripts.push(\n typeof attrs.textContent === 'string'\n ? {\n src: '',\n textContent: attrs.textContent,\n }\n : {\n src: clientSrc,\n },\n );\n }\n },\n onLink(attrs) {\n const relativeAttrs = {\n ...attrs,\n href: getClientSrc(attrs.href, serverUrl.href),\n };\n if (\n !links.find(\n (it) => it.href === relativeAttrs.href && it.rel === attrs.rel,\n )\n ) {\n links.push(relativeAttrs);\n }\n },\n onRSC(chunk) {\n hydrationData.push(chunk);\n hasRSC = true;\n },\n onNextData(data) {\n nextData = data;\n\n // use the Next.js Pages Router props data to extract remote component metadata\n if (data.props.__REMOTE_COMPONENT__) {\n Object.assign(metadata, data.props.__REMOTE_COMPONENT__);\n // only a singleton remote component is supported per page when using the Next.js Pages Router\n metadata.id = '__next';\n metadata.route = data.page ?? '/';\n }\n },\n onHTML(_html) {\n if (!html.includes(_html)) {\n html += _html;\n }\n },\n onShared(_shared) {\n remoteShared = _shared;\n hasShared = true;\n },\n onError(message, stack) {\n error = new RemoteComponentsError(message);\n if (stack) {\n error.stack = stack;\n }\n },\n });\n\n if (error) {\n throw error;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRemoteComponent) {\n throw new Error(\n `No Remote Component found at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (hasMultipleRemoteComponents && !remoteName) {\n throw multipleRemoteComponentsError(serverUrl.href);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRSC && !nextData && metadata.type === 'nextjs') {\n throw new Error(\n `The Remote Component at \"${serverUrl.href}\" seems to be a Next.js component but it does not contain any RSC flight data or Next.js props data. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n if (\n metadata.type === 'nextjs' &&\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n !hasShared &&\n !nextData?.props.__REMOTE_COMPONENT__?.shared\n ) {\n throw new Error(\n `No shared dependencies found for Remote Component at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component with shared dependencies.`,\n );\n }\n\n let component: React.ReactNode | undefined;\n\n // only create a React component if requested\n if (options.rsc) {\n // RSC flight data for the static HTML in a single RSC line\n const componentRSC = `0:${JSON.stringify(rsc)}\\n`;\n\n const { createFromReadableStream } = await import(\n 'next/dist/compiled/react-server-dom-webpack/client.edge'\n );\n\n // create a React tree from the RSC flight data\n component = await createFromReadableStream(\n new ReadableStream({\n type: 'bytes',\n start(controller) {\n const encoder = new TextEncoder();\n controller.enqueue(encoder.encode(componentRSC));\n controller.close();\n },\n }),\n {\n serverConsumerManifest: {\n moduleLoading: {\n prefix: serverUrl.origin,\n crossOrigin: true,\n },\n moduleMap: {},\n },\n },\n );\n }\n\n const name = metadata.id.replace(/_ssr$/, '');\n return {\n name,\n serverUrl,\n metadata,\n rsc,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n html,\n remoteShared: nextData?.props.__REMOTE_COMPONENT__?.shared ?? remoteShared,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Parser } from "parse5";
|
|
2
|
+
import { getClientSrc } from "#internal/shared/client/get-client-src";
|
|
2
3
|
import {
|
|
3
4
|
failedToFetchRemoteComponentError,
|
|
4
5
|
multipleRemoteComponentsError,
|
|
@@ -6,6 +7,7 @@ import {
|
|
|
6
7
|
} from "#internal/shared/error";
|
|
7
8
|
import { visit } from "#internal/shared/ssr/dom-flight";
|
|
8
9
|
import { remoteFetchHeaders } from "#internal/shared/ssr/fetch-headers";
|
|
10
|
+
import { getSSRRelativePathBaseUrl } from "#internal/shared/ssr/get-ssr-relative-path-base-url";
|
|
9
11
|
const CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;
|
|
10
12
|
function getBaseUrl(reqHeaders) {
|
|
11
13
|
const host = reqHeaders.get("host");
|
|
@@ -16,10 +18,7 @@ function getBaseUrl(reqHeaders) {
|
|
|
16
18
|
if (forwardedHost) {
|
|
17
19
|
return `https://${forwardedHost}`;
|
|
18
20
|
}
|
|
19
|
-
|
|
20
|
-
return `https://${process.env.VERCEL_URL}`;
|
|
21
|
-
}
|
|
22
|
-
return `http://localhost:${process.env.MFE_LOCAL_PROXY_PORT || 3024}`;
|
|
21
|
+
return getSSRRelativePathBaseUrl();
|
|
23
22
|
}
|
|
24
23
|
async function fetchRemoteComponent(src, headers = new Headers(), options = {
|
|
25
24
|
rsc: false
|
|
@@ -79,19 +78,24 @@ async function fetchRemoteComponent(src, headers = new Headers(), options = {
|
|
|
79
78
|
hasRemoteComponent = true;
|
|
80
79
|
},
|
|
81
80
|
onScript(attrs) {
|
|
81
|
+
const clientSrc = getClientSrc(attrs.src, serverUrl.href);
|
|
82
82
|
if (!scripts.find(
|
|
83
|
-
(it) => it.src ===
|
|
83
|
+
(it) => it.src === clientSrc || attrs.textContent && it.textContent === attrs.textContent
|
|
84
84
|
)) {
|
|
85
|
-
scripts.push(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
scripts.push(
|
|
86
|
+
typeof attrs.textContent === "string" ? {
|
|
87
|
+
src: "",
|
|
88
|
+
textContent: attrs.textContent
|
|
89
|
+
} : {
|
|
90
|
+
src: clientSrc
|
|
91
|
+
}
|
|
92
|
+
);
|
|
89
93
|
}
|
|
90
94
|
},
|
|
91
95
|
onLink(attrs) {
|
|
92
96
|
const relativeAttrs = {
|
|
93
97
|
...attrs,
|
|
94
|
-
href:
|
|
98
|
+
href: getClientSrc(attrs.href, serverUrl.href)
|
|
95
99
|
};
|
|
96
100
|
if (!links.find(
|
|
97
101
|
(it) => it.href === relativeAttrs.href && it.rel === attrs.rel
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/shared/ssr/fetch-remote-component.ts"],"sourcesContent":["import { type DefaultTreeAdapterMap, Parser } from 'parse5';\nimport {\n failedToFetchRemoteComponentError,\n multipleRemoteComponentsError,\n RemoteComponentsError,\n} from '#internal/shared/error';\nimport { visit } from '#internal/shared/ssr/dom-flight';\nimport { remoteFetchHeaders } from '#internal/shared/ssr/fetch-headers';\nimport type { RemoteComponentMetadata } from './types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * Resolves the base URL that should be used to fetch the remote component.\n * This function must support local development, Vercel environments, and SSG\n * and dynamic rendering.\n */\nexport function getBaseUrl(reqHeaders: Headers): string {\n const host = reqHeaders.get('host');\n if (host) {\n return host.startsWith('localhost') ? `http://${host}` : `https://${host}`;\n }\n const forwardedHost = reqHeaders.get('x-forwarded-host');\n if (forwardedHost) {\n return `https://${forwardedHost}`;\n }\n // This is the deployment URL. When using deployment protection the\n // automation bypass header can be provided using additionalHeaders.\n if (process.env.VERCEL_URL) {\n return `https://${process.env.VERCEL_URL}`;\n }\n // TODO: Resolve the correct URL in local development when the proxy is not running.\n return `http://localhost:${process.env.MFE_LOCAL_PROXY_PORT || 3024}`;\n}\n\nexport async function fetchRemoteComponent(\n src: string | URL,\n headers: Headers = new Headers(),\n options: {\n name?: string;\n rsc?: boolean;\n } = {\n rsc: false,\n },\n) {\n const serverUrl = new URL(src, getBaseUrl(headers));\n\n const fetchInit = {\n method: 'GET',\n // pass all headers to the remote component\n headers: remoteFetchHeaders(headers),\n credentials: 'include',\n } as RequestInit;\n\n const res = await fetch(serverUrl, fetchInit);\n\n if (!res.ok && !res.body) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n new Error(`${res.status} ${res.statusText}`),\n );\n }\n\n // create a parser for the HTML response\n const parser = Parser.getFragmentParser<DefaultTreeAdapterMap>();\n\n if (!res.body) {\n throw new Error(\n `Response is empty for Remote Component \"${serverUrl.href}\". Check if you can open it in the browser and you see the Remote Component content.`,\n );\n }\n\n const decoder = new TextDecoder();\n // read the response body as a stream and parse it using the parse5 fragment parser\n for await (const chunk of res.body as unknown as AsyncIterable<Uint8Array>) {\n parser.tokenizer.write(decoder.decode(chunk), false);\n }\n const fragment = parser.getFragment();\n\n let metadata: RemoteComponentMetadata = {\n bundle: CURRENT_ZONE ?? '__vercel_remote_component',\n route: '/',\n runtime: 'webpack',\n id: '__vercel_remote_component',\n type: 'unknown',\n };\n let remoteShared: Record<string, string> = {};\n const scripts: { src: string; textContent?: string }[] = [];\n const links: Record<string, string | boolean>[] = [];\n const hydrationData: string[] = [];\n let nextData:\n | {\n props: {\n pageProps: Record<string, unknown>;\n __REMOTE_COMPONENT__?: {\n bundle: string;\n runtime: string;\n shared?: Record<string, string>;\n };\n };\n page?: string;\n buildId?: string;\n }\n | undefined;\n let html = '';\n\n const remoteName =\n options.name || serverUrl.hash ? serverUrl.hash.substring(1) : undefined;\n // convert the parsed HTML fragment into an RSC flight data\n // and extract the metadata, scripts, links and remote component RSC flight data\n let hasRemoteComponent = false;\n let hasRSC = false;\n let hasShared = false;\n let hasMultipleRemoteComponents = false;\n let error: Error | undefined;\n const rsc = visit(fragment, {\n url: serverUrl,\n name: remoteName,\n onMetadata(_metadata) {\n metadata = _metadata;\n if (hasRemoteComponent && metadata.id !== _metadata.id) {\n hasMultipleRemoteComponents = true;\n }\n hasRemoteComponent = true;\n },\n onScript(attrs) {\n if (\n !scripts.find(\n (it) =>\n it.src === attrs.src ||\n (attrs.textContent && it.textContent === attrs.textContent),\n )\n ) {\n scripts.push({\n src:\n typeof attrs.textContent === 'string'\n ? ''\n : new URL(attrs.src as string, new URL(serverUrl).origin).href,\n textContent:\n typeof attrs.textContent === 'string'\n ? attrs.textContent\n : undefined,\n });\n }\n },\n onLink(attrs) {\n const relativeAttrs = {\n ...attrs,\n href: new URL(attrs.href as string, new URL(serverUrl).origin).href,\n };\n if (\n !links.find(\n (it) => it.href === relativeAttrs.href && it.rel === attrs.rel,\n )\n ) {\n links.push(relativeAttrs);\n }\n },\n onRSC(chunk) {\n hydrationData.push(chunk);\n hasRSC = true;\n },\n onNextData(data) {\n nextData = data;\n\n // use the Next.js Pages Router props data to extract remote component metadata\n if (data.props.__REMOTE_COMPONENT__) {\n Object.assign(metadata, data.props.__REMOTE_COMPONENT__);\n // only a singleton remote component is supported per page when using the Next.js Pages Router\n metadata.id = '__next';\n metadata.route = data.page ?? '/';\n }\n },\n onHTML(_html) {\n if (!html.includes(_html)) {\n html += _html;\n }\n },\n onShared(_shared) {\n remoteShared = _shared;\n hasShared = true;\n },\n onError(message, stack) {\n error = new RemoteComponentsError(message);\n if (stack) {\n error.stack = stack;\n }\n },\n });\n\n if (error) {\n throw error;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRemoteComponent) {\n throw new Error(\n `No Remote Component found at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (hasMultipleRemoteComponents && !remoteName) {\n throw multipleRemoteComponentsError(serverUrl.href);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRSC && !nextData && metadata.type === 'nextjs') {\n throw new Error(\n `The Remote Component at \"${serverUrl.href}\" seems to be a Next.js component but it does not contain any RSC flight data or Next.js props data. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n if (\n metadata.type === 'nextjs' &&\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n !hasShared &&\n !nextData?.props.__REMOTE_COMPONENT__?.shared\n ) {\n throw new Error(\n `No shared dependencies found for Remote Component at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component with shared dependencies.`,\n );\n }\n\n let component: React.ReactNode | undefined;\n\n // only create a React component if requested\n if (options.rsc) {\n // RSC flight data for the static HTML in a single RSC line\n const componentRSC = `0:${JSON.stringify(rsc)}\\n`;\n\n const { createFromReadableStream } = await import(\n 'next/dist/compiled/react-server-dom-webpack/client.edge'\n );\n\n // create a React tree from the RSC flight data\n component = await createFromReadableStream(\n new ReadableStream({\n type: 'bytes',\n start(controller) {\n const encoder = new TextEncoder();\n controller.enqueue(encoder.encode(componentRSC));\n controller.close();\n },\n }),\n {\n serverConsumerManifest: {\n moduleLoading: {\n prefix: serverUrl.origin,\n crossOrigin: true,\n },\n moduleMap: {},\n },\n },\n );\n }\n\n const name = metadata.id.replace(/_ssr$/, '');\n return {\n name,\n serverUrl,\n metadata,\n rsc,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n html,\n remoteShared: nextData?.props.__REMOTE_COMPONENT__?.shared ?? remoteShared,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/shared/ssr/fetch-remote-component.ts"],"sourcesContent":["import { type DefaultTreeAdapterMap, Parser } from 'parse5';\nimport { getClientSrc } from '#internal/shared/client/get-client-src';\nimport {\n failedToFetchRemoteComponentError,\n multipleRemoteComponentsError,\n RemoteComponentsError,\n} from '#internal/shared/error';\nimport { visit } from '#internal/shared/ssr/dom-flight';\nimport { remoteFetchHeaders } from '#internal/shared/ssr/fetch-headers';\nimport { getSSRRelativePathBaseUrl } from '#internal/shared/ssr/get-ssr-relative-path-base-url';\nimport type { RemoteComponentMetadata } from './types';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * Resolves the base URL that should be used to fetch the remote component.\n * This function must support local development, Vercel environments, and SSG\n * and dynamic rendering.\n */\nexport function getBaseUrl(reqHeaders: Headers): string {\n const host = reqHeaders.get('host');\n if (host) {\n return host.startsWith('localhost') ? `http://${host}` : `https://${host}`;\n }\n const forwardedHost = reqHeaders.get('x-forwarded-host');\n if (forwardedHost) {\n return `https://${forwardedHost}`;\n }\n return getSSRRelativePathBaseUrl();\n}\n\nexport async function fetchRemoteComponent(\n src: string | URL,\n headers: Headers = new Headers(),\n options: {\n name?: string;\n rsc?: boolean;\n } = {\n rsc: false,\n },\n) {\n const serverUrl = new URL(src, getBaseUrl(headers));\n\n const fetchInit = {\n method: 'GET',\n // pass all headers to the remote component\n headers: remoteFetchHeaders(headers),\n credentials: 'include',\n } as RequestInit;\n\n const res = await fetch(serverUrl, fetchInit);\n\n if (!res.ok && !res.body) {\n throw failedToFetchRemoteComponentError(\n serverUrl.href,\n new Error(`${res.status} ${res.statusText}`),\n );\n }\n\n // create a parser for the HTML response\n const parser = Parser.getFragmentParser<DefaultTreeAdapterMap>();\n\n if (!res.body) {\n throw new Error(\n `Response is empty for Remote Component \"${serverUrl.href}\". Check if you can open it in the browser and you see the Remote Component content.`,\n );\n }\n\n const decoder = new TextDecoder();\n // read the response body as a stream and parse it using the parse5 fragment parser\n for await (const chunk of res.body as unknown as AsyncIterable<Uint8Array>) {\n parser.tokenizer.write(decoder.decode(chunk), false);\n }\n const fragment = parser.getFragment();\n\n let metadata: RemoteComponentMetadata = {\n bundle: CURRENT_ZONE ?? '__vercel_remote_component',\n route: '/',\n runtime: 'webpack',\n id: '__vercel_remote_component',\n type: 'unknown',\n };\n let remoteShared: Record<string, string> = {};\n const scripts: { src: string; textContent?: string }[] = [];\n const links: Record<string, string | boolean>[] = [];\n const hydrationData: string[] = [];\n let nextData:\n | {\n props: {\n pageProps: Record<string, unknown>;\n __REMOTE_COMPONENT__?: {\n bundle: string;\n runtime: string;\n shared?: Record<string, string>;\n };\n };\n page?: string;\n buildId?: string;\n }\n | undefined;\n let html = '';\n\n const remoteName =\n options.name || serverUrl.hash ? serverUrl.hash.substring(1) : undefined;\n // convert the parsed HTML fragment into an RSC flight data\n // and extract the metadata, scripts, links and remote component RSC flight data\n let hasRemoteComponent = false;\n let hasRSC = false;\n let hasShared = false;\n let hasMultipleRemoteComponents = false;\n let error: Error | undefined;\n const rsc = visit(fragment, {\n url: serverUrl,\n name: remoteName,\n onMetadata(_metadata) {\n metadata = _metadata;\n if (hasRemoteComponent && metadata.id !== _metadata.id) {\n hasMultipleRemoteComponents = true;\n }\n hasRemoteComponent = true;\n },\n onScript(attrs) {\n const clientSrc = getClientSrc(attrs.src, serverUrl.href);\n if (\n !scripts.find(\n (it) =>\n it.src === clientSrc ||\n (attrs.textContent && it.textContent === attrs.textContent),\n )\n ) {\n scripts.push(\n typeof attrs.textContent === 'string'\n ? {\n src: '',\n textContent: attrs.textContent,\n }\n : {\n src: clientSrc,\n },\n );\n }\n },\n onLink(attrs) {\n const relativeAttrs = {\n ...attrs,\n href: getClientSrc(attrs.href, serverUrl.href),\n };\n if (\n !links.find(\n (it) => it.href === relativeAttrs.href && it.rel === attrs.rel,\n )\n ) {\n links.push(relativeAttrs);\n }\n },\n onRSC(chunk) {\n hydrationData.push(chunk);\n hasRSC = true;\n },\n onNextData(data) {\n nextData = data;\n\n // use the Next.js Pages Router props data to extract remote component metadata\n if (data.props.__REMOTE_COMPONENT__) {\n Object.assign(metadata, data.props.__REMOTE_COMPONENT__);\n // only a singleton remote component is supported per page when using the Next.js Pages Router\n metadata.id = '__next';\n metadata.route = data.page ?? '/';\n }\n },\n onHTML(_html) {\n if (!html.includes(_html)) {\n html += _html;\n }\n },\n onShared(_shared) {\n remoteShared = _shared;\n hasShared = true;\n },\n onError(message, stack) {\n error = new RemoteComponentsError(message);\n if (stack) {\n error.stack = stack;\n }\n },\n });\n\n if (error) {\n throw error;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRemoteComponent) {\n throw new Error(\n `No Remote Component found at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (hasMultipleRemoteComponents && !remoteName) {\n throw multipleRemoteComponentsError(serverUrl.href);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!hasRSC && !nextData && metadata.type === 'nextjs') {\n throw new Error(\n `The Remote Component at \"${serverUrl.href}\" seems to be a Next.js component but it does not contain any RSC flight data or Next.js props data. Make sure the remote URL is correct and contains a Remote Component.`,\n );\n }\n\n if (\n metadata.type === 'nextjs' &&\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n !hasShared &&\n !nextData?.props.__REMOTE_COMPONENT__?.shared\n ) {\n throw new Error(\n `No shared dependencies found for Remote Component at \"${serverUrl.href}\". Make sure the remote URL is correct and contains a Remote Component with shared dependencies.`,\n );\n }\n\n let component: React.ReactNode | undefined;\n\n // only create a React component if requested\n if (options.rsc) {\n // RSC flight data for the static HTML in a single RSC line\n const componentRSC = `0:${JSON.stringify(rsc)}\\n`;\n\n const { createFromReadableStream } = await import(\n 'next/dist/compiled/react-server-dom-webpack/client.edge'\n );\n\n // create a React tree from the RSC flight data\n component = await createFromReadableStream(\n new ReadableStream({\n type: 'bytes',\n start(controller) {\n const encoder = new TextEncoder();\n controller.enqueue(encoder.encode(componentRSC));\n controller.close();\n },\n }),\n {\n serverConsumerManifest: {\n moduleLoading: {\n prefix: serverUrl.origin,\n crossOrigin: true,\n },\n moduleMap: {},\n },\n },\n );\n }\n\n const name = metadata.id.replace(/_ssr$/, '');\n return {\n name,\n serverUrl,\n metadata,\n rsc,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n html,\n remoteShared: nextData?.props.__REMOTE_COMPONENT__?.shared ?? remoteShared,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var get_ssr_relative_path_base_url_exports = {};
|
|
20
|
+
__export(get_ssr_relative_path_base_url_exports, {
|
|
21
|
+
getSSRRelativePathBaseUrl: () => getSSRRelativePathBaseUrl
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(get_ssr_relative_path_base_url_exports);
|
|
24
|
+
function getSSRRelativePathBaseUrl() {
|
|
25
|
+
if (process.env.VERCEL_URL) {
|
|
26
|
+
return `https://${process.env.VERCEL_URL}`;
|
|
27
|
+
}
|
|
28
|
+
return `http://localhost:${process.env.MFE_LOCAL_PROXY_PORT || 3024}`;
|
|
29
|
+
}
|
|
30
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
31
|
+
0 && (module.exports = {
|
|
32
|
+
getSSRRelativePathBaseUrl
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=get-ssr-relative-path-base-url.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/shared/ssr/get-ssr-relative-path-base-url.ts"],"sourcesContent":["/**\n * When fetching a remote component using a relative path with SSR, a base URL is required.\n * This is not used on the client.\n *\n * Can add support in the future with a custom env var for prop for when not building with Vercel\n * and Vercel URL is not available.\n */\nexport function getSSRRelativePathBaseUrl(): string {\n // This is the deployment URL. When using deployment protection the\n // automation bypass header can be provided using additionalHeaders.\n if (process.env.VERCEL_URL) {\n return `https://${process.env.VERCEL_URL}`;\n }\n\n // TODO: Resolve the correct URL in local development when the proxy is not running.\n return `http://localhost:${process.env.MFE_LOCAL_PROXY_PORT || 3024}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOO,SAAS,4BAAoC;AAGlD,MAAI,QAAQ,IAAI,YAAY;AAC1B,WAAO,WAAW,QAAQ,IAAI;AAAA,EAChC;AAGA,SAAO,oBAAoB,QAAQ,IAAI,wBAAwB;AACjE;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When fetching a remote component using a relative path with SSR, a base URL is required.
|
|
3
|
+
* This is not used on the client.
|
|
4
|
+
*
|
|
5
|
+
* Can add support in the future with a custom env var for prop for when not building with Vercel
|
|
6
|
+
* and Vercel URL is not available.
|
|
7
|
+
*/
|
|
8
|
+
declare function getSSRRelativePathBaseUrl(): string;
|
|
9
|
+
|
|
10
|
+
export { getSSRRelativePathBaseUrl };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function getSSRRelativePathBaseUrl() {
|
|
2
|
+
if (process.env.VERCEL_URL) {
|
|
3
|
+
return `https://${process.env.VERCEL_URL}`;
|
|
4
|
+
}
|
|
5
|
+
return `http://localhost:${process.env.MFE_LOCAL_PROXY_PORT || 3024}`;
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
getSSRRelativePathBaseUrl
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=get-ssr-relative-path-base-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/shared/ssr/get-ssr-relative-path-base-url.ts"],"sourcesContent":["/**\n * When fetching a remote component using a relative path with SSR, a base URL is required.\n * This is not used on the client.\n *\n * Can add support in the future with a custom env var for prop for when not building with Vercel\n * and Vercel URL is not available.\n */\nexport function getSSRRelativePathBaseUrl(): string {\n // This is the deployment URL. When using deployment protection the\n // automation bypass header can be provided using additionalHeaders.\n if (process.env.VERCEL_URL) {\n return `https://${process.env.VERCEL_URL}`;\n }\n\n // TODO: Resolve the correct URL in local development when the proxy is not running.\n return `http://localhost:${process.env.MFE_LOCAL_PROXY_PORT || 3024}`;\n}\n"],"mappings":"AAOO,SAAS,4BAAoC;AAGlD,MAAI,QAAQ,IAAI,YAAY;AAC1B,WAAO,WAAW,QAAQ,IAAI;AAAA,EAChC;AAGA,SAAO,oBAAoB,QAAQ,IAAI,wBAAwB;AACjE;","names":[]}
|