Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/mf-ssr-public-path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@modern-js/plugin-module-federation': patch
---

Use the shared SSR public path plugin from the updated Module Federation preview so Modern and Rslib producers can load their asynchronous chunks over HTTP with the loaded-first share strategy.
12 changes: 12 additions & 0 deletions .changeset/modern-3-builtin-module-federation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@modern-js/plugin-module-federation': minor
'@modern-js/app-tools': minor
---

Integrate Module Federation as a built-in Modern.js capability. Automatically detect module-federation.config.ts, expose moduleFederation adapter options, preserve the existing CSR/SSR and data-fetch behavior, and reject simultaneous legacy-plugin registration. Set moduleFederation to false to retain the legacy integration. Runtime APIs and types use the unified enhanced/runtime entry without extra lower-level runtime application dependencies. Default the top-level shareStrategy to loaded-first at build time while honoring explicit configuration, without injecting a shared-strategy runtime plugin.

Resolve SSR output directories from the final bundler path or user distPath configuration with the framework default directory constant. Remove unused Bridge forwarding entries and obsolete browser fallbacks.

Retain the CLI configuration, SSR, data-fetch server plugin and type entry points. Remove the broad Enhanced runtime forwarding facade. Use the resolved application output directory and development port, and honor the server output directory when serving federated JavaScript.

Use the shared Modern.js CLI logger for configuration and bundler messages.
58 changes: 58 additions & 0 deletions .github/workflows/test-module-federation-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Module Federation E2E

on:
pull_request:
branches: [main, feat/module-federation-builtin]
types: [opened, synchronize, reopened, ready_for_review]
push:
branches: [main, feat/module-federation-builtin]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: mf-e2e-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
module-federation-e2e:
runs-on: ubuntu-latest
timeout-minutes: 45
env:
MF_LAB_DIAGNOSTICS: '1'
NX_DAEMON: 'false'
NX_REJECT_UNKNOWN_LOCAL_CACHE: '0'
steps:
- name: Checkout
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4

- name: Install pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4

- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22.x
cache: pnpm

- name: Install dependencies
run: pnpm install --ignore-scripts --frozen-lockfile

- name: Nx cache
uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # v3
with:
path: .nx/cache
key: nx-mf-e2e-${{ github.ref_name }}-${{ github.sha }}
restore-keys: |
nx-mf-e2e-${{ github.ref_name }}-
nx-mf-e2e-

- name: Build Modern.js and its dependencies
run: pnpm exec nx run-many --target=build --projects=@modern-js/app-tools,@modern-js/runtime --parallel=2

- name: Install Chrome
run: pnpm --filter mf-lab-tests exec puppeteer browsers install chrome

- name: Test MF development and production
run: pnpm --filter mf-lab-tests test --bail=1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@modern-js/runtime/registry/index';
export declare const provider: () => {
render(info: import("@module-federation/modern-js-v3/react-v19").RenderParams): Promise<void>;
destroy(info: import("@module-federation/modern-js-v3/react-v19").DestroyParams): void;
render(info: import("@module-federation/bridge-react/v19").RenderParams): Promise<void>;
destroy(info: import("@module-federation/bridge-react/v19").DestroyParams): void;
};
export default provider;
3 changes: 1 addition & 2 deletions examples/module-federation/app-export/host/modern.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { appTools, defineConfig } from '@modern-js/app-tools';
import { moduleFederationPlugin } from '@module-federation/modern-js-v3';

// https://modernjs.dev/en/configure/app/usage
export default defineConfig({
plugins: [appTools(), moduleFederationPlugin()],
plugins: [appTools()],
resolve: {
alias: {
'react-router-dom': require.resolve('react-router-dom'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
import { createModuleFederationConfig } from '@module-federation/enhanced';

export default createModuleFederationConfig({
name: 'host',
dts: { consumeTypes: { typesOnBuild: true } },
remotes: {
remote: 'remote@http://localhost:3051/static/mf-manifest.json',
},
Expand Down
7 changes: 4 additions & 3 deletions examples/module-federation/app-export/host/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
},
"dependencies": {
"@modern-js/runtime": "latest",
"@module-federation/modern-js-v3": "2.0.0",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-router": "^7.15.0",
"react-router-dom": "^7.15.0"
"react-router-dom": "^7.15.0",
"@module-federation/enhanced": "0.0.0-feat-enhanced-runtime-unification-20261022085654",
"@module-federation/bridge-react": "0.0.0-feat-enhanced-runtime-unification-20261022085654"
},
"devDependencies": {
"@modern-js/app-tools": "latest",
Expand All @@ -27,6 +28,6 @@
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"rimraf": "^6.1.3",
"typescript": "~5.0.4"
"typescript": "^5.9.3"
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference types='@modern-js/app-tools/types' />
/// <reference types='@modern-js/runtime/types' />
/// <reference types='@modern-js/runtime/types/router' />
/// <reference types='@module-federation/modern-js-v3' />
/// <reference types='@module-federation/enhanced' />
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createRemoteAppComponent } from '@module-federation/modern-js-v3/react';
import { loadRemote } from '@module-federation/modern-js-v3/runtime';
import { createRemoteAppComponent } from '@module-federation/bridge-react';
import { loadRemote } from '@module-federation/enhanced/runtime';

// 定义 FallbackErrorComp 组件
const ErrorBoundary = (info?: { error: { message: string } }) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { appTools, defineConfig } from '@modern-js/app-tools';
import { moduleFederationPlugin } from '@module-federation/modern-js-v3';

// https://modernjs.dev/en/configure/app/usage
export default defineConfig({
Expand All @@ -12,5 +11,5 @@ export default defineConfig({
// Module federation will automatically write it to mf-manifest.json, which influences consumer to fetch remoteEntry.js.
assetPrefix: 'http://127.0.0.1:3051',
},
plugins: [appTools(), moduleFederationPlugin()],
plugins: [appTools()],
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
import { createModuleFederationConfig } from '@module-federation/enhanced';

export default createModuleFederationConfig({
name: 'remote',
dts: { generateTypes: { typesFolder: 'static/@mf-types' } },
manifest: {
filePath: 'static',
additionalData({ stats }) {
stats.metaData.types.zip = 'static/@mf-types.zip';
stats.metaData.types.api = 'static/@mf-types.d.ts';
},
},
filename: 'static/remoteEntry.js',
exposes: {
Expand Down
5 changes: 3 additions & 2 deletions examples/module-federation/app-export/remote/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"@modern-js/runtime": "latest",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"@module-federation/modern-js-v3": "2.0.0"
"@module-federation/enhanced": "0.0.0-feat-enhanced-runtime-unification-20261022085654",
"@module-federation/bridge-react": "0.0.0-feat-enhanced-runtime-unification-20261022085654"
},
"devDependencies": {
"@modern-js/app-tools": "latest",
Expand All @@ -25,6 +26,6 @@
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"rimraf": "^6.1.3",
"typescript": "~5.0.4"
"typescript": "^5.9.3"
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import '@modern-js/runtime/registry/index'; // 这一行必须引入,它会默认导入微前端运行时依赖
import { render } from '@modern-js/runtime/browser';
import { createRoot } from '@modern-js/runtime/react';
import { createBridgeComponent } from '@module-federation/modern-js-v3/react-v19';
import { createBridgeComponent } from '@module-federation/bridge-react/v19';
import type { ReactElement } from 'react';

const ModernRoot = createRoot();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DataFetchParams } from '@module-federation/modern-js-v3/react';
import type { DataFetchParams } from '@module-federation/bridge-react';
export type Data = {
data: string;
};
Expand Down
3 changes: 1 addition & 2 deletions examples/module-federation/base/host/modern.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { appTools, defineConfig } from '@modern-js/app-tools';
import { moduleFederationPlugin } from '@module-federation/modern-js-v3';

// https://modernjs.dev/en/configure/app/usage
export default defineConfig({
server: {
ssr: true,
},
plugins: [appTools(), moduleFederationPlugin()],
plugins: [appTools()],
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
import { createModuleFederationConfig } from '@module-federation/enhanced';

export default createModuleFederationConfig({
name: 'host',
dts: { consumeTypes: { typesOnBuild: true } },
remotes: {
remote: 'remote@http://localhost:3051/static/mf-manifest.json',
},
Expand Down
6 changes: 3 additions & 3 deletions examples/module-federation/base/host/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-router-dom": "^7.15.1",
"@module-federation/modern-js-v3": "2.0.0",
"@module-federation/runtime": "2.0.0"
"@module-federation/enhanced": "0.0.0-feat-enhanced-runtime-unification-20261022085654",
"@module-federation/bridge-react": "0.0.0-feat-enhanced-runtime-unification-20261022085654"
},
"devDependencies": {
"@modern-js/app-tools": "latest",
Expand All @@ -27,6 +27,6 @@
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"rimraf": "^6.1.3",
"typescript": "~5.0.4"
"typescript": "^5.9.3"
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference types='@modern-js/app-tools/types' />
/// <reference types='@modern-js/runtime/types' />
/// <reference types='@modern-js/runtime/types/router' />
/// <reference types='@module-federation/modern-js-v3' />
/// <reference types='@module-federation/enhanced' />
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* But it will flash the page when use SSR and the provider has css
* For detail, please see https://module-federation.io/practice/frameworks/modern/index.html#css-flickering-issue
*/
import { createLazyComponent } from '@module-federation/modern-js-v3/react';
import { getInstance } from '@module-federation/modern-js-v3/runtime';
import { createLazyComponent } from '@module-federation/bridge-react';
import { getInstance } from '@module-federation/enhanced/runtime';
import type React from 'react';

const Button = createLazyComponent({
Expand Down
3 changes: 1 addition & 2 deletions examples/module-federation/base/remote/modern.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { appTools, defineConfig } from '@modern-js/app-tools';
import { moduleFederationPlugin } from '@module-federation/modern-js-v3';

// https://modernjs.dev/en/configure/app/usage
export default defineConfig({
Expand All @@ -13,5 +12,5 @@ export default defineConfig({
// Module federation will automatically write it to mf-manifest.json, which influences consumer to fetch remoteEntry.js.
assetPrefix: 'http://127.0.0.1:3051',
},
plugins: [appTools(), moduleFederationPlugin()],
plugins: [appTools()],
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
import { createModuleFederationConfig } from '@module-federation/enhanced';

export default createModuleFederationConfig({
name: 'remote',
dts: { generateTypes: { typesFolder: 'static/@mf-types' } },
manifest: {
filePath: 'static',
additionalData({ stats }) {
stats.metaData.types.zip = 'static/@mf-types.zip';
stats.metaData.types.api = 'static/@mf-types.d.ts';
},
},
filename: 'static/remoteEntry.js',
exposes: {
Expand Down
9 changes: 5 additions & 4 deletions examples/module-federation/base/remote/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"@modern-js/runtime": "latest",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"@module-federation/modern-js-v3": "2.0.0"
"@module-federation/enhanced": "0.0.0-feat-enhanced-runtime-unification-20261022085654",
"@module-federation/bridge-react": "0.0.0-feat-enhanced-runtime-unification-20261022085654"
},
"devDependencies": {
"@modern-js/app-tools": "latest",
Expand All @@ -25,8 +26,8 @@
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"rimraf": "^6.1.3",
"typescript": "~5.0.4",
"ts-node": "~10.8.1",
"tsconfig-paths": "~3.14.1"
"typescript": "^5.9.3",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DataFetchParams } from '@module-federation/modern-js-v3/react';
import type { DataFetchParams } from '@module-federation/bridge-react';

export type Data = {
data: string;
Expand Down
21 changes: 21 additions & 0 deletions packages/cli/plugin-module-federation/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024-present zhanghang(2heal1)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading
Loading