remote-components 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/html/host.cjs +112 -63
- package/dist/html/host.cjs.map +1 -1
- package/dist/html/host.js +112 -63
- package/dist/html/host.js.map +1 -1
- package/dist/next/config.cjs +1 -0
- package/dist/next/config.cjs.map +1 -1
- package/dist/next/config.js +1 -0
- package/dist/next/config.js.map +1 -1
- package/dist/next/host/app-client.cjs +2 -11
- package/dist/next/host/app-client.cjs.map +1 -1
- package/dist/next/host/app-client.js +2 -11
- package/dist/next/host/app-client.js.map +1 -1
- package/dist/next/host/app-server.cjs +3 -2
- package/dist/next/host/app-server.cjs.map +1 -1
- package/dist/next/host/app-server.js +3 -2
- package/dist/next/host/app-server.js.map +1 -1
- package/dist/next/remote/render-server.cjs +29 -5
- package/dist/next/remote/render-server.cjs.map +1 -1
- package/dist/next/remote/render-server.js +29 -5
- package/dist/next/remote/render-server.js.map +1 -1
- package/dist/shared/client/remote-component.cjs +61 -58
- package/dist/shared/client/remote-component.cjs.map +1 -1
- package/dist/shared/client/remote-component.d.ts +1 -2
- package/dist/shared/client/remote-component.js +61 -57
- package/dist/shared/client/remote-component.js.map +1 -1
- package/dist/shared/ssr/fetch-remote-component.cjs +3 -1
- package/dist/shared/ssr/fetch-remote-component.cjs.map +1 -1
- package/dist/shared/ssr/fetch-remote-component.js +3 -1
- package/dist/shared/ssr/fetch-remote-component.js.map +1 -1
- package/package.json +1 -1
package/dist/next/config.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/config/index.ts","../../src/next/config/webpack/index.ts","../../src/next/config/webpack/plugins/remote-webpack-require-runtime-module.ts","../../src/next/config/webpack/plugins/remote-webpack-require.ts","../../src/next/config/webpack/plugins/module-id-embed-runtime-module.ts","../../src/next/config/webpack/plugins/module-id-embed.ts","../../src/next/config/webpack/plugins/conditional-exec.ts","../../src/next/config/webpack/plugins/patch-require.ts"],"sourcesContent":["import { basename, dirname, join, relative } from 'node:path';\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { findUpSync } from 'find-up';\nimport type { NextConfig } from 'next';\nimport { transform as webpackTransform } from './webpack';\n\ninterface WithRemoteComponentsOptions {\n /**\n * An array of package names that should be shared between the host and remote components.\n * This is useful for ensuring that both the host and remote components use the same version\n * of shared libraries.\n *\n * Essential packages are included by default: `react`, `react-dom`, `next/navigation`, `next/link`, `next/form`, `next/image`, and `next/script`.\n */\n shared?: string[];\n}\n\n/**\n * This function configures Next.js to support Remote Components.\n * You need to also use the `withMicrofrontends` function to extend your Next.js configuration.\n *\n * @param nextConfig - The Next.js configuration object.\n * @param options - Optional configuration for remote components.\n * @returns The modified Next.js configuration object with remote components support.\n *\n * @example\n *\n * ```js\n * import { withMicrofrontends } from '@vercel/microfrontends/next/config';\n * import { withRemoteComponents } from 'remote-components/next/config';\n *\n * const nextConfig = {\n * // your Next.js configuration\n * };\n *\n * export default withRemoteComponents(\n * withMicrofrontends(nextConfig),\n * {\n * shared: ['some-package', 'another-package'],\n * },\n * );\n * ```\n */\nexport function withRemoteComponents(\n nextConfig: NextConfig,\n options?: WithRemoteComponentsOptions,\n) {\n const virtualRemoteComponentSharedRemote = join(\n process.cwd(),\n nextConfig.distDir ?? '.next',\n 'remote-components/shared/remote.tsx',\n );\n const virtualRemoteComponentSharedHost = join(\n process.cwd(),\n nextConfig.distDir ?? '.next',\n 'remote-components/shared/host.tsx',\n );\n\n const shared = new Set([\n ...[\n 'react',\n 'react/jsx-dev-runtime',\n 'react/jsx-runtime',\n 'react-dom',\n 'react-dom/client',\n 'next/navigation',\n 'next/link',\n 'next/form',\n 'next/image',\n 'next/script',\n ],\n ...(options?.shared ?? []),\n ]);\n\n const vendorShared: Record<string, string> = {\n react: `'/react/index.js'`,\n 'react/jsx-dev-runtime': `'/react/jsx-dev-runtime.js'`,\n 'react/jsx-runtime': `'/react/jsx-runtime.js'`,\n 'react-dom': `'/react-dom/index.js'`,\n };\n\n const sharedRemote = `'use client';\\nmodule.exports = { shared: { ${Array.from(\n shared,\n )\n .reduce<string[]>((acc, curr) => {\n acc.push(\n `[${vendorShared[curr] ?? `require.resolve('${curr}')`}]: '${curr}',`,\n );\n return acc;\n }, [])\n .join('\\n')} } };\\n`;\n\n const sharedHost = `'use client';\\nmodule.exports = { shared: { ${Array.from(\n shared,\n )\n .reduce<string[]>((acc, curr) => {\n acc.push(`['${curr}']: () => import('${curr}'),`);\n return acc;\n }, [])\n .join('\\n')} } };\\n`;\n\n const emitSharedFiles = () => {\n mkdirSync(dirname(virtualRemoteComponentSharedRemote), {\n recursive: true,\n });\n\n writeFileSync(virtualRemoteComponentSharedRemote, sharedRemote, 'utf-8');\n writeFileSync(virtualRemoteComponentSharedHost, sharedHost, 'utf-8');\n };\n\n nextConfig.transpilePackages = [\n ...(nextConfig.transpilePackages ?? []),\n 'remote-components/next',\n 'remote-components/next/host',\n '@remote-component/shared/remote',\n '@remote-component/shared/host',\n ];\n\n const alias = {\n '@remote-component/shared/remote': `./${relative(\n process.cwd(),\n virtualRemoteComponentSharedRemote,\n )}`,\n '@remote-component/shared/host': `./${relative(\n process.cwd(),\n virtualRemoteComponentSharedHost,\n )}`,\n };\n\n let projectId =\n process.env.REMOTE_COMPONENTS_PROJECT_ID ||\n process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION ||\n process.env.VERCEL_PROJECT_ID;\n\n if (!projectId) {\n try {\n const projectPath = findUpSync('.vercel/project.json', {\n cwd: process.cwd(),\n });\n if (projectPath) {\n projectId = (\n JSON.parse(readFileSync(projectPath, 'utf8')) as { projectId: string }\n ).projectId;\n }\n } catch {\n // fallback to env‑var above\n }\n }\n\n if (!projectId) {\n const packageJsonPath = findUpSync('package.json', {\n cwd: process.cwd(),\n });\n if (packageJsonPath) {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as {\n name?: string;\n };\n projectId = packageJson.name || basename(process.cwd());\n } else {\n projectId = basename(process.cwd());\n }\n }\n\n if (process.env.TURBOPACK) {\n nextConfig.turbopack = {\n ...nextConfig.turbopack,\n moduleIds: 'named',\n resolveAlias: {\n ...nextConfig.turbopack?.resolveAlias,\n ...alias,\n },\n };\n nextConfig.compiler = {\n ...nextConfig.compiler,\n defineServer: {\n ...nextConfig.compiler?.defineServer,\n 'process.env.REMOTE_COMPONENTS_PROJECT_ID': projectId,\n },\n };\n emitSharedFiles();\n return nextConfig;\n }\n\n // apply the webpack transform\n return webpackTransform(nextConfig, {\n app: { name: projectId },\n alias,\n emitSharedFiles,\n });\n}\n","import { join } from 'node:path';\nimport type { NextConfig } from 'next';\nimport type { WebpackOptionsNormalized } from 'webpack';\nimport { RemoteWebpackRequirePlugin } from './plugins/remote-webpack-require';\nimport { ModuleIdEmbedPlugin } from './plugins/module-id-embed';\nimport { ConditionalExecPlugin } from './plugins/conditional-exec';\nimport { PatchRequirePlugin } from './plugins/patch-require';\n\nexport function transform(\n nextConfig: NextConfig,\n {\n app,\n alias = {},\n emitSharedFiles = () => {\n // no-op by default\n },\n }: {\n app: { name: string };\n alias?: Record<string, string>;\n emitSharedFiles?: () => void;\n },\n) {\n const webpackConfig = nextConfig.webpack;\n\n nextConfig.webpack = (\n baseConfig: WebpackOptionsNormalized,\n webpackContext,\n ) => {\n // execute the client config first, otherwise their config may accidentally\n // overwrite our required config - leading to unexpected errors.\n const config = (\n typeof webpackConfig === 'function'\n ? (webpackConfig(baseConfig, webpackContext) ?? baseConfig)\n : baseConfig\n ) as WebpackOptionsNormalized;\n\n // remote component specific plugins\n config.plugins.push(\n new RemoteWebpackRequirePlugin(app.name),\n new ModuleIdEmbedPlugin(app.name),\n new ConditionalExecPlugin(),\n new PatchRequirePlugin(),\n );\n if (!webpackContext.isServer) {\n // change the chunk loading global to avoid conflicts with other remote components\n config.output.chunkLoadingGlobal = `__remote_chunk_loading_global_${app.name}__`;\n }\n\n config.resolve = {\n ...config.resolve,\n alias: {\n ...config.resolve.alias,\n ...Object.fromEntries(\n Object.entries(alias).map(([key, value]) => [\n key,\n join(process.cwd(), value),\n ]),\n ),\n },\n };\n\n emitSharedFiles();\n return config;\n };\n\n return nextConfig;\n}\n","export function createRemoteWebpackRequireRuntimeModule(webpack: {\n RuntimeModule: new (name: string, stage?: number) => object;\n}) {\n return class RemoteWebpackRequireRuntimeModule extends webpack.RuntimeModule {\n appName: string;\n\n constructor(appName: string) {\n super('remote-webpack-require');\n this.appName = appName;\n }\n\n generate(): null | string {\n return `globalThis.__remote_webpack_require__ = globalThis.__remote_webpack_require__ || {}; globalThis.__remote_webpack_require__[\"${this.appName}\"] = __webpack_require__;`;\n }\n };\n}\n","import type { Compiler, RuntimeModule } from 'webpack';\nimport { createRemoteWebpackRequireRuntimeModule } from './remote-webpack-require-runtime-module';\n\nexport class RemoteWebpackRequirePlugin {\n appName: string;\n\n constructor(appName: string) {\n this.appName = appName;\n }\n\n apply(compiler: Compiler) {\n const RemoteWebpackRequireRuntimeModule =\n createRemoteWebpackRequireRuntimeModule(compiler.webpack);\n\n compiler.hooks.thisCompilation.tap(\n 'RemoteWebpackRequirePlugin',\n (compilation) => {\n compilation.hooks.runtimeRequirementInTree\n .for('__webpack_require__')\n .tap('RemoteWebpackRequirePlugin', (chunk) => {\n compilation.addRuntimeModule(\n chunk,\n new RemoteWebpackRequireRuntimeModule(\n this.appName,\n ) as unknown as RuntimeModule,\n );\n });\n },\n );\n }\n}\n","export function createModuleIdEmbedRuntimeModule(webpack: {\n RuntimeModule: new (name: string, stage?: number) => object;\n}) {\n return class ModuleIdEmbedRuntimeModule extends webpack.RuntimeModule {\n appName: string;\n moduleMap: Record<string | number, unknown>;\n\n constructor(appName: string, moduleMap: Record<string | number, unknown>) {\n super('remote-webpack-module-id-embed');\n this.appName = appName;\n this.moduleMap = moduleMap;\n }\n\n generate(): null | string {\n return `globalThis.__remote_webpack_module_map__ = globalThis.__remote_webpack_module_map__ || {}; globalThis.__remote_webpack_module_map__[\"${this.appName}\"] = ${JSON.stringify(this.moduleMap)};`;\n }\n };\n}\n","import type { NormalModule, Compiler, RuntimeModule } from 'webpack';\nimport { createModuleIdEmbedRuntimeModule } from './module-id-embed-runtime-module';\n\nexport class ModuleIdEmbedPlugin {\n appName: string;\n\n constructor(appName: string) {\n this.appName = appName;\n }\n\n apply(compiler: Compiler) {\n const ModuleIdEmbedRuntimeModule = createModuleIdEmbedRuntimeModule(\n compiler.webpack,\n );\n\n compiler.hooks.thisCompilation.tap('ModuleIdEmbedPlugin', (compilation) => {\n const moduleMap = {} as Record<string, string | number>;\n\n compilation.hooks.runtimeRequirementInTree\n .for(compiler.webpack.RuntimeGlobals.require)\n .tap('ModuleIdEmbedPlugin', (chunk, set) => {\n for (const [key, entry] of compilation.entrypoints) {\n for (const entryChunk of entry.chunks) {\n if (key.includes('nextjs-pages-remote')) {\n for (const mod of compilation.chunkGraph.getChunkModulesIterable(\n entryChunk,\n )) {\n const id = compilation.chunkGraph.getModuleId(mod);\n const normalModule = mod as NormalModule;\n if (id) {\n moduleMap[normalModule.resource || normalModule.request] =\n id;\n }\n }\n }\n }\n }\n for (const mod of compilation.modules) {\n const id = compilation.chunkGraph.getModuleId(mod);\n if (id && mod.layer?.endsWith('browser')) {\n const normalModule = mod as NormalModule;\n moduleMap[normalModule.resource || normalModule.request] = id;\n }\n }\n\n if (Object.keys(moduleMap).length > 0) {\n compilation.addRuntimeModule(\n chunk,\n new ModuleIdEmbedRuntimeModule(\n this.appName,\n moduleMap,\n ) as unknown as RuntimeModule,\n );\n\n set.add(compiler.webpack.RuntimeGlobals.require);\n }\n });\n });\n }\n}\n","import type { Compiler } from 'webpack';\n\nexport class ConditionalExecPlugin {\n apply(compiler: Compiler) {\n const { Compilation, sources } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap(\n 'ConditionalExecPlugin',\n (compilation) => {\n compilation.hooks.processAssets.tap(\n {\n name: 'ConditionalExecPlugin',\n stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,\n },\n (assets) => {\n for (const [name, source] of Object.entries(assets)) {\n if (name.endsWith('.js')) {\n const patchedSource = source\n .source()\n .toString()\n .replace(\n `var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))`,\n `var __webpack_exec__ = (moduleId) => { if (globalThis.__DISABLE_WEBPACK_EXEC__) return; return __webpack_require__(__webpack_require__.s = moduleId); }`,\n );\n compilation.updateAsset(\n name,\n new sources.RawSource(patchedSource),\n );\n }\n }\n },\n );\n },\n );\n }\n}\n","import type { Compiler } from 'webpack';\n\n// This plugin patches the webpack require function to support loading remote components in Next.js\nexport class PatchRequirePlugin {\n apply(compiler: Compiler) {\n const { sources } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap('PatchRequirePlugin', (compilation) => {\n compilation.mainTemplate.hooks.requireExtensions.tap(\n 'PatchRequirePlugin',\n (source) => {\n return new sources.ConcatSource(\n source,\n `const __webpack_require_orig__ = __webpack_require__;\nconst REMOTE_RE = /\\\\[(?<bundle>[a-zA-Z0-9-_]+)\\\\] (?<id>.*)/;\n__webpack_require__ = function __remote_webpack_require__(remoteId) {\n const match = REMOTE_RE.exec(remoteId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_orig__(remoteId);\n }\n if (typeof self.__remote_webpack_require__?.[bundle] !== 'function') {\n throw new Error(\\`Remote component loading error: \"\\${bundle}\"\\`);\n }\n return self.__remote_webpack_require__[bundle](self.__remote_webpack_require__[bundle].type === 'turbopack' ? remoteId : id);\n};\nObject.assign(__webpack_require__, __webpack_require_orig__);\nconst __webpack_require_l__ = __webpack_require__.l;\n__webpack_require__.l = function __remote_webpack_require_l__(url, done, key, chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_l__(url, done, key, chunkId);\n }\n return done();\n};\nconst __webpack_require_o__ = __webpack_require__.o;\n__webpack_require__.o = function __remote_webpack_require_o__(installedChunks, chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_o__(installedChunks, chunkId);\n }\n return installedChunks[chunkId] = 0;\n};\nconst __webpack_require_e__ = __webpack_require__.e;\n__webpack_require__.e = function __remote_webpack_require_e__(chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_e__(chunkId);\n }\n return Promise.resolve([]);\n};`,\n )\n .source()\n .toString();\n },\n );\n });\n }\n}\n"],"mappings":"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","names":["import_node_path"]}
|
|
1
|
+
{"version":3,"sources":["../../src/next/config/index.ts","../../src/next/config/webpack/index.ts","../../src/next/config/webpack/plugins/remote-webpack-require-runtime-module.ts","../../src/next/config/webpack/plugins/remote-webpack-require.ts","../../src/next/config/webpack/plugins/module-id-embed-runtime-module.ts","../../src/next/config/webpack/plugins/module-id-embed.ts","../../src/next/config/webpack/plugins/conditional-exec.ts","../../src/next/config/webpack/plugins/patch-require.ts"],"sourcesContent":["import { basename, dirname, join, relative } from 'node:path';\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { findUpSync } from 'find-up';\nimport type { NextConfig } from 'next';\nimport { transform as webpackTransform } from './webpack';\n\ninterface WithRemoteComponentsOptions {\n /**\n * An array of package names that should be shared between the host and remote components.\n * This is useful for ensuring that both the host and remote components use the same version\n * of shared libraries.\n *\n * Essential packages are included by default: `react`, `react-dom`, `next/navigation`, `next/link`, `next/form`, `next/image`, and `next/script`.\n */\n shared?: string[];\n}\n\n/**\n * This function configures Next.js to support Remote Components.\n * You need to also use the `withMicrofrontends` function to extend your Next.js configuration.\n *\n * @param nextConfig - The Next.js configuration object.\n * @param options - Optional configuration for remote components.\n * @returns The modified Next.js configuration object with remote components support.\n *\n * @example\n *\n * ```js\n * import { withMicrofrontends } from '@vercel/microfrontends/next/config';\n * import { withRemoteComponents } from 'remote-components/next/config';\n *\n * const nextConfig = {\n * // your Next.js configuration\n * };\n *\n * export default withRemoteComponents(\n * withMicrofrontends(nextConfig),\n * {\n * shared: ['some-package', 'another-package'],\n * },\n * );\n * ```\n */\nexport function withRemoteComponents(\n nextConfig: NextConfig,\n options?: WithRemoteComponentsOptions,\n) {\n const virtualRemoteComponentSharedRemote = join(\n process.cwd(),\n nextConfig.distDir ?? '.next',\n 'remote-components/shared/remote.tsx',\n );\n const virtualRemoteComponentSharedHost = join(\n process.cwd(),\n nextConfig.distDir ?? '.next',\n 'remote-components/shared/host.tsx',\n );\n\n const shared = new Set([\n ...[\n 'react',\n 'react/jsx-dev-runtime',\n 'react/jsx-runtime',\n 'react-dom',\n 'react-dom/client',\n 'next/navigation',\n 'next/link',\n 'next/form',\n 'next/image',\n 'next/script',\n ],\n ...(options?.shared ?? []),\n ]);\n\n const vendorShared: Record<string, string> = {\n react: `'/react/index.js'`,\n 'react/jsx-dev-runtime': `'/react/jsx-dev-runtime.js'`,\n 'react/jsx-runtime': `'/react/jsx-runtime.js'`,\n 'react-dom': `'/react-dom/index.js'`,\n };\n\n const sharedRemote = `'use client';\\nmodule.exports = { shared: { ${Array.from(\n shared,\n )\n .reduce<string[]>((acc, curr) => {\n acc.push(\n `[${vendorShared[curr] ?? `require.resolve('${curr}')`}]: '${curr}',`,\n );\n return acc;\n }, [])\n .join('\\n')} } };\\n`;\n\n const sharedHost = `'use client';\\nmodule.exports = { shared: { ${Array.from(\n shared,\n )\n .reduce<string[]>((acc, curr) => {\n acc.push(`['${curr}']: () => import('${curr}'),`);\n return acc;\n }, [])\n .join('\\n')} } };\\n`;\n\n const emitSharedFiles = () => {\n mkdirSync(dirname(virtualRemoteComponentSharedRemote), {\n recursive: true,\n });\n\n writeFileSync(virtualRemoteComponentSharedRemote, sharedRemote, 'utf-8');\n writeFileSync(virtualRemoteComponentSharedHost, sharedHost, 'utf-8');\n };\n\n nextConfig.transpilePackages = [\n ...(nextConfig.transpilePackages ?? []),\n 'remote-components/next',\n 'remote-components/next/host',\n '@remote-component/shared/remote',\n '@remote-component/shared/host',\n ];\n\n const alias = {\n '@remote-component/shared/remote': `./${relative(\n process.cwd(),\n virtualRemoteComponentSharedRemote,\n )}`,\n '@remote-component/shared/host': `./${relative(\n process.cwd(),\n virtualRemoteComponentSharedHost,\n )}`,\n };\n\n let projectId =\n process.env.REMOTE_COMPONENTS_PROJECT_ID ||\n process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION ||\n process.env.VERCEL_PROJECT_ID;\n\n if (!projectId) {\n try {\n const projectPath = findUpSync('.vercel/project.json', {\n cwd: process.cwd(),\n });\n if (projectPath) {\n projectId = (\n JSON.parse(readFileSync(projectPath, 'utf8')) as { projectId: string }\n ).projectId;\n }\n } catch {\n // fallback to env‑var above\n }\n }\n\n if (!projectId) {\n const packageJsonPath = findUpSync('package.json', {\n cwd: process.cwd(),\n });\n if (packageJsonPath) {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as {\n name?: string;\n };\n projectId = packageJson.name || basename(process.cwd());\n } else {\n projectId = basename(process.cwd());\n }\n }\n\n process.env.REMOTE_COMPONENTS_PROJECT_ID = projectId;\n\n if (process.env.TURBOPACK) {\n nextConfig.turbopack = {\n ...nextConfig.turbopack,\n moduleIds: 'named',\n resolveAlias: {\n ...nextConfig.turbopack?.resolveAlias,\n ...alias,\n },\n };\n nextConfig.compiler = {\n ...nextConfig.compiler,\n defineServer: {\n ...nextConfig.compiler?.defineServer,\n 'process.env.REMOTE_COMPONENTS_PROJECT_ID': projectId,\n },\n };\n emitSharedFiles();\n return nextConfig;\n }\n\n // apply the webpack transform\n return webpackTransform(nextConfig, {\n app: { name: projectId },\n alias,\n emitSharedFiles,\n });\n}\n","import { join } from 'node:path';\nimport type { NextConfig } from 'next';\nimport type { WebpackOptionsNormalized } from 'webpack';\nimport { RemoteWebpackRequirePlugin } from './plugins/remote-webpack-require';\nimport { ModuleIdEmbedPlugin } from './plugins/module-id-embed';\nimport { ConditionalExecPlugin } from './plugins/conditional-exec';\nimport { PatchRequirePlugin } from './plugins/patch-require';\n\nexport function transform(\n nextConfig: NextConfig,\n {\n app,\n alias = {},\n emitSharedFiles = () => {\n // no-op by default\n },\n }: {\n app: { name: string };\n alias?: Record<string, string>;\n emitSharedFiles?: () => void;\n },\n) {\n const webpackConfig = nextConfig.webpack;\n\n nextConfig.webpack = (\n baseConfig: WebpackOptionsNormalized,\n webpackContext,\n ) => {\n // execute the client config first, otherwise their config may accidentally\n // overwrite our required config - leading to unexpected errors.\n const config = (\n typeof webpackConfig === 'function'\n ? (webpackConfig(baseConfig, webpackContext) ?? baseConfig)\n : baseConfig\n ) as WebpackOptionsNormalized;\n\n // remote component specific plugins\n config.plugins.push(\n new RemoteWebpackRequirePlugin(app.name),\n new ModuleIdEmbedPlugin(app.name),\n new ConditionalExecPlugin(),\n new PatchRequirePlugin(),\n );\n if (!webpackContext.isServer) {\n // change the chunk loading global to avoid conflicts with other remote components\n config.output.chunkLoadingGlobal = `__remote_chunk_loading_global_${app.name}__`;\n }\n\n config.resolve = {\n ...config.resolve,\n alias: {\n ...config.resolve.alias,\n ...Object.fromEntries(\n Object.entries(alias).map(([key, value]) => [\n key,\n join(process.cwd(), value),\n ]),\n ),\n },\n };\n\n emitSharedFiles();\n return config;\n };\n\n return nextConfig;\n}\n","export function createRemoteWebpackRequireRuntimeModule(webpack: {\n RuntimeModule: new (name: string, stage?: number) => object;\n}) {\n return class RemoteWebpackRequireRuntimeModule extends webpack.RuntimeModule {\n appName: string;\n\n constructor(appName: string) {\n super('remote-webpack-require');\n this.appName = appName;\n }\n\n generate(): null | string {\n return `globalThis.__remote_webpack_require__ = globalThis.__remote_webpack_require__ || {}; globalThis.__remote_webpack_require__[\"${this.appName}\"] = __webpack_require__;`;\n }\n };\n}\n","import type { Compiler, RuntimeModule } from 'webpack';\nimport { createRemoteWebpackRequireRuntimeModule } from './remote-webpack-require-runtime-module';\n\nexport class RemoteWebpackRequirePlugin {\n appName: string;\n\n constructor(appName: string) {\n this.appName = appName;\n }\n\n apply(compiler: Compiler) {\n const RemoteWebpackRequireRuntimeModule =\n createRemoteWebpackRequireRuntimeModule(compiler.webpack);\n\n compiler.hooks.thisCompilation.tap(\n 'RemoteWebpackRequirePlugin',\n (compilation) => {\n compilation.hooks.runtimeRequirementInTree\n .for('__webpack_require__')\n .tap('RemoteWebpackRequirePlugin', (chunk) => {\n compilation.addRuntimeModule(\n chunk,\n new RemoteWebpackRequireRuntimeModule(\n this.appName,\n ) as unknown as RuntimeModule,\n );\n });\n },\n );\n }\n}\n","export function createModuleIdEmbedRuntimeModule(webpack: {\n RuntimeModule: new (name: string, stage?: number) => object;\n}) {\n return class ModuleIdEmbedRuntimeModule extends webpack.RuntimeModule {\n appName: string;\n moduleMap: Record<string | number, unknown>;\n\n constructor(appName: string, moduleMap: Record<string | number, unknown>) {\n super('remote-webpack-module-id-embed');\n this.appName = appName;\n this.moduleMap = moduleMap;\n }\n\n generate(): null | string {\n return `globalThis.__remote_webpack_module_map__ = globalThis.__remote_webpack_module_map__ || {}; globalThis.__remote_webpack_module_map__[\"${this.appName}\"] = ${JSON.stringify(this.moduleMap)};`;\n }\n };\n}\n","import type { NormalModule, Compiler, RuntimeModule } from 'webpack';\nimport { createModuleIdEmbedRuntimeModule } from './module-id-embed-runtime-module';\n\nexport class ModuleIdEmbedPlugin {\n appName: string;\n\n constructor(appName: string) {\n this.appName = appName;\n }\n\n apply(compiler: Compiler) {\n const ModuleIdEmbedRuntimeModule = createModuleIdEmbedRuntimeModule(\n compiler.webpack,\n );\n\n compiler.hooks.thisCompilation.tap('ModuleIdEmbedPlugin', (compilation) => {\n const moduleMap = {} as Record<string, string | number>;\n\n compilation.hooks.runtimeRequirementInTree\n .for(compiler.webpack.RuntimeGlobals.require)\n .tap('ModuleIdEmbedPlugin', (chunk, set) => {\n for (const [key, entry] of compilation.entrypoints) {\n for (const entryChunk of entry.chunks) {\n if (key.includes('nextjs-pages-remote')) {\n for (const mod of compilation.chunkGraph.getChunkModulesIterable(\n entryChunk,\n )) {\n const id = compilation.chunkGraph.getModuleId(mod);\n const normalModule = mod as NormalModule;\n if (id) {\n moduleMap[normalModule.resource || normalModule.request] =\n id;\n }\n }\n }\n }\n }\n for (const mod of compilation.modules) {\n const id = compilation.chunkGraph.getModuleId(mod);\n if (id && mod.layer?.endsWith('browser')) {\n const normalModule = mod as NormalModule;\n moduleMap[normalModule.resource || normalModule.request] = id;\n }\n }\n\n if (Object.keys(moduleMap).length > 0) {\n compilation.addRuntimeModule(\n chunk,\n new ModuleIdEmbedRuntimeModule(\n this.appName,\n moduleMap,\n ) as unknown as RuntimeModule,\n );\n\n set.add(compiler.webpack.RuntimeGlobals.require);\n }\n });\n });\n }\n}\n","import type { Compiler } from 'webpack';\n\nexport class ConditionalExecPlugin {\n apply(compiler: Compiler) {\n const { Compilation, sources } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap(\n 'ConditionalExecPlugin',\n (compilation) => {\n compilation.hooks.processAssets.tap(\n {\n name: 'ConditionalExecPlugin',\n stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,\n },\n (assets) => {\n for (const [name, source] of Object.entries(assets)) {\n if (name.endsWith('.js')) {\n const patchedSource = source\n .source()\n .toString()\n .replace(\n `var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))`,\n `var __webpack_exec__ = (moduleId) => { if (globalThis.__DISABLE_WEBPACK_EXEC__) return; return __webpack_require__(__webpack_require__.s = moduleId); }`,\n );\n compilation.updateAsset(\n name,\n new sources.RawSource(patchedSource),\n );\n }\n }\n },\n );\n },\n );\n }\n}\n","import type { Compiler } from 'webpack';\n\n// This plugin patches the webpack require function to support loading remote components in Next.js\nexport class PatchRequirePlugin {\n apply(compiler: Compiler) {\n const { sources } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap('PatchRequirePlugin', (compilation) => {\n compilation.mainTemplate.hooks.requireExtensions.tap(\n 'PatchRequirePlugin',\n (source) => {\n return new sources.ConcatSource(\n source,\n `const __webpack_require_orig__ = __webpack_require__;\nconst REMOTE_RE = /\\\\[(?<bundle>[a-zA-Z0-9-_]+)\\\\] (?<id>.*)/;\n__webpack_require__ = function __remote_webpack_require__(remoteId) {\n const match = REMOTE_RE.exec(remoteId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_orig__(remoteId);\n }\n if (typeof self.__remote_webpack_require__?.[bundle] !== 'function') {\n throw new Error(\\`Remote component loading error: \"\\${bundle}\"\\`);\n }\n return self.__remote_webpack_require__[bundle](self.__remote_webpack_require__[bundle].type === 'turbopack' ? remoteId : id);\n};\nObject.assign(__webpack_require__, __webpack_require_orig__);\nconst __webpack_require_l__ = __webpack_require__.l;\n__webpack_require__.l = function __remote_webpack_require_l__(url, done, key, chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_l__(url, done, key, chunkId);\n }\n return done();\n};\nconst __webpack_require_o__ = __webpack_require__.o;\n__webpack_require__.o = function __remote_webpack_require_o__(installedChunks, chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_o__(installedChunks, chunkId);\n }\n return installedChunks[chunkId] = 0;\n};\nconst __webpack_require_e__ = __webpack_require__.e;\n__webpack_require__.e = function __remote_webpack_require_e__(chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_e__(chunkId);\n }\n return Promise.resolve([]);\n};`,\n )\n .source()\n .toString();\n },\n );\n });\n }\n}\n"],"mappings":"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","names":["import_node_path"]}
|
package/dist/next/config.js
CHANGED
package/dist/next/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/config/index.ts","../../src/next/config/webpack/index.ts","../../src/next/config/webpack/plugins/remote-webpack-require-runtime-module.ts","../../src/next/config/webpack/plugins/remote-webpack-require.ts","../../src/next/config/webpack/plugins/module-id-embed-runtime-module.ts","../../src/next/config/webpack/plugins/module-id-embed.ts","../../src/next/config/webpack/plugins/conditional-exec.ts","../../src/next/config/webpack/plugins/patch-require.ts"],"sourcesContent":["import { basename, dirname, join, relative } from 'node:path';\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { findUpSync } from 'find-up';\nimport type { NextConfig } from 'next';\nimport { transform as webpackTransform } from './webpack';\n\ninterface WithRemoteComponentsOptions {\n /**\n * An array of package names that should be shared between the host and remote components.\n * This is useful for ensuring that both the host and remote components use the same version\n * of shared libraries.\n *\n * Essential packages are included by default: `react`, `react-dom`, `next/navigation`, `next/link`, `next/form`, `next/image`, and `next/script`.\n */\n shared?: string[];\n}\n\n/**\n * This function configures Next.js to support Remote Components.\n * You need to also use the `withMicrofrontends` function to extend your Next.js configuration.\n *\n * @param nextConfig - The Next.js configuration object.\n * @param options - Optional configuration for remote components.\n * @returns The modified Next.js configuration object with remote components support.\n *\n * @example\n *\n * ```js\n * import { withMicrofrontends } from '@vercel/microfrontends/next/config';\n * import { withRemoteComponents } from 'remote-components/next/config';\n *\n * const nextConfig = {\n * // your Next.js configuration\n * };\n *\n * export default withRemoteComponents(\n * withMicrofrontends(nextConfig),\n * {\n * shared: ['some-package', 'another-package'],\n * },\n * );\n * ```\n */\nexport function withRemoteComponents(\n nextConfig: NextConfig,\n options?: WithRemoteComponentsOptions,\n) {\n const virtualRemoteComponentSharedRemote = join(\n process.cwd(),\n nextConfig.distDir ?? '.next',\n 'remote-components/shared/remote.tsx',\n );\n const virtualRemoteComponentSharedHost = join(\n process.cwd(),\n nextConfig.distDir ?? '.next',\n 'remote-components/shared/host.tsx',\n );\n\n const shared = new Set([\n ...[\n 'react',\n 'react/jsx-dev-runtime',\n 'react/jsx-runtime',\n 'react-dom',\n 'react-dom/client',\n 'next/navigation',\n 'next/link',\n 'next/form',\n 'next/image',\n 'next/script',\n ],\n ...(options?.shared ?? []),\n ]);\n\n const vendorShared: Record<string, string> = {\n react: `'/react/index.js'`,\n 'react/jsx-dev-runtime': `'/react/jsx-dev-runtime.js'`,\n 'react/jsx-runtime': `'/react/jsx-runtime.js'`,\n 'react-dom': `'/react-dom/index.js'`,\n };\n\n const sharedRemote = `'use client';\\nmodule.exports = { shared: { ${Array.from(\n shared,\n )\n .reduce<string[]>((acc, curr) => {\n acc.push(\n `[${vendorShared[curr] ?? `require.resolve('${curr}')`}]: '${curr}',`,\n );\n return acc;\n }, [])\n .join('\\n')} } };\\n`;\n\n const sharedHost = `'use client';\\nmodule.exports = { shared: { ${Array.from(\n shared,\n )\n .reduce<string[]>((acc, curr) => {\n acc.push(`['${curr}']: () => import('${curr}'),`);\n return acc;\n }, [])\n .join('\\n')} } };\\n`;\n\n const emitSharedFiles = () => {\n mkdirSync(dirname(virtualRemoteComponentSharedRemote), {\n recursive: true,\n });\n\n writeFileSync(virtualRemoteComponentSharedRemote, sharedRemote, 'utf-8');\n writeFileSync(virtualRemoteComponentSharedHost, sharedHost, 'utf-8');\n };\n\n nextConfig.transpilePackages = [\n ...(nextConfig.transpilePackages ?? []),\n 'remote-components/next',\n 'remote-components/next/host',\n '@remote-component/shared/remote',\n '@remote-component/shared/host',\n ];\n\n const alias = {\n '@remote-component/shared/remote': `./${relative(\n process.cwd(),\n virtualRemoteComponentSharedRemote,\n )}`,\n '@remote-component/shared/host': `./${relative(\n process.cwd(),\n virtualRemoteComponentSharedHost,\n )}`,\n };\n\n let projectId =\n process.env.REMOTE_COMPONENTS_PROJECT_ID ||\n process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION ||\n process.env.VERCEL_PROJECT_ID;\n\n if (!projectId) {\n try {\n const projectPath = findUpSync('.vercel/project.json', {\n cwd: process.cwd(),\n });\n if (projectPath) {\n projectId = (\n JSON.parse(readFileSync(projectPath, 'utf8')) as { projectId: string }\n ).projectId;\n }\n } catch {\n // fallback to env‑var above\n }\n }\n\n if (!projectId) {\n const packageJsonPath = findUpSync('package.json', {\n cwd: process.cwd(),\n });\n if (packageJsonPath) {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as {\n name?: string;\n };\n projectId = packageJson.name || basename(process.cwd());\n } else {\n projectId = basename(process.cwd());\n }\n }\n\n if (process.env.TURBOPACK) {\n nextConfig.turbopack = {\n ...nextConfig.turbopack,\n moduleIds: 'named',\n resolveAlias: {\n ...nextConfig.turbopack?.resolveAlias,\n ...alias,\n },\n };\n nextConfig.compiler = {\n ...nextConfig.compiler,\n defineServer: {\n ...nextConfig.compiler?.defineServer,\n 'process.env.REMOTE_COMPONENTS_PROJECT_ID': projectId,\n },\n };\n emitSharedFiles();\n return nextConfig;\n }\n\n // apply the webpack transform\n return webpackTransform(nextConfig, {\n app: { name: projectId },\n alias,\n emitSharedFiles,\n });\n}\n","import { join } from 'node:path';\nimport type { NextConfig } from 'next';\nimport type { WebpackOptionsNormalized } from 'webpack';\nimport { RemoteWebpackRequirePlugin } from './plugins/remote-webpack-require';\nimport { ModuleIdEmbedPlugin } from './plugins/module-id-embed';\nimport { ConditionalExecPlugin } from './plugins/conditional-exec';\nimport { PatchRequirePlugin } from './plugins/patch-require';\n\nexport function transform(\n nextConfig: NextConfig,\n {\n app,\n alias = {},\n emitSharedFiles = () => {\n // no-op by default\n },\n }: {\n app: { name: string };\n alias?: Record<string, string>;\n emitSharedFiles?: () => void;\n },\n) {\n const webpackConfig = nextConfig.webpack;\n\n nextConfig.webpack = (\n baseConfig: WebpackOptionsNormalized,\n webpackContext,\n ) => {\n // execute the client config first, otherwise their config may accidentally\n // overwrite our required config - leading to unexpected errors.\n const config = (\n typeof webpackConfig === 'function'\n ? (webpackConfig(baseConfig, webpackContext) ?? baseConfig)\n : baseConfig\n ) as WebpackOptionsNormalized;\n\n // remote component specific plugins\n config.plugins.push(\n new RemoteWebpackRequirePlugin(app.name),\n new ModuleIdEmbedPlugin(app.name),\n new ConditionalExecPlugin(),\n new PatchRequirePlugin(),\n );\n if (!webpackContext.isServer) {\n // change the chunk loading global to avoid conflicts with other remote components\n config.output.chunkLoadingGlobal = `__remote_chunk_loading_global_${app.name}__`;\n }\n\n config.resolve = {\n ...config.resolve,\n alias: {\n ...config.resolve.alias,\n ...Object.fromEntries(\n Object.entries(alias).map(([key, value]) => [\n key,\n join(process.cwd(), value),\n ]),\n ),\n },\n };\n\n emitSharedFiles();\n return config;\n };\n\n return nextConfig;\n}\n","export function createRemoteWebpackRequireRuntimeModule(webpack: {\n RuntimeModule: new (name: string, stage?: number) => object;\n}) {\n return class RemoteWebpackRequireRuntimeModule extends webpack.RuntimeModule {\n appName: string;\n\n constructor(appName: string) {\n super('remote-webpack-require');\n this.appName = appName;\n }\n\n generate(): null | string {\n return `globalThis.__remote_webpack_require__ = globalThis.__remote_webpack_require__ || {}; globalThis.__remote_webpack_require__[\"${this.appName}\"] = __webpack_require__;`;\n }\n };\n}\n","import type { Compiler, RuntimeModule } from 'webpack';\nimport { createRemoteWebpackRequireRuntimeModule } from './remote-webpack-require-runtime-module';\n\nexport class RemoteWebpackRequirePlugin {\n appName: string;\n\n constructor(appName: string) {\n this.appName = appName;\n }\n\n apply(compiler: Compiler) {\n const RemoteWebpackRequireRuntimeModule =\n createRemoteWebpackRequireRuntimeModule(compiler.webpack);\n\n compiler.hooks.thisCompilation.tap(\n 'RemoteWebpackRequirePlugin',\n (compilation) => {\n compilation.hooks.runtimeRequirementInTree\n .for('__webpack_require__')\n .tap('RemoteWebpackRequirePlugin', (chunk) => {\n compilation.addRuntimeModule(\n chunk,\n new RemoteWebpackRequireRuntimeModule(\n this.appName,\n ) as unknown as RuntimeModule,\n );\n });\n },\n );\n }\n}\n","export function createModuleIdEmbedRuntimeModule(webpack: {\n RuntimeModule: new (name: string, stage?: number) => object;\n}) {\n return class ModuleIdEmbedRuntimeModule extends webpack.RuntimeModule {\n appName: string;\n moduleMap: Record<string | number, unknown>;\n\n constructor(appName: string, moduleMap: Record<string | number, unknown>) {\n super('remote-webpack-module-id-embed');\n this.appName = appName;\n this.moduleMap = moduleMap;\n }\n\n generate(): null | string {\n return `globalThis.__remote_webpack_module_map__ = globalThis.__remote_webpack_module_map__ || {}; globalThis.__remote_webpack_module_map__[\"${this.appName}\"] = ${JSON.stringify(this.moduleMap)};`;\n }\n };\n}\n","import type { NormalModule, Compiler, RuntimeModule } from 'webpack';\nimport { createModuleIdEmbedRuntimeModule } from './module-id-embed-runtime-module';\n\nexport class ModuleIdEmbedPlugin {\n appName: string;\n\n constructor(appName: string) {\n this.appName = appName;\n }\n\n apply(compiler: Compiler) {\n const ModuleIdEmbedRuntimeModule = createModuleIdEmbedRuntimeModule(\n compiler.webpack,\n );\n\n compiler.hooks.thisCompilation.tap('ModuleIdEmbedPlugin', (compilation) => {\n const moduleMap = {} as Record<string, string | number>;\n\n compilation.hooks.runtimeRequirementInTree\n .for(compiler.webpack.RuntimeGlobals.require)\n .tap('ModuleIdEmbedPlugin', (chunk, set) => {\n for (const [key, entry] of compilation.entrypoints) {\n for (const entryChunk of entry.chunks) {\n if (key.includes('nextjs-pages-remote')) {\n for (const mod of compilation.chunkGraph.getChunkModulesIterable(\n entryChunk,\n )) {\n const id = compilation.chunkGraph.getModuleId(mod);\n const normalModule = mod as NormalModule;\n if (id) {\n moduleMap[normalModule.resource || normalModule.request] =\n id;\n }\n }\n }\n }\n }\n for (const mod of compilation.modules) {\n const id = compilation.chunkGraph.getModuleId(mod);\n if (id && mod.layer?.endsWith('browser')) {\n const normalModule = mod as NormalModule;\n moduleMap[normalModule.resource || normalModule.request] = id;\n }\n }\n\n if (Object.keys(moduleMap).length > 0) {\n compilation.addRuntimeModule(\n chunk,\n new ModuleIdEmbedRuntimeModule(\n this.appName,\n moduleMap,\n ) as unknown as RuntimeModule,\n );\n\n set.add(compiler.webpack.RuntimeGlobals.require);\n }\n });\n });\n }\n}\n","import type { Compiler } from 'webpack';\n\nexport class ConditionalExecPlugin {\n apply(compiler: Compiler) {\n const { Compilation, sources } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap(\n 'ConditionalExecPlugin',\n (compilation) => {\n compilation.hooks.processAssets.tap(\n {\n name: 'ConditionalExecPlugin',\n stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,\n },\n (assets) => {\n for (const [name, source] of Object.entries(assets)) {\n if (name.endsWith('.js')) {\n const patchedSource = source\n .source()\n .toString()\n .replace(\n `var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))`,\n `var __webpack_exec__ = (moduleId) => { if (globalThis.__DISABLE_WEBPACK_EXEC__) return; return __webpack_require__(__webpack_require__.s = moduleId); }`,\n );\n compilation.updateAsset(\n name,\n new sources.RawSource(patchedSource),\n );\n }\n }\n },\n );\n },\n );\n }\n}\n","import type { Compiler } from 'webpack';\n\n// This plugin patches the webpack require function to support loading remote components in Next.js\nexport class PatchRequirePlugin {\n apply(compiler: Compiler) {\n const { sources } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap('PatchRequirePlugin', (compilation) => {\n compilation.mainTemplate.hooks.requireExtensions.tap(\n 'PatchRequirePlugin',\n (source) => {\n return new sources.ConcatSource(\n source,\n `const __webpack_require_orig__ = __webpack_require__;\nconst REMOTE_RE = /\\\\[(?<bundle>[a-zA-Z0-9-_]+)\\\\] (?<id>.*)/;\n__webpack_require__ = function __remote_webpack_require__(remoteId) {\n const match = REMOTE_RE.exec(remoteId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_orig__(remoteId);\n }\n if (typeof self.__remote_webpack_require__?.[bundle] !== 'function') {\n throw new Error(\\`Remote component loading error: \"\\${bundle}\"\\`);\n }\n return self.__remote_webpack_require__[bundle](self.__remote_webpack_require__[bundle].type === 'turbopack' ? remoteId : id);\n};\nObject.assign(__webpack_require__, __webpack_require_orig__);\nconst __webpack_require_l__ = __webpack_require__.l;\n__webpack_require__.l = function __remote_webpack_require_l__(url, done, key, chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_l__(url, done, key, chunkId);\n }\n return done();\n};\nconst __webpack_require_o__ = __webpack_require__.o;\n__webpack_require__.o = function __remote_webpack_require_o__(installedChunks, chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_o__(installedChunks, chunkId);\n }\n return installedChunks[chunkId] = 0;\n};\nconst __webpack_require_e__ = __webpack_require__.e;\n__webpack_require__.e = function __remote_webpack_require_e__(chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_e__(chunkId);\n }\n return Promise.resolve([]);\n};`,\n )\n .source()\n .toString();\n },\n );\n });\n }\n}\n"],"mappings":"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","names":["join","join"]}
|
|
1
|
+
{"version":3,"sources":["../../src/next/config/index.ts","../../src/next/config/webpack/index.ts","../../src/next/config/webpack/plugins/remote-webpack-require-runtime-module.ts","../../src/next/config/webpack/plugins/remote-webpack-require.ts","../../src/next/config/webpack/plugins/module-id-embed-runtime-module.ts","../../src/next/config/webpack/plugins/module-id-embed.ts","../../src/next/config/webpack/plugins/conditional-exec.ts","../../src/next/config/webpack/plugins/patch-require.ts"],"sourcesContent":["import { basename, dirname, join, relative } from 'node:path';\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { findUpSync } from 'find-up';\nimport type { NextConfig } from 'next';\nimport { transform as webpackTransform } from './webpack';\n\ninterface WithRemoteComponentsOptions {\n /**\n * An array of package names that should be shared between the host and remote components.\n * This is useful for ensuring that both the host and remote components use the same version\n * of shared libraries.\n *\n * Essential packages are included by default: `react`, `react-dom`, `next/navigation`, `next/link`, `next/form`, `next/image`, and `next/script`.\n */\n shared?: string[];\n}\n\n/**\n * This function configures Next.js to support Remote Components.\n * You need to also use the `withMicrofrontends` function to extend your Next.js configuration.\n *\n * @param nextConfig - The Next.js configuration object.\n * @param options - Optional configuration for remote components.\n * @returns The modified Next.js configuration object with remote components support.\n *\n * @example\n *\n * ```js\n * import { withMicrofrontends } from '@vercel/microfrontends/next/config';\n * import { withRemoteComponents } from 'remote-components/next/config';\n *\n * const nextConfig = {\n * // your Next.js configuration\n * };\n *\n * export default withRemoteComponents(\n * withMicrofrontends(nextConfig),\n * {\n * shared: ['some-package', 'another-package'],\n * },\n * );\n * ```\n */\nexport function withRemoteComponents(\n nextConfig: NextConfig,\n options?: WithRemoteComponentsOptions,\n) {\n const virtualRemoteComponentSharedRemote = join(\n process.cwd(),\n nextConfig.distDir ?? '.next',\n 'remote-components/shared/remote.tsx',\n );\n const virtualRemoteComponentSharedHost = join(\n process.cwd(),\n nextConfig.distDir ?? '.next',\n 'remote-components/shared/host.tsx',\n );\n\n const shared = new Set([\n ...[\n 'react',\n 'react/jsx-dev-runtime',\n 'react/jsx-runtime',\n 'react-dom',\n 'react-dom/client',\n 'next/navigation',\n 'next/link',\n 'next/form',\n 'next/image',\n 'next/script',\n ],\n ...(options?.shared ?? []),\n ]);\n\n const vendorShared: Record<string, string> = {\n react: `'/react/index.js'`,\n 'react/jsx-dev-runtime': `'/react/jsx-dev-runtime.js'`,\n 'react/jsx-runtime': `'/react/jsx-runtime.js'`,\n 'react-dom': `'/react-dom/index.js'`,\n };\n\n const sharedRemote = `'use client';\\nmodule.exports = { shared: { ${Array.from(\n shared,\n )\n .reduce<string[]>((acc, curr) => {\n acc.push(\n `[${vendorShared[curr] ?? `require.resolve('${curr}')`}]: '${curr}',`,\n );\n return acc;\n }, [])\n .join('\\n')} } };\\n`;\n\n const sharedHost = `'use client';\\nmodule.exports = { shared: { ${Array.from(\n shared,\n )\n .reduce<string[]>((acc, curr) => {\n acc.push(`['${curr}']: () => import('${curr}'),`);\n return acc;\n }, [])\n .join('\\n')} } };\\n`;\n\n const emitSharedFiles = () => {\n mkdirSync(dirname(virtualRemoteComponentSharedRemote), {\n recursive: true,\n });\n\n writeFileSync(virtualRemoteComponentSharedRemote, sharedRemote, 'utf-8');\n writeFileSync(virtualRemoteComponentSharedHost, sharedHost, 'utf-8');\n };\n\n nextConfig.transpilePackages = [\n ...(nextConfig.transpilePackages ?? []),\n 'remote-components/next',\n 'remote-components/next/host',\n '@remote-component/shared/remote',\n '@remote-component/shared/host',\n ];\n\n const alias = {\n '@remote-component/shared/remote': `./${relative(\n process.cwd(),\n virtualRemoteComponentSharedRemote,\n )}`,\n '@remote-component/shared/host': `./${relative(\n process.cwd(),\n virtualRemoteComponentSharedHost,\n )}`,\n };\n\n let projectId =\n process.env.REMOTE_COMPONENTS_PROJECT_ID ||\n process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION ||\n process.env.VERCEL_PROJECT_ID;\n\n if (!projectId) {\n try {\n const projectPath = findUpSync('.vercel/project.json', {\n cwd: process.cwd(),\n });\n if (projectPath) {\n projectId = (\n JSON.parse(readFileSync(projectPath, 'utf8')) as { projectId: string }\n ).projectId;\n }\n } catch {\n // fallback to env‑var above\n }\n }\n\n if (!projectId) {\n const packageJsonPath = findUpSync('package.json', {\n cwd: process.cwd(),\n });\n if (packageJsonPath) {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as {\n name?: string;\n };\n projectId = packageJson.name || basename(process.cwd());\n } else {\n projectId = basename(process.cwd());\n }\n }\n\n process.env.REMOTE_COMPONENTS_PROJECT_ID = projectId;\n\n if (process.env.TURBOPACK) {\n nextConfig.turbopack = {\n ...nextConfig.turbopack,\n moduleIds: 'named',\n resolveAlias: {\n ...nextConfig.turbopack?.resolveAlias,\n ...alias,\n },\n };\n nextConfig.compiler = {\n ...nextConfig.compiler,\n defineServer: {\n ...nextConfig.compiler?.defineServer,\n 'process.env.REMOTE_COMPONENTS_PROJECT_ID': projectId,\n },\n };\n emitSharedFiles();\n return nextConfig;\n }\n\n // apply the webpack transform\n return webpackTransform(nextConfig, {\n app: { name: projectId },\n alias,\n emitSharedFiles,\n });\n}\n","import { join } from 'node:path';\nimport type { NextConfig } from 'next';\nimport type { WebpackOptionsNormalized } from 'webpack';\nimport { RemoteWebpackRequirePlugin } from './plugins/remote-webpack-require';\nimport { ModuleIdEmbedPlugin } from './plugins/module-id-embed';\nimport { ConditionalExecPlugin } from './plugins/conditional-exec';\nimport { PatchRequirePlugin } from './plugins/patch-require';\n\nexport function transform(\n nextConfig: NextConfig,\n {\n app,\n alias = {},\n emitSharedFiles = () => {\n // no-op by default\n },\n }: {\n app: { name: string };\n alias?: Record<string, string>;\n emitSharedFiles?: () => void;\n },\n) {\n const webpackConfig = nextConfig.webpack;\n\n nextConfig.webpack = (\n baseConfig: WebpackOptionsNormalized,\n webpackContext,\n ) => {\n // execute the client config first, otherwise their config may accidentally\n // overwrite our required config - leading to unexpected errors.\n const config = (\n typeof webpackConfig === 'function'\n ? (webpackConfig(baseConfig, webpackContext) ?? baseConfig)\n : baseConfig\n ) as WebpackOptionsNormalized;\n\n // remote component specific plugins\n config.plugins.push(\n new RemoteWebpackRequirePlugin(app.name),\n new ModuleIdEmbedPlugin(app.name),\n new ConditionalExecPlugin(),\n new PatchRequirePlugin(),\n );\n if (!webpackContext.isServer) {\n // change the chunk loading global to avoid conflicts with other remote components\n config.output.chunkLoadingGlobal = `__remote_chunk_loading_global_${app.name}__`;\n }\n\n config.resolve = {\n ...config.resolve,\n alias: {\n ...config.resolve.alias,\n ...Object.fromEntries(\n Object.entries(alias).map(([key, value]) => [\n key,\n join(process.cwd(), value),\n ]),\n ),\n },\n };\n\n emitSharedFiles();\n return config;\n };\n\n return nextConfig;\n}\n","export function createRemoteWebpackRequireRuntimeModule(webpack: {\n RuntimeModule: new (name: string, stage?: number) => object;\n}) {\n return class RemoteWebpackRequireRuntimeModule extends webpack.RuntimeModule {\n appName: string;\n\n constructor(appName: string) {\n super('remote-webpack-require');\n this.appName = appName;\n }\n\n generate(): null | string {\n return `globalThis.__remote_webpack_require__ = globalThis.__remote_webpack_require__ || {}; globalThis.__remote_webpack_require__[\"${this.appName}\"] = __webpack_require__;`;\n }\n };\n}\n","import type { Compiler, RuntimeModule } from 'webpack';\nimport { createRemoteWebpackRequireRuntimeModule } from './remote-webpack-require-runtime-module';\n\nexport class RemoteWebpackRequirePlugin {\n appName: string;\n\n constructor(appName: string) {\n this.appName = appName;\n }\n\n apply(compiler: Compiler) {\n const RemoteWebpackRequireRuntimeModule =\n createRemoteWebpackRequireRuntimeModule(compiler.webpack);\n\n compiler.hooks.thisCompilation.tap(\n 'RemoteWebpackRequirePlugin',\n (compilation) => {\n compilation.hooks.runtimeRequirementInTree\n .for('__webpack_require__')\n .tap('RemoteWebpackRequirePlugin', (chunk) => {\n compilation.addRuntimeModule(\n chunk,\n new RemoteWebpackRequireRuntimeModule(\n this.appName,\n ) as unknown as RuntimeModule,\n );\n });\n },\n );\n }\n}\n","export function createModuleIdEmbedRuntimeModule(webpack: {\n RuntimeModule: new (name: string, stage?: number) => object;\n}) {\n return class ModuleIdEmbedRuntimeModule extends webpack.RuntimeModule {\n appName: string;\n moduleMap: Record<string | number, unknown>;\n\n constructor(appName: string, moduleMap: Record<string | number, unknown>) {\n super('remote-webpack-module-id-embed');\n this.appName = appName;\n this.moduleMap = moduleMap;\n }\n\n generate(): null | string {\n return `globalThis.__remote_webpack_module_map__ = globalThis.__remote_webpack_module_map__ || {}; globalThis.__remote_webpack_module_map__[\"${this.appName}\"] = ${JSON.stringify(this.moduleMap)};`;\n }\n };\n}\n","import type { NormalModule, Compiler, RuntimeModule } from 'webpack';\nimport { createModuleIdEmbedRuntimeModule } from './module-id-embed-runtime-module';\n\nexport class ModuleIdEmbedPlugin {\n appName: string;\n\n constructor(appName: string) {\n this.appName = appName;\n }\n\n apply(compiler: Compiler) {\n const ModuleIdEmbedRuntimeModule = createModuleIdEmbedRuntimeModule(\n compiler.webpack,\n );\n\n compiler.hooks.thisCompilation.tap('ModuleIdEmbedPlugin', (compilation) => {\n const moduleMap = {} as Record<string, string | number>;\n\n compilation.hooks.runtimeRequirementInTree\n .for(compiler.webpack.RuntimeGlobals.require)\n .tap('ModuleIdEmbedPlugin', (chunk, set) => {\n for (const [key, entry] of compilation.entrypoints) {\n for (const entryChunk of entry.chunks) {\n if (key.includes('nextjs-pages-remote')) {\n for (const mod of compilation.chunkGraph.getChunkModulesIterable(\n entryChunk,\n )) {\n const id = compilation.chunkGraph.getModuleId(mod);\n const normalModule = mod as NormalModule;\n if (id) {\n moduleMap[normalModule.resource || normalModule.request] =\n id;\n }\n }\n }\n }\n }\n for (const mod of compilation.modules) {\n const id = compilation.chunkGraph.getModuleId(mod);\n if (id && mod.layer?.endsWith('browser')) {\n const normalModule = mod as NormalModule;\n moduleMap[normalModule.resource || normalModule.request] = id;\n }\n }\n\n if (Object.keys(moduleMap).length > 0) {\n compilation.addRuntimeModule(\n chunk,\n new ModuleIdEmbedRuntimeModule(\n this.appName,\n moduleMap,\n ) as unknown as RuntimeModule,\n );\n\n set.add(compiler.webpack.RuntimeGlobals.require);\n }\n });\n });\n }\n}\n","import type { Compiler } from 'webpack';\n\nexport class ConditionalExecPlugin {\n apply(compiler: Compiler) {\n const { Compilation, sources } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap(\n 'ConditionalExecPlugin',\n (compilation) => {\n compilation.hooks.processAssets.tap(\n {\n name: 'ConditionalExecPlugin',\n stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,\n },\n (assets) => {\n for (const [name, source] of Object.entries(assets)) {\n if (name.endsWith('.js')) {\n const patchedSource = source\n .source()\n .toString()\n .replace(\n `var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))`,\n `var __webpack_exec__ = (moduleId) => { if (globalThis.__DISABLE_WEBPACK_EXEC__) return; return __webpack_require__(__webpack_require__.s = moduleId); }`,\n );\n compilation.updateAsset(\n name,\n new sources.RawSource(patchedSource),\n );\n }\n }\n },\n );\n },\n );\n }\n}\n","import type { Compiler } from 'webpack';\n\n// This plugin patches the webpack require function to support loading remote components in Next.js\nexport class PatchRequirePlugin {\n apply(compiler: Compiler) {\n const { sources } = compiler.webpack;\n\n compiler.hooks.thisCompilation.tap('PatchRequirePlugin', (compilation) => {\n compilation.mainTemplate.hooks.requireExtensions.tap(\n 'PatchRequirePlugin',\n (source) => {\n return new sources.ConcatSource(\n source,\n `const __webpack_require_orig__ = __webpack_require__;\nconst REMOTE_RE = /\\\\[(?<bundle>[a-zA-Z0-9-_]+)\\\\] (?<id>.*)/;\n__webpack_require__ = function __remote_webpack_require__(remoteId) {\n const match = REMOTE_RE.exec(remoteId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_orig__(remoteId);\n }\n if (typeof self.__remote_webpack_require__?.[bundle] !== 'function') {\n throw new Error(\\`Remote component loading error: \"\\${bundle}\"\\`);\n }\n return self.__remote_webpack_require__[bundle](self.__remote_webpack_require__[bundle].type === 'turbopack' ? remoteId : id);\n};\nObject.assign(__webpack_require__, __webpack_require_orig__);\nconst __webpack_require_l__ = __webpack_require__.l;\n__webpack_require__.l = function __remote_webpack_require_l__(url, done, key, chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_l__(url, done, key, chunkId);\n }\n return done();\n};\nconst __webpack_require_o__ = __webpack_require__.o;\n__webpack_require__.o = function __remote_webpack_require_o__(installedChunks, chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_o__(installedChunks, chunkId);\n }\n return installedChunks[chunkId] = 0;\n};\nconst __webpack_require_e__ = __webpack_require__.e;\n__webpack_require__.e = function __remote_webpack_require_e__(chunkId) {\n const match = REMOTE_RE.exec(chunkId);\n const bundle = match?.groups?.bundle;\n const id = match?.groups?.id;\n if (!(id && bundle)) {\n return __webpack_require_e__(chunkId);\n }\n return Promise.resolve([]);\n};`,\n )\n .source()\n .toString();\n },\n );\n });\n }\n}\n"],"mappings":"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","names":["join","join"]}
|
|
@@ -66,7 +66,7 @@ function RemoteComponentClient({
|
|
|
66
66
|
setShadowRoot(shadowRootElement);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
}, [name, isolate, shadowRoot]);
|
|
69
|
+
}, [name, isolate, shadowRoot, links, url]);
|
|
70
70
|
(0, import_react.useEffect)(() => {
|
|
71
71
|
let mounted = true;
|
|
72
72
|
if (!component && (isolate === false || shadowRoot)) {
|
|
@@ -120,7 +120,7 @@ function RemoteComponentClient({
|
|
|
120
120
|
"link",
|
|
121
121
|
{
|
|
122
122
|
as: link.as,
|
|
123
|
-
href: link.href,
|
|
123
|
+
href: new URL(link.href, url || location.origin).href,
|
|
124
124
|
rel: link.rel
|
|
125
125
|
},
|
|
126
126
|
`${link.href}_${link.rel}`
|
|
@@ -153,15 +153,6 @@ function RemoteComponentClient({
|
|
|
153
153
|
}) }),
|
|
154
154
|
linksToRender,
|
|
155
155
|
componentToRender,
|
|
156
|
-
links.map((link) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
157
|
-
"link",
|
|
158
|
-
{
|
|
159
|
-
as: link.as,
|
|
160
|
-
href: link.href,
|
|
161
|
-
rel: link.rel
|
|
162
|
-
},
|
|
163
|
-
`${link.href}_${link.rel}`
|
|
164
|
-
)),
|
|
165
156
|
data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("script", { id: `${name}_rsc`, children: data.join("\n") }) : null,
|
|
166
157
|
nextData ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
167
158
|
"script",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/next/host/app-client.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, useLayoutEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { shared } from '@remote-component/shared/host';\nimport {\n loadRemoteComponent,\n DEFAULT_ROUTE,\n RUNTIME_WEBPACK,\n} from '../../shared/client/remote-component';\nimport type { RemoteComponentProps } from '../../shared/client/remote-component';\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 children: React.ReactNode;\n };\n }\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 url,\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 children,\n}: RemoteComponentProps) {\n const [component, setComponent] = useState<React.ReactNode | Error>(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 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 const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null);\n\n useLayoutEffect(() => {\n if (isolate !== false && typeof document !== 'undefined' && !shadowRoot) {\n let shadowRootElement: ShadowRoot | null = null;\n const element = document.getElementById(`shadowroot_${name}`);\n shadowRootElement = element?.shadowRoot ?? 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 element.attachShadow({ mode: 'open' });\n shadowRootElement = element.shadowRoot;\n }\n\n if (shadowRootElement) {\n // remove all nodes from the shadow root except links\n shadowRootElement.querySelectorAll('*:not(link)').forEach((node) => {\n node.remove();\n });\n setShadowRoot(shadowRootElement);\n }\n }\n }, [name, isolate, shadowRoot]);\n\n useEffect(() => {\n let mounted = true;\n\n // if we have a component, we don't need to load it again\n if (!component && (isolate === false || shadowRoot)) {\n loadRemoteComponent({\n url: new URL(url, location.origin),\n name,\n bundle,\n route,\n runtime,\n data,\n nextData,\n scripts,\n shared,\n remoteShared,\n container: shadowRoot,\n })\n .then((result) => {\n if (mounted) {\n if (result.error) {\n setComponent(result.error);\n } else {\n setComponent(result.component);\n }\n }\n })\n .catch((error: Error) => {\n if (mounted) {\n setComponent(error);\n }\n });\n }\n\n return () => {\n mounted = false;\n };\n }, [\n url,\n component,\n name,\n bundle,\n route,\n runtime,\n scripts,\n data,\n nextData,\n remoteShared,\n children,\n links,\n isolate,\n shadowRoot,\n ]);\n\n let componentToRender = (\n <>{shouldUseChildren ? children : (component as React.ReactNode)}</>\n );\n let linksToRender: React.ReactNode[] | null = links.map((link) => (\n <link\n as={link.as as string}\n href={link.href as string}\n key={`${link.href as string}_${link.rel}`}\n rel={link.rel as string}\n />\n ));\n\n if (isolate !== false) {\n componentToRender = (\n <div id={`shadowroot_${name}`}>\n {typeof document === 'undefined' ? (\n // eslint-disable-next-line react/no-unknown-property\n <template shadowrootmode=\"open\">\n {linksToRender}\n {componentToRender}\n </template>\n ) : null}\n {shadowRoot\n ? createPortal(\n shadowRoot.querySelectorAll('link').length !== links.length ? (\n <>\n {linksToRender}\n {componentToRender}\n </>\n ) : (\n componentToRender\n ),\n shadowRoot,\n )\n : null}\n </div>\n );\n linksToRender = null;\n }\n\n return (\n <>\n <script data-remote-component type=\"application/json\">\n {JSON.stringify({\n name,\n bundle,\n route,\n runtime,\n })}\n </script>\n {linksToRender}\n {componentToRender}\n {
|
|
1
|
+
{"version":3,"sources":["../../../src/next/host/app-client.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, useLayoutEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { shared } from '@remote-component/shared/host';\nimport {\n loadRemoteComponent,\n DEFAULT_ROUTE,\n RUNTIME_WEBPACK,\n} from '../../shared/client/remote-component';\nimport type { RemoteComponentProps } from '../../shared/client/remote-component';\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 children: React.ReactNode;\n };\n }\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 url,\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 children,\n}: RemoteComponentProps) {\n const [component, setComponent] = useState<React.ReactNode | Error>(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 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 const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null);\n\n useLayoutEffect(() => {\n if (isolate !== false && typeof document !== 'undefined' && !shadowRoot) {\n let shadowRootElement: ShadowRoot | null = null;\n const element = document.getElementById(`shadowroot_${name}`);\n shadowRootElement = element?.shadowRoot ?? 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 element.attachShadow({ mode: 'open' });\n shadowRootElement = element.shadowRoot;\n }\n\n if (shadowRootElement) {\n // remove all nodes from the shadow root except links\n shadowRootElement.querySelectorAll('*:not(link)').forEach((node) => {\n node.remove();\n });\n setShadowRoot(shadowRootElement);\n }\n }\n }, [name, isolate, shadowRoot, links, url]);\n\n useEffect(() => {\n let mounted = true;\n\n // if we have a component, we don't need to load it again\n if (!component && (isolate === false || shadowRoot)) {\n loadRemoteComponent({\n url: new URL(url, location.origin),\n name,\n bundle,\n route,\n runtime,\n data,\n nextData,\n scripts,\n shared,\n remoteShared,\n container: shadowRoot,\n })\n .then((result) => {\n if (mounted) {\n if (result.error) {\n setComponent(result.error);\n } else {\n setComponent(result.component);\n }\n }\n })\n .catch((error: Error) => {\n if (mounted) {\n setComponent(error);\n }\n });\n }\n\n return () => {\n mounted = false;\n };\n }, [\n url,\n component,\n name,\n bundle,\n route,\n runtime,\n scripts,\n data,\n nextData,\n remoteShared,\n children,\n links,\n isolate,\n shadowRoot,\n ]);\n\n let componentToRender = (\n <>{shouldUseChildren ? children : (component as React.ReactNode)}</>\n );\n let linksToRender: React.ReactNode[] | null = links.map((link) => (\n <link\n as={link.as as string}\n href={new URL(link.href as string, url || location.origin).href}\n key={`${link.href as string}_${link.rel}`}\n rel={link.rel as string}\n />\n ));\n\n if (isolate !== false) {\n componentToRender = (\n <div id={`shadowroot_${name}`}>\n {typeof document === 'undefined' ? (\n // eslint-disable-next-line react/no-unknown-property\n <template shadowrootmode=\"open\">\n {linksToRender}\n {componentToRender}\n </template>\n ) : null}\n {shadowRoot\n ? createPortal(\n shadowRoot.querySelectorAll('link').length !== links.length ? (\n <>\n {linksToRender}\n {componentToRender}\n </>\n ) : (\n componentToRender\n ),\n shadowRoot,\n )\n : null}\n </div>\n );\n linksToRender = null;\n }\n\n return (\n <>\n <script data-remote-component type=\"application/json\">\n {JSON.stringify({\n name,\n bundle,\n route,\n runtime,\n })}\n </script>\n {linksToRender}\n {componentToRender}\n {data.length > 0 ? (\n <script id={`${name}_rsc`}>{data.join('\\n')}</script>\n ) : null}\n {nextData ? (\n <script\n id={`${bundle}_${route.replace(/\\//g, '_')}${name}_next_data`}\n type=\"application/json\"\n >\n {JSON.stringify(nextData)}\n </script>\n ) : null}\n </>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -47,7 +47,7 @@ function RemoteComponentClient({
|
|
|
47
47
|
setShadowRoot(shadowRootElement);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
}, [name, isolate, shadowRoot]);
|
|
50
|
+
}, [name, isolate, shadowRoot, links, url]);
|
|
51
51
|
useEffect(() => {
|
|
52
52
|
let mounted = true;
|
|
53
53
|
if (!component && (isolate === false || shadowRoot)) {
|
|
@@ -101,7 +101,7 @@ function RemoteComponentClient({
|
|
|
101
101
|
"link",
|
|
102
102
|
{
|
|
103
103
|
as: link.as,
|
|
104
|
-
href: link.href,
|
|
104
|
+
href: new URL(link.href, url || location.origin).href,
|
|
105
105
|
rel: link.rel
|
|
106
106
|
},
|
|
107
107
|
`${link.href}_${link.rel}`
|
|
@@ -134,15 +134,6 @@ function RemoteComponentClient({
|
|
|
134
134
|
}) }),
|
|
135
135
|
linksToRender,
|
|
136
136
|
componentToRender,
|
|
137
|
-
links.map((link) => /* @__PURE__ */ jsx(
|
|
138
|
-
"link",
|
|
139
|
-
{
|
|
140
|
-
as: link.as,
|
|
141
|
-
href: link.href,
|
|
142
|
-
rel: link.rel
|
|
143
|
-
},
|
|
144
|
-
`${link.href}_${link.rel}`
|
|
145
|
-
)),
|
|
146
137
|
data.length > 0 ? /* @__PURE__ */ jsx("script", { id: `${name}_rsc`, children: data.join("\n") }) : null,
|
|
147
138
|
nextData ? /* @__PURE__ */ jsx(
|
|
148
139
|
"script",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/next/host/app-client.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, useLayoutEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { shared } from '@remote-component/shared/host';\nimport {\n loadRemoteComponent,\n DEFAULT_ROUTE,\n RUNTIME_WEBPACK,\n} from '../../shared/client/remote-component';\nimport type { RemoteComponentProps } from '../../shared/client/remote-component';\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 children: React.ReactNode;\n };\n }\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 url,\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 children,\n}: RemoteComponentProps) {\n const [component, setComponent] = useState<React.ReactNode | Error>(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 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 const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null);\n\n useLayoutEffect(() => {\n if (isolate !== false && typeof document !== 'undefined' && !shadowRoot) {\n let shadowRootElement: ShadowRoot | null = null;\n const element = document.getElementById(`shadowroot_${name}`);\n shadowRootElement = element?.shadowRoot ?? 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 element.attachShadow({ mode: 'open' });\n shadowRootElement = element.shadowRoot;\n }\n\n if (shadowRootElement) {\n // remove all nodes from the shadow root except links\n shadowRootElement.querySelectorAll('*:not(link)').forEach((node) => {\n node.remove();\n });\n setShadowRoot(shadowRootElement);\n }\n }\n }, [name, isolate, shadowRoot]);\n\n useEffect(() => {\n let mounted = true;\n\n // if we have a component, we don't need to load it again\n if (!component && (isolate === false || shadowRoot)) {\n loadRemoteComponent({\n url: new URL(url, location.origin),\n name,\n bundle,\n route,\n runtime,\n data,\n nextData,\n scripts,\n shared,\n remoteShared,\n container: shadowRoot,\n })\n .then((result) => {\n if (mounted) {\n if (result.error) {\n setComponent(result.error);\n } else {\n setComponent(result.component);\n }\n }\n })\n .catch((error: Error) => {\n if (mounted) {\n setComponent(error);\n }\n });\n }\n\n return () => {\n mounted = false;\n };\n }, [\n url,\n component,\n name,\n bundle,\n route,\n runtime,\n scripts,\n data,\n nextData,\n remoteShared,\n children,\n links,\n isolate,\n shadowRoot,\n ]);\n\n let componentToRender = (\n <>{shouldUseChildren ? children : (component as React.ReactNode)}</>\n );\n let linksToRender: React.ReactNode[] | null = links.map((link) => (\n <link\n as={link.as as string}\n href={link.href as string}\n key={`${link.href as string}_${link.rel}`}\n rel={link.rel as string}\n />\n ));\n\n if (isolate !== false) {\n componentToRender = (\n <div id={`shadowroot_${name}`}>\n {typeof document === 'undefined' ? (\n // eslint-disable-next-line react/no-unknown-property\n <template shadowrootmode=\"open\">\n {linksToRender}\n {componentToRender}\n </template>\n ) : null}\n {shadowRoot\n ? createPortal(\n shadowRoot.querySelectorAll('link').length !== links.length ? (\n <>\n {linksToRender}\n {componentToRender}\n </>\n ) : (\n componentToRender\n ),\n shadowRoot,\n )\n : null}\n </div>\n );\n linksToRender = null;\n }\n\n return (\n <>\n <script data-remote-component type=\"application/json\">\n {JSON.stringify({\n name,\n bundle,\n route,\n runtime,\n })}\n </script>\n {linksToRender}\n {componentToRender}\n {
|
|
1
|
+
{"version":3,"sources":["../../../src/next/host/app-client.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState, useLayoutEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { shared } from '@remote-component/shared/host';\nimport {\n loadRemoteComponent,\n DEFAULT_ROUTE,\n RUNTIME_WEBPACK,\n} from '../../shared/client/remote-component';\nimport type { RemoteComponentProps } from '../../shared/client/remote-component';\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 children: React.ReactNode;\n };\n }\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 url,\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 children,\n}: RemoteComponentProps) {\n const [component, setComponent] = useState<React.ReactNode | Error>(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 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 const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null);\n\n useLayoutEffect(() => {\n if (isolate !== false && typeof document !== 'undefined' && !shadowRoot) {\n let shadowRootElement: ShadowRoot | null = null;\n const element = document.getElementById(`shadowroot_${name}`);\n shadowRootElement = element?.shadowRoot ?? 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 element.attachShadow({ mode: 'open' });\n shadowRootElement = element.shadowRoot;\n }\n\n if (shadowRootElement) {\n // remove all nodes from the shadow root except links\n shadowRootElement.querySelectorAll('*:not(link)').forEach((node) => {\n node.remove();\n });\n setShadowRoot(shadowRootElement);\n }\n }\n }, [name, isolate, shadowRoot, links, url]);\n\n useEffect(() => {\n let mounted = true;\n\n // if we have a component, we don't need to load it again\n if (!component && (isolate === false || shadowRoot)) {\n loadRemoteComponent({\n url: new URL(url, location.origin),\n name,\n bundle,\n route,\n runtime,\n data,\n nextData,\n scripts,\n shared,\n remoteShared,\n container: shadowRoot,\n })\n .then((result) => {\n if (mounted) {\n if (result.error) {\n setComponent(result.error);\n } else {\n setComponent(result.component);\n }\n }\n })\n .catch((error: Error) => {\n if (mounted) {\n setComponent(error);\n }\n });\n }\n\n return () => {\n mounted = false;\n };\n }, [\n url,\n component,\n name,\n bundle,\n route,\n runtime,\n scripts,\n data,\n nextData,\n remoteShared,\n children,\n links,\n isolate,\n shadowRoot,\n ]);\n\n let componentToRender = (\n <>{shouldUseChildren ? children : (component as React.ReactNode)}</>\n );\n let linksToRender: React.ReactNode[] | null = links.map((link) => (\n <link\n as={link.as as string}\n href={new URL(link.href as string, url || location.origin).href}\n key={`${link.href as string}_${link.rel}`}\n rel={link.rel as string}\n />\n ));\n\n if (isolate !== false) {\n componentToRender = (\n <div id={`shadowroot_${name}`}>\n {typeof document === 'undefined' ? (\n // eslint-disable-next-line react/no-unknown-property\n <template shadowrootmode=\"open\">\n {linksToRender}\n {componentToRender}\n </template>\n ) : null}\n {shadowRoot\n ? createPortal(\n shadowRoot.querySelectorAll('link').length !== links.length ? (\n <>\n {linksToRender}\n {componentToRender}\n </>\n ) : (\n componentToRender\n ),\n shadowRoot,\n )\n : null}\n </div>\n );\n linksToRender = null;\n }\n\n return (\n <>\n <script data-remote-component type=\"application/json\">\n {JSON.stringify({\n name,\n bundle,\n route,\n runtime,\n })}\n </script>\n {linksToRender}\n {componentToRender}\n {data.length > 0 ? (\n <script id={`${name}_rsc`}>{data.join('\\n')}</script>\n ) : null}\n {nextData ? (\n <script\n id={`${bundle}_${route.replace(/\\//g, '_')}${name}_next_data`}\n type=\"application/json\"\n >\n {JSON.stringify(nextData)}\n </script>\n ) : null}\n </>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -38,7 +38,8 @@ async function RemoteComponent({
|
|
|
38
38
|
hydrationData,
|
|
39
39
|
nextData,
|
|
40
40
|
component,
|
|
41
|
-
remoteShared
|
|
41
|
+
remoteShared,
|
|
42
|
+
url
|
|
42
43
|
} = await (0, import_fetch_remote_component.fetchRemoteComponent)(src, headerList, true);
|
|
43
44
|
const name = metadata.id.replace(/_ssr$/, "");
|
|
44
45
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -54,7 +55,7 @@ async function RemoteComponent({
|
|
|
54
55
|
route: metadata.route,
|
|
55
56
|
runtime: metadata.runtime,
|
|
56
57
|
scripts,
|
|
57
|
-
url:
|
|
58
|
+
url: url.href,
|
|
58
59
|
children: component
|
|
59
60
|
}
|
|
60
61
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/next/host/app-server.tsx"],"sourcesContent":["import { headers } from 'next/headers';\nimport { fetchRemoteComponent } from '../../shared/ssr/fetch-remote-component';\nimport { RemoteComponentClient } from './app-client';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * RemoteComponent is a Next.js component that fetches and renders a remote component.\n * It supports SSR and can isolate the remote component in a shadow DOM.\n *\n * @param src - The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param isolate - Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation.\n * @returns A React component that renders the remote component.\n *\n * @example\n *\n * Use the `<RemoteComponent>` in your Next.js App Router application to consume a remote component from a remote application:\n *\n * ```tsx\n * import { RemoteComponent } from 'remote-components/next/host';\n *\n * export default function MyPage() {\n * return (\n * <>\n * <h1>Welcome to My Page</h1>\n * <p>This page consumes a remote component from another application.</p>\n * <RemoteComponent src=\"/nextjs-app-remote/components/header\" />\n * </>\n * );\n * }\n * ```\n */\nexport async function RemoteComponent({\n src,\n isolate,\n}: {\n src: string | URL;\n isolate?: boolean;\n}) {\n // get the headers from the request\n const headerList = await headers();\n\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n } = await fetchRemoteComponent(src, headerList, true);\n\n // pass all remote component data to the SSR/client layer\n // render remote component static HTML as children\n // remote _ssr suffix from remote component id\n const name = metadata.id.replace(/_ssr$/, '');\n return (\n <RemoteComponentClient\n bundle={metadata.bundle || (CURRENT_ZONE ?? name)}\n data={hydrationData}\n isolate={isolate}\n links={links}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n route={metadata.route}\n runtime={metadata.runtime}\n scripts={scripts}\n url={
|
|
1
|
+
{"version":3,"sources":["../../../src/next/host/app-server.tsx"],"sourcesContent":["import { headers } from 'next/headers';\nimport { fetchRemoteComponent } from '../../shared/ssr/fetch-remote-component';\nimport { RemoteComponentClient } from './app-client';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * RemoteComponent is a Next.js component that fetches and renders a remote component.\n * It supports SSR and can isolate the remote component in a shadow DOM.\n *\n * @param src - The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param isolate - Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation.\n * @returns A React component that renders the remote component.\n *\n * @example\n *\n * Use the `<RemoteComponent>` in your Next.js App Router application to consume a remote component from a remote application:\n *\n * ```tsx\n * import { RemoteComponent } from 'remote-components/next/host';\n *\n * export default function MyPage() {\n * return (\n * <>\n * <h1>Welcome to My Page</h1>\n * <p>This page consumes a remote component from another application.</p>\n * <RemoteComponent src=\"/nextjs-app-remote/components/header\" />\n * </>\n * );\n * }\n * ```\n */\nexport async function RemoteComponent({\n src,\n isolate,\n}: {\n src: string | URL;\n isolate?: boolean;\n}) {\n // get the headers from the request\n const headerList = await headers();\n\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n url,\n } = await fetchRemoteComponent(src, headerList, true);\n\n // pass all remote component data to the SSR/client layer\n // render remote component static HTML as children\n // remote _ssr suffix from remote component id\n const name = metadata.id.replace(/_ssr$/, '');\n return (\n <RemoteComponentClient\n bundle={metadata.bundle || (CURRENT_ZONE ?? name)}\n data={hydrationData}\n isolate={isolate}\n links={links}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n route={metadata.route}\n runtime={metadata.runtime}\n scripts={scripts}\n url={url.href}\n >\n {component}\n </RemoteComponentClient>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0DI;AA1DJ,qBAAwB;AACxB,oCAAqC;AACrC,wBAAsC;AAEtC,MAAM,eAAe,QAAQ,IAAI;AA4BjC,eAAsB,gBAAgB;AAAA,EACpC;AAAA,EACA;AACF,GAGG;AAED,QAAM,aAAa,UAAM,wBAAQ;AAEjC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,UAAM,oDAAqB,KAAK,YAAY,IAAI;AAKpD,QAAM,OAAO,SAAS,GAAG,QAAQ,SAAS,EAAE;AAC5C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ,SAAS,WAAW,gBAAgB;AAAA,MAC5C,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,KAAK,IAAI;AAAA,MAER;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -15,7 +15,8 @@ async function RemoteComponent({
|
|
|
15
15
|
hydrationData,
|
|
16
16
|
nextData,
|
|
17
17
|
component,
|
|
18
|
-
remoteShared
|
|
18
|
+
remoteShared,
|
|
19
|
+
url
|
|
19
20
|
} = await fetchRemoteComponent(src, headerList, true);
|
|
20
21
|
const name = metadata.id.replace(/_ssr$/, "");
|
|
21
22
|
return /* @__PURE__ */ jsx(
|
|
@@ -31,7 +32,7 @@ async function RemoteComponent({
|
|
|
31
32
|
route: metadata.route,
|
|
32
33
|
runtime: metadata.runtime,
|
|
33
34
|
scripts,
|
|
34
|
-
url:
|
|
35
|
+
url: url.href,
|
|
35
36
|
children: component
|
|
36
37
|
}
|
|
37
38
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/next/host/app-server.tsx"],"sourcesContent":["import { headers } from 'next/headers';\nimport { fetchRemoteComponent } from '../../shared/ssr/fetch-remote-component';\nimport { RemoteComponentClient } from './app-client';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * RemoteComponent is a Next.js component that fetches and renders a remote component.\n * It supports SSR and can isolate the remote component in a shadow DOM.\n *\n * @param src - The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param isolate - Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation.\n * @returns A React component that renders the remote component.\n *\n * @example\n *\n * Use the `<RemoteComponent>` in your Next.js App Router application to consume a remote component from a remote application:\n *\n * ```tsx\n * import { RemoteComponent } from 'remote-components/next/host';\n *\n * export default function MyPage() {\n * return (\n * <>\n * <h1>Welcome to My Page</h1>\n * <p>This page consumes a remote component from another application.</p>\n * <RemoteComponent src=\"/nextjs-app-remote/components/header\" />\n * </>\n * );\n * }\n * ```\n */\nexport async function RemoteComponent({\n src,\n isolate,\n}: {\n src: string | URL;\n isolate?: boolean;\n}) {\n // get the headers from the request\n const headerList = await headers();\n\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n } = await fetchRemoteComponent(src, headerList, true);\n\n // pass all remote component data to the SSR/client layer\n // render remote component static HTML as children\n // remote _ssr suffix from remote component id\n const name = metadata.id.replace(/_ssr$/, '');\n return (\n <RemoteComponentClient\n bundle={metadata.bundle || (CURRENT_ZONE ?? name)}\n data={hydrationData}\n isolate={isolate}\n links={links}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n route={metadata.route}\n runtime={metadata.runtime}\n scripts={scripts}\n url={
|
|
1
|
+
{"version":3,"sources":["../../../src/next/host/app-server.tsx"],"sourcesContent":["import { headers } from 'next/headers';\nimport { fetchRemoteComponent } from '../../shared/ssr/fetch-remote-component';\nimport { RemoteComponentClient } from './app-client';\n\nconst CURRENT_ZONE = process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;\n\n/**\n * RemoteComponent is a Next.js component that fetches and renders a remote component.\n * It supports SSR and can isolate the remote component in a shadow DOM.\n *\n * @param src - The source URL of the remote component. When using Vercel Microfrontends, you can use relative paths, e.g. `/nextjs-app-remote/components/header`. Absolute URLs are also supported.\n * @param isolate - Whether to isolate the remote component using a Shadow DOM wrapper. Defaults to `true`. Use `false` explicitly to disable isolation.\n * @returns A React component that renders the remote component.\n *\n * @example\n *\n * Use the `<RemoteComponent>` in your Next.js App Router application to consume a remote component from a remote application:\n *\n * ```tsx\n * import { RemoteComponent } from 'remote-components/next/host';\n *\n * export default function MyPage() {\n * return (\n * <>\n * <h1>Welcome to My Page</h1>\n * <p>This page consumes a remote component from another application.</p>\n * <RemoteComponent src=\"/nextjs-app-remote/components/header\" />\n * </>\n * );\n * }\n * ```\n */\nexport async function RemoteComponent({\n src,\n isolate,\n}: {\n src: string | URL;\n isolate?: boolean;\n}) {\n // get the headers from the request\n const headerList = await headers();\n\n const {\n metadata,\n scripts,\n links,\n hydrationData,\n nextData,\n component,\n remoteShared,\n url,\n } = await fetchRemoteComponent(src, headerList, true);\n\n // pass all remote component data to the SSR/client layer\n // render remote component static HTML as children\n // remote _ssr suffix from remote component id\n const name = metadata.id.replace(/_ssr$/, '');\n return (\n <RemoteComponentClient\n bundle={metadata.bundle || (CURRENT_ZONE ?? name)}\n data={hydrationData}\n isolate={isolate}\n links={links}\n name={name}\n nextData={nextData}\n remoteShared={remoteShared}\n route={metadata.route}\n runtime={metadata.runtime}\n scripts={scripts}\n url={url.href}\n >\n {component}\n </RemoteComponentClient>\n );\n}\n"],"mappings":"AA0DI;AA1DJ,SAAS,eAAe;AACxB,SAAS,4BAA4B;AACrC,SAAS,6BAA6B;AAEtC,MAAM,eAAe,QAAQ,IAAI;AA4BjC,eAAsB,gBAAgB;AAAA,EACpC;AAAA,EACA;AACF,GAGG;AAED,QAAM,aAAa,MAAM,QAAQ;AAEjC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,MAAM,qBAAqB,KAAK,YAAY,IAAI;AAKpD,QAAM,OAAO,SAAS,GAAG,QAAQ,SAAS,EAAE;AAC5C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ,SAAS,WAAW,gBAAgB;AAAA,MAC5C,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,KAAK,IAAI;AAAA,MAER;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -37,7 +37,14 @@ var import_work_async_storage = require("next/dist/server/app-render/work-async-
|
|
|
37
37
|
const SERVER_ACTION_MANIFESTS_SINGLETON = Symbol.for(
|
|
38
38
|
"next.server.action-manifests"
|
|
39
39
|
);
|
|
40
|
-
const PROJECT_ID = process.env.REMOTE_COMPONENTS_PROJECT_ID;
|
|
40
|
+
const PROJECT_ID = process.env.REMOTE_COMPONENTS_PROJECT_ID || process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION || process.env.VERCEL_PROJECT_ID;
|
|
41
|
+
async function tryImport(importer) {
|
|
42
|
+
try {
|
|
43
|
+
return await importer();
|
|
44
|
+
} catch {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
41
48
|
function RemoteComponentData({ name, data }) {
|
|
42
49
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("script", { id: `${name}_rsc`, children: data.map(
|
|
43
50
|
(chunk, i) => (
|
|
@@ -79,20 +86,37 @@ async function RemoteComponent({
|
|
|
79
86
|
// prepend the current zone to the chunks to handle remote component chunk loading in Webpack
|
|
80
87
|
// this is required to avoid loading the wrong chunk in the host application
|
|
81
88
|
chunks: value.chunks.map((chunk) => `[${PROJECT_ID}] ${chunk}`)
|
|
82
|
-
// async: true,
|
|
83
89
|
}
|
|
84
90
|
];
|
|
85
91
|
})
|
|
86
92
|
);
|
|
87
|
-
const [
|
|
93
|
+
const [
|
|
94
|
+
{ renderToReadableStream: nextRenderToReadableStream },
|
|
95
|
+
{ renderToReadableStream: legacyRenderToReadableStream },
|
|
96
|
+
{ RemoteComponentSSR }
|
|
97
|
+
] = await Promise.all(
|
|
88
98
|
process.env.TURBOPACK ? [
|
|
89
|
-
|
|
99
|
+
tryImport(
|
|
100
|
+
() => import("react-server-dom-turbopack/server")
|
|
101
|
+
),
|
|
102
|
+
tryImport(
|
|
103
|
+
() => import("react-server-dom-turbopack/server.edge")
|
|
104
|
+
),
|
|
90
105
|
import("./render-client-turbopack")
|
|
91
106
|
] : [
|
|
92
|
-
|
|
107
|
+
tryImport(
|
|
108
|
+
() => import("react-server-dom-webpack/server")
|
|
109
|
+
),
|
|
110
|
+
tryImport(
|
|
111
|
+
() => import("react-server-dom-webpack/server.edge")
|
|
112
|
+
),
|
|
93
113
|
import("./render-client-webpack")
|
|
94
114
|
]
|
|
95
115
|
);
|
|
116
|
+
const renderToReadableStream = nextRenderToReadableStream ?? legacyRenderToReadableStream;
|
|
117
|
+
if (typeof renderToReadableStream !== "function") {
|
|
118
|
+
throw new Error("No valid renderToReadableStream function found");
|
|
119
|
+
}
|
|
96
120
|
const stream = renderToReadableStream(children, clientModules);
|
|
97
121
|
const data = [];
|
|
98
122
|
const decoder = new TextDecoder();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/next/remote/render-server.tsx"],"sourcesContent":["import { headers } from 'next/headers';\nimport { workAsyncStorage } from 'next/dist/server/app-render/work-async-storage.external';\nimport type { Manifest } from './types';\n\n// internal Next.js symbol to access the manifest which is stored in the global scope\nconst SERVER_ACTION_MANIFESTS_SINGLETON = Symbol.for(\n 'next.server.action-manifests',\n);\n\nconst PROJECT_ID
|
|
1
|
+
{"version":3,"sources":["../../../src/next/remote/render-server.tsx"],"sourcesContent":["import { headers } from 'next/headers';\nimport { workAsyncStorage } from 'next/dist/server/app-render/work-async-storage.external';\nimport type { Manifest } from './types';\n\n// internal Next.js symbol to access the manifest which is stored in the global scope\nconst SERVER_ACTION_MANIFESTS_SINGLETON = Symbol.for(\n 'next.server.action-manifests',\n);\n\nconst PROJECT_ID =\n process.env.REMOTE_COMPONENTS_PROJECT_ID ||\n process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION ||\n process.env.VERCEL_PROJECT_ID;\n\nasync function tryImport<T>(importer: () => Promise<T>) {\n try {\n return (await importer()) as T;\n } catch {\n return {} as T;\n }\n}\n\n// inject the RSC flight data into the HTML response using <script>\n// the RSC flight data is used to hydrate the remote component on the host\n// this approach is similar to an island architecture on the host\n// the remote component is static HTML until it is hydrated using this RSC flight data\nfunction RemoteComponentData({ name, data }: { name: string; data: string[] }) {\n return (\n <script id={`${name}_rsc`}>\n {data\n .map(\n (chunk, i) =>\n // make the data handling somewhat safe\n `${i === 0 ? `self[\"${name}\"]=self[\"${name}\"]||[];` : ''}self[\"${name}\"].push(${JSON.stringify(\n chunk,\n )});`,\n )\n .join('\\n')}\n </script>\n );\n}\n\n/**\n * RemoteComponent is a Next.js component that exposes a remote component\n * that can be used in a host application.\n *\n * @param name - The name of the remote component. Use a unique name to expose multiple remote components from the same page.\n * @param children - The content of the remote component. This is the content that will be rendered as the remote component.\n * @returns A React component that renders the remote component.\n *\n * @example\n *\n * Use the `<RemoteComponent>` in your Next.js App Router application to expose the children as a remote component:\n *\n * ```tsx\n * import { RemoteComponent } from 'remote-components/next';\n *\n * export default function MyPage() {\n * return (\n * <RemoteComponent>\n * <h1>Hello from the remote component!</h1>\n * <p>This is a remote component that can be used in a host application.</p>\n * </RemoteComponent>\n * );\n * }\n * ```\n */\nexport async function RemoteComponent({\n name = '__vercel_remote_component',\n children,\n}: {\n name?: string;\n children: React.ReactNode;\n}): Promise<React.ReactNode> {\n const headersList = await headers();\n const url = headersList.get('Vercel-Remote-Component-Url');\n const isRemote = url !== null;\n\n if (!isRemote) {\n return children;\n }\n\n // this URL passed by the remote component consumer is only used to know the public address of the remote component\n // it is only used to determine if we need to mutate the client module map for now\n\n const { pathname } = new URL(url);\n // access the internal Next.js work store to get the active page and route\n const { page, route } = workAsyncStorage.getStore() ?? { page: pathname };\n\n // get reference to the manifests from the global scope\n const manifests = (\n globalThis as typeof globalThis & {\n [SERVER_ACTION_MANIFESTS_SINGLETON]: {\n clientReferenceManifestsPerPage?: Record<string, Manifest>;\n };\n }\n )[SERVER_ACTION_MANIFESTS_SINGLETON];\n const manifest = manifests.clientReferenceManifestsPerPage?.[route ?? page];\n\n const self = globalThis as typeof globalThis & {\n [SERVER_ACTION_MANIFESTS_SINGLETON]?: {\n clientReferenceManifestsPerPage?: Record<string, Manifest>;\n };\n __RSC_MANIFEST?: Record<string, unknown>;\n };\n\n // manually handle the internal Next.js manifest\n self.__RSC_MANIFEST = self.__RSC_MANIFEST || {};\n self.__RSC_MANIFEST[page] = self.__RSC_MANIFEST[page] || manifest;\n\n // get the client and SSR module mapping to be able to use client components in the remote component\n let clientModules = manifest?.clientModules ?? {};\n const ssrModuleMapping = { ...manifest?.ssrModuleMapping };\n\n // if the remote component is used in a hosting application, we need to mutate the module map to include the zone\n clientModules = Object.fromEntries(\n Object.entries(clientModules).map(([key, value]) => {\n // append a prefix to each entry in the module map to include the zone of the remote component\n const remoteId = `[${PROJECT_ID}] ${value.id}`;\n ssrModuleMapping[remoteId] = ssrModuleMapping[value.id];\n // override the original id with the new remote id\n return [\n key,\n {\n ...value,\n id: remoteId,\n // prepend the current zone to the chunks to handle remote component chunk loading in Webpack\n // this is required to avoid loading the wrong chunk in the host application\n chunks: value.chunks.map((chunk) => `[${PROJECT_ID}] ${chunk}`),\n },\n ];\n }),\n );\n\n // dynamically import the runtime specific RSC rendering functions and client component\n const [\n { renderToReadableStream: nextRenderToReadableStream },\n { renderToReadableStream: legacyRenderToReadableStream },\n { RemoteComponentSSR },\n ] = await Promise.all(\n process.env.TURBOPACK\n ? [\n tryImport<RSDWServer>(\n () => import('react-server-dom-turbopack/server'),\n ),\n tryImport<RSDWServer>(\n () => import('react-server-dom-turbopack/server.edge'),\n ),\n import('./render-client-turbopack'),\n ]\n : [\n tryImport<RSDWServer>(\n () => import('react-server-dom-webpack/server'),\n ),\n tryImport<RSDWServer>(\n () => import('react-server-dom-webpack/server.edge'),\n ),\n import('./render-client-webpack'),\n ],\n );\n const renderToReadableStream =\n nextRenderToReadableStream ?? legacyRenderToReadableStream;\n\n if (typeof renderToReadableStream !== 'function') {\n throw new Error('No valid renderToReadableStream function found');\n }\n\n // render the wrapped content of this component (children) into an RSC stream\n const stream = renderToReadableStream(children, clientModules);\n\n const data = [];\n const decoder = new TextDecoder();\n\n // convert the stream to an array for safe passing to the client\n for await (const chunk of stream as unknown as AsyncIterable<Uint8Array>) {\n data.push(decoder.decode(chunk));\n }\n\n const runtime = process.env.TURBOPACK ? 'turbopack' : 'webpack';\n const remoteComponentName = `${name}_${route?.replace(/\\//g, '_')}`;\n\n return (\n // wrap the remote component content into a div to know which part of the HTML belongs to the remote component\n <div\n data-bundle={PROJECT_ID}\n data-route={route}\n data-runtime={runtime}\n id={`${remoteComponentName}_ssr`}\n >\n <RemoteComponentSSR\n data={data}\n moduleLoading={manifest?.moduleLoading ?? {}}\n moduleMap={ssrModuleMapping}\n name={remoteComponentName}\n />\n {/* inject RSC flight data as <script> */}\n <RemoteComponentData data={data} name={remoteComponentName} />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BI;AA5BJ,qBAAwB;AACxB,gCAAiC;AAIjC,MAAM,oCAAoC,OAAO;AAAA,EAC/C;AACF;AAEA,MAAM,aACJ,QAAQ,IAAI,gCACZ,QAAQ,IAAI,uCACZ,QAAQ,IAAI;AAEd,eAAe,UAAa,UAA4B;AACtD,MAAI;AACF,WAAQ,MAAM,SAAS;AAAA,EACzB,QAAE;AACA,WAAO,CAAC;AAAA,EACV;AACF;AAMA,SAAS,oBAAoB,EAAE,MAAM,KAAK,GAAqC;AAC7E,SACE,4CAAC,YAAO,IAAI,GAAG,YACZ,eACE;AAAA,IACC,CAAC,OAAO;AAAA;AAAA,MAEN,GAAG,MAAM,IAAI,SAAS,gBAAgB,gBAAgB,WAAW,eAAe,KAAK;AAAA,QACnF;AAAA,MACF;AAAA;AAAA,EACJ,EACC,KAAK,IAAI,GACd;AAEJ;AA2BA,eAAsB,gBAAgB;AAAA,EACpC,OAAO;AAAA,EACP;AACF,GAG6B;AAC3B,QAAM,cAAc,UAAM,wBAAQ;AAClC,QAAM,MAAM,YAAY,IAAI,6BAA6B;AACzD,QAAM,WAAW,QAAQ;AAEzB,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAKA,QAAM,EAAE,SAAS,IAAI,IAAI,IAAI,GAAG;AAEhC,QAAM,EAAE,MAAM,MAAM,IAAI,2CAAiB,SAAS,KAAK,EAAE,MAAM,SAAS;AAGxE,QAAM,YACJ,WAKA,iCAAiC;AACnC,QAAM,WAAW,UAAU,kCAAkC,SAAS,IAAI;AAE1E,QAAM,OAAO;AAQb,OAAK,iBAAiB,KAAK,kBAAkB,CAAC;AAC9C,OAAK,eAAe,IAAI,IAAI,KAAK,eAAe,IAAI,KAAK;AAGzD,MAAI,gBAAgB,UAAU,iBAAiB,CAAC;AAChD,QAAM,mBAAmB,EAAE,GAAG,UAAU,iBAAiB;AAGzD,kBAAgB,OAAO;AAAA,IACrB,OAAO,QAAQ,aAAa,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AAElD,YAAM,WAAW,IAAI,eAAe,MAAM;AAC1C,uBAAiB,QAAQ,IAAI,iBAAiB,MAAM,EAAE;AAEtD,aAAO;AAAA,QACL;AAAA,QACA;AAAA,UACE,GAAG;AAAA,UACH,IAAI;AAAA;AAAA;AAAA,UAGJ,QAAQ,MAAM,OAAO,IAAI,CAAC,UAAU,IAAI,eAAe,OAAO;AAAA,QAChE;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM;AAAA,IACJ,EAAE,wBAAwB,2BAA2B;AAAA,IACrD,EAAE,wBAAwB,6BAA6B;AAAA,IACvD,EAAE,mBAAmB;AAAA,EACvB,IAAI,MAAM,QAAQ;AAAA,IAChB,QAAQ,IAAI,YACR;AAAA,MACE;AAAA,QACE,MAAM,OAAO,mCAAmC;AAAA,MAClD;AAAA,MACA;AAAA,QACE,MAAM,OAAO,wCAAwC;AAAA,MACvD;AAAA,MACA,OAAO,2BAA2B;AAAA,IACpC,IACA;AAAA,MACE;AAAA,QACE,MAAM,OAAO,iCAAiC;AAAA,MAChD;AAAA,MACA;AAAA,QACE,MAAM,OAAO,sCAAsC;AAAA,MACrD;AAAA,MACA,OAAO,yBAAyB;AAAA,IAClC;AAAA,EACN;AACA,QAAM,yBACJ,8BAA8B;AAEhC,MAAI,OAAO,2BAA2B,YAAY;AAChD,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAGA,QAAM,SAAS,uBAAuB,UAAU,aAAa;AAE7D,QAAM,OAAO,CAAC;AACd,QAAM,UAAU,IAAI,YAAY;AAGhC,mBAAiB,SAAS,QAAgD;AACxE,SAAK,KAAK,QAAQ,OAAO,KAAK,CAAC;AAAA,EACjC;AAEA,QAAM,UAAU,QAAQ,IAAI,YAAY,cAAc;AACtD,QAAM,sBAAsB,GAAG,QAAQ,OAAO,QAAQ,OAAO,GAAG;AAEhE;AAAA;AAAA,IAEE;AAAA,MAAC;AAAA;AAAA,QACC,eAAa;AAAA,QACb,cAAY;AAAA,QACZ,gBAAc;AAAA,QACd,IAAI,GAAG;AAAA,QAEP;AAAA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,eAAe,UAAU,iBAAiB,CAAC;AAAA,cAC3C,WAAW;AAAA,cACX,MAAM;AAAA;AAAA,UACR;AAAA,UAEA,4CAAC,uBAAoB,MAAY,MAAM,qBAAqB;AAAA;AAAA;AAAA,IAC9D;AAAA;AAEJ;","names":[]}
|