remote-components 0.0.37 → 0.0.39
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/html/host.cjs +78 -0
- package/dist/html/host.cjs.map +1 -1
- package/dist/html/host.js +78 -0
- package/dist/html/host.js.map +1 -1
- 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/next/remote/render-server.cjs.map +1 -1
- package/dist/internal/next/remote/render-server.d.ts +13 -0
- package/dist/internal/next/remote/render-server.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/dist/next/host/client/index.cjs +41 -2
- package/dist/next/host/client/index.cjs.map +1 -1
- package/dist/next/host/client/index.d.ts +13 -0
- package/dist/next/host/client/index.js +41 -2
- package/dist/next/host/client/index.js.map +1 -1
- package/dist/react/index.cjs +41 -2
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +14 -1
- package/dist/react/index.js +41 -2
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -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":[]}
|
|
@@ -1385,7 +1385,11 @@ function RemoteComponent({
|
|
|
1385
1385
|
name: nameProp = "__vercel_remote_component",
|
|
1386
1386
|
shared = {},
|
|
1387
1387
|
additionalHeaders,
|
|
1388
|
-
children
|
|
1388
|
+
children,
|
|
1389
|
+
onBeforeLoad,
|
|
1390
|
+
onLoad,
|
|
1391
|
+
onError,
|
|
1392
|
+
onChange
|
|
1389
1393
|
}) {
|
|
1390
1394
|
const name = (0, import_react.useMemo)(() => {
|
|
1391
1395
|
if (typeof src === "string") {
|
|
@@ -1441,6 +1445,7 @@ function RemoteComponent({
|
|
|
1441
1445
|
const prevUrlRef = (0, import_react.useRef)(null);
|
|
1442
1446
|
const prevRemoteComponentContainerRef = (0, import_react.useRef)(null);
|
|
1443
1447
|
const unmountRef = (0, import_react.useRef)(null);
|
|
1448
|
+
const prevNameRef = (0, import_react.useRef)(void 0);
|
|
1444
1449
|
(0, import_react.useLayoutEffect)(() => {
|
|
1445
1450
|
if (childrenRef.current.length > 0 && remoteComponent) {
|
|
1446
1451
|
childrenRef.current.forEach((el) => {
|
|
@@ -1496,7 +1501,10 @@ function RemoteComponent({
|
|
|
1496
1501
|
}, [shadowRoot, remoteComponent, name]);
|
|
1497
1502
|
(0, import_react.useEffect)(() => {
|
|
1498
1503
|
if (src && src !== prevSrcRef.current) {
|
|
1504
|
+
const previousSrc = prevSrcRef.current;
|
|
1505
|
+
const previousName = prevNameRef.current;
|
|
1499
1506
|
prevSrcRef.current = src;
|
|
1507
|
+
onBeforeLoad?.(src);
|
|
1500
1508
|
(0, import_react.startTransition)(async () => {
|
|
1501
1509
|
try {
|
|
1502
1510
|
let html = getRemoteComponentHtml(
|
|
@@ -1594,6 +1602,7 @@ function RemoteComponent({
|
|
|
1594
1602
|
}
|
|
1595
1603
|
prevIsRemoteComponentRef.current = isRemoteComponent;
|
|
1596
1604
|
prevUrlRef.current = url;
|
|
1605
|
+
prevNameRef.current = remoteName;
|
|
1597
1606
|
applyOriginToNodes(doc, url);
|
|
1598
1607
|
const links = Array.from(
|
|
1599
1608
|
doc.querySelectorAll("link[href]")
|
|
@@ -1699,6 +1708,14 @@ function RemoteComponent({
|
|
|
1699
1708
|
);
|
|
1700
1709
|
}
|
|
1701
1710
|
if (isRemoteComponent) {
|
|
1711
|
+
if (previousSrc !== null) {
|
|
1712
|
+
onChange?.({
|
|
1713
|
+
previousSrc,
|
|
1714
|
+
nextSrc: src,
|
|
1715
|
+
previousName,
|
|
1716
|
+
nextName: remoteName
|
|
1717
|
+
});
|
|
1718
|
+
}
|
|
1702
1719
|
setData(newData);
|
|
1703
1720
|
if (shadowRoot) {
|
|
1704
1721
|
let shadowRootHtml = component.innerHTML;
|
|
@@ -1715,6 +1732,7 @@ function RemoteComponent({
|
|
|
1715
1732
|
await Promise.all(
|
|
1716
1733
|
Array.from(mount).map((mountFn) => mountFn(shadowRoot))
|
|
1717
1734
|
);
|
|
1735
|
+
onLoad?.(src);
|
|
1718
1736
|
} else if (isolate === false) {
|
|
1719
1737
|
setRemoteComponent(
|
|
1720
1738
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -1735,6 +1753,7 @@ function RemoteComponent({
|
|
|
1735
1753
|
(mountFn) => mountFn(prevRemoteComponentContainerRef.current)
|
|
1736
1754
|
)
|
|
1737
1755
|
);
|
|
1756
|
+
onLoad?.(src);
|
|
1738
1757
|
}
|
|
1739
1758
|
} else {
|
|
1740
1759
|
const result = await loadRemoteComponent({
|
|
@@ -1775,14 +1794,25 @@ function RemoteComponent({
|
|
|
1775
1794
|
rsc.remove();
|
|
1776
1795
|
}
|
|
1777
1796
|
setData(newData);
|
|
1797
|
+
if (previousSrc !== null) {
|
|
1798
|
+
onChange?.({
|
|
1799
|
+
previousSrc,
|
|
1800
|
+
nextSrc: src,
|
|
1801
|
+
previousName,
|
|
1802
|
+
nextName: remoteName
|
|
1803
|
+
});
|
|
1804
|
+
}
|
|
1778
1805
|
if (result.error) {
|
|
1779
1806
|
setRemoteComponent(result.error);
|
|
1807
|
+
onError?.(result.error);
|
|
1780
1808
|
} else {
|
|
1781
1809
|
setRemoteComponent(result.component);
|
|
1810
|
+
onLoad?.(src);
|
|
1782
1811
|
}
|
|
1783
1812
|
}
|
|
1784
1813
|
} catch (error) {
|
|
1785
1814
|
setRemoteComponent(error);
|
|
1815
|
+
onError?.(error);
|
|
1786
1816
|
}
|
|
1787
1817
|
});
|
|
1788
1818
|
}
|
|
@@ -1796,7 +1826,11 @@ function RemoteComponent({
|
|
|
1796
1826
|
shadowRoot,
|
|
1797
1827
|
additionalHeaders,
|
|
1798
1828
|
reset,
|
|
1799
|
-
id
|
|
1829
|
+
id,
|
|
1830
|
+
onBeforeLoad,
|
|
1831
|
+
onLoad,
|
|
1832
|
+
onError,
|
|
1833
|
+
onChange
|
|
1800
1834
|
]);
|
|
1801
1835
|
if (remoteComponent instanceof Error) {
|
|
1802
1836
|
throw remoteComponent;
|
|
@@ -1832,6 +1866,10 @@ function RemoteComponent({
|
|
|
1832
1866
|
return Promise.all(
|
|
1833
1867
|
Array.from(mount).map((mountFn) => mountFn(shadowRoot))
|
|
1834
1868
|
);
|
|
1869
|
+
}).then(() => {
|
|
1870
|
+
if (src) {
|
|
1871
|
+
onLoad?.(src);
|
|
1872
|
+
}
|
|
1835
1873
|
}).catch((e) => {
|
|
1836
1874
|
const error = new RemoteComponentsError(
|
|
1837
1875
|
`Error mounting remote component from "${url.href}"`,
|
|
@@ -1840,6 +1878,7 @@ function RemoteComponent({
|
|
|
1840
1878
|
}
|
|
1841
1879
|
);
|
|
1842
1880
|
setRemoteComponent(error);
|
|
1881
|
+
onError?.(error);
|
|
1843
1882
|
});
|
|
1844
1883
|
}
|
|
1845
1884
|
}
|