Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
1b194ad
fix: preserve worker runtimes with shared runtime chunk
ScriptedAlchemy Oct 4, 2025
8b328d9
fix: adjust runtime reassignment timing
ScriptedAlchemy Oct 4, 2025
decc21f
fix: retain runtime modules when reassigning chunks
ScriptedAlchemy Oct 4, 2025
75762c8
fix: carry runtime modules when moving worker runtime
ScriptedAlchemy Oct 4, 2025
16af11a
fix: copy runtime requirements to reassigned chunk
ScriptedAlchemy Oct 4, 2025
f137cb9
fix: guard remote runtime when bundler runtime missing
ScriptedAlchemy Oct 4, 2025
aa9c43a
fix: guard remotes helper when bundler runtime absent
ScriptedAlchemy Oct 4, 2025
0fada87
fix: guard remote runtime indentation
ScriptedAlchemy Oct 4, 2025
6b14527
fix: type guard runtime template indent
ScriptedAlchemy Oct 4, 2025
53301e6
fix: retain shared runtime modules for async entries
ScriptedAlchemy Oct 4, 2025
ac8fc81
chore: add changeset for async runtime fix
ScriptedAlchemy Oct 4, 2025
a30e43c
test: cover worker runtime chunk clone
ScriptedAlchemy Oct 4, 2025
b00b06b
test: capture worker runtime duplication
ScriptedAlchemy Oct 4, 2025
0cfff1b
test: cover compiler runtime hoisting
ScriptedAlchemy Oct 5, 2025
c5afda1
fix(module-federation): guard remote runtime chunk relocation
ScriptedAlchemy Oct 6, 2025
874341d
test(enhanced): add worker test case for module federation
ScriptedAlchemy Oct 7, 2025
1062bc9
fix(enhanced): prevent React version contamination in worker test
ScriptedAlchemy Oct 7, 2025
66325ee
fix(enhanced): ensure federation runtime in worker chunks and prevent…
ScriptedAlchemy Oct 7, 2025
49c44ab
chore(module-federation): scope root test script to packages (tag:typ…
ScriptedAlchemy Oct 7, 2025
e0226a0
Merge remote-tracking branch 'origin/main' into research/issue-4085
ScriptedAlchemy Oct 7, 2025
c9d39ff
chore(runtime-demo): add Worker wrapper demo mirroring gravity-ui pat…
ScriptedAlchemy Oct 7, 2025
95cef3f
fix(runtime-demo): enable runtime chunk and use WorkerWrapper for wor…
ScriptedAlchemy Oct 7, 2025
e242212
fix: format code to pass CI checks
ScriptedAlchemy Oct 7, 2025
dac0e60
chore(tests,docs): restore removed fixtures and docs from main
ScriptedAlchemy Oct 7, 2025
3e2713f
test(runtime-demo): skip WorkerWrapper in Cypress to avoid importScri…
ScriptedAlchemy Oct 7, 2025
09a4ff2
test(enhanced): add react stub under container/worker test fixture to…
ScriptedAlchemy Oct 7, 2025
730e00e
test(runtime-demo): skip WorkerDemo worker init under Cypress to avoi…
ScriptedAlchemy Oct 7, 2025
8bf41de
test(e2e): account for Cypress skip by expecting n/a for worker result
ScriptedAlchemy Oct 7, 2025
afc8e68
fix(runtime-demo): load compiled worker via .js URL so importScripts …
ScriptedAlchemy Oct 7, 2025
a5511fd
fix(runtime-demo): emit dedicated worker entry as worker.js and point…
ScriptedAlchemy Oct 7, 2025
8bdbc3d
fix(runtime-demo): force importScripts to load /worker.js from public…
ScriptedAlchemy Oct 7, 2025
a35626c
test(e2e): assert both native worker and worker-loader wrapper responses
ScriptedAlchemy Oct 7, 2025
4d685d0
fix(runtime-demo): preload runtime.js in worker loader and use static…
ScriptedAlchemy Oct 7, 2025
2779164
Merge branch 'main' into research/issue-4085
ScriptedAlchemy Oct 8, 2025
d0f805d
Merge remote-tracking branch 'origin/main' into research/issue-4085
ScriptedAlchemy Oct 9, 2025
c08e78e
test: add worker federation compiler integration
ScriptedAlchemy Oct 9, 2025
a98e9d1
refactor: use existing identifiers for async runtimes
ScriptedAlchemy Oct 9, 2025
bbb335f
fix: ensure runtime names are plain strings
ScriptedAlchemy Oct 9, 2025
8188210
test: inspect share plugin internals via private fields
ScriptedAlchemy Oct 9, 2025
6b5045a
refactor: switch runtime app to worker-loader
ScriptedAlchemy Oct 9, 2025
952bec0
refactor: split worker demo into native and loader flows
ScriptedAlchemy Oct 9, 2025
db01b16
test: disable dts in worker async runtime test
ScriptedAlchemy Oct 9, 2025
2177eac
chore: merge main into research issue 4085
ScriptedAlchemy Oct 10, 2025
58c0cf0
fix: reattach runtime modules via hooks
ScriptedAlchemy Oct 10, 2025
a6bede7
test: harden compiler unit suites
ScriptedAlchemy Oct 10, 2025
58b007c
chore: merge main
ScriptedAlchemy Oct 10, 2025
3357428
chore: run full enhanced test suite
ScriptedAlchemy Oct 10, 2025
b4f0a90
test: extend worker integration timeout
ScriptedAlchemy Oct 10, 2025
7cc4b1f
Merge branch 'main' into research/issue-4085
ScriptedAlchemy Oct 10, 2025
39c8d3a
fix: guard manifest package detection
ScriptedAlchemy Oct 10, 2025
ae883fd
Merge branch 'main' into research/issue-4085
ScriptedAlchemy Oct 10, 2025
8fd36a6
chore: disable nx tui and clean enhanced jest setup
ScriptedAlchemy Oct 10, 2025
da540ca
Merge remote-tracking branch 'origin/main' into research/issue-4085
ScriptedAlchemy Oct 10, 2025
a0e6864
fix(runtime): hoist federation runtime into worker child compilers
ScriptedAlchemy Oct 11, 2025
1d5497a
fix(enhanced): inject federation runtime into worker chunks
ScriptedAlchemy Oct 12, 2025
becdf94
fix: ensure runtime logger available in worker
ScriptedAlchemy Oct 12, 2025
0c9ddec
fix(enhanced): restore runtime plugin defaults
ScriptedAlchemy Oct 12, 2025
073d591
feat: include federation runtime for worker blocks
ScriptedAlchemy Oct 12, 2025
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/steady-workers-remotes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@module-federation/enhanced": patch
---

Keep async entry runtime helpers available when cloning runtimes for web workers and other dynamic entrypoints.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
NX_DEAMON=false
NX_DAEMON=false
2 changes: 1 addition & 1 deletion .github/workflows/e2e-runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ jobs:

- name: E2E Test for Runtime Demo
if: steps.check-ci.outcome == 'success'
run: npx kill-port --port 3005,3006,3007 && pnpm run app:runtime:dev & echo "done" && sleep 20 && npx nx run-many --target=test:e2e --projects=3005-runtime-host --parallel=1 && lsof -ti tcp:3005,3006,3007 | xargs kill
run: node tools/scripts/run-runtime-e2e.mjs --mode=dev
15 changes: 15 additions & 0 deletions apps/runtime-demo/3005-runtime-host/cypress/e2e/app.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,19 @@ describe('3005-runtime-host/', () => {
});
});
});

describe('web worker check', () => {
it('should display value returned from worker', () => {
cy.get('.worker-native-result').should('contain.text', '"answer": "1"');
cy.get('.worker-native-result').should(
'contain.text',
'"federationKeys"',
);
cy.get('.worker-loader-result').should('contain.text', '"answer": "1"');
cy.get('.worker-loader-result').should(
'contain.text',
'"federationKeys"',
);
});
});
});
17 changes: 13 additions & 4 deletions apps/runtime-demo/3005-runtime-host/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,25 @@
"name": "runtime-host",
"private": true,
"version": "0.0.0",
"scripts": {
"build": "webpack --config webpack.config.js --mode production",
"build:development": "webpack --config webpack.config.js --mode development",
"serve": "webpack serve --config webpack.config.js --mode development --host 127.0.0.1 --port 3005 --allowed-hosts all",
"serve:production": "webpack serve --config webpack.config.js --mode production --host 127.0.0.1 --port 3005 --allowed-hosts all --no-hot"
},
"devDependencies": {
"@module-federation/core": "workspace:*",
"@module-federation/dts-plugin": "workspace:*",
"@module-federation/enhanced": "workspace:*",
"@module-federation/runtime": "workspace:*",
"@module-federation/typescript": "workspace:*",
"@module-federation/enhanced": "workspace:*",
"@module-federation/dts-plugin": "workspace:*",
"@pmmmwh/react-refresh-webpack-plugin": "0.5.15",
"react-refresh": "0.14.2",
"@types/react": "18.3.11",
"@types/react-dom": "18.3.0"
"@types/react-dom": "18.3.0",
"mini-css-extract-plugin": "2.9.2",
"react-refresh": "0.14.2",
"css-loader": "6.11.0",
"webpack-dev-server": "5.1.0"
},
"dependencies": {
"antd": "4.24.15",
Expand Down
45 changes: 15 additions & 30 deletions apps/runtime-demo/3005-runtime-host/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,21 @@
"tags": [],
"targets": {
"build": {
"executor": "@nx/webpack:webpack",
"outputs": ["{options.outputPath}"],
"executor": "nx:run-commands",
"outputs": ["{projectRoot}/dist"],
"defaultConfiguration": "production",
"options": {
"compiler": "babel",
"outputPath": "apps/runtime-demo/3005-runtime-host/dist",
"index": "apps/runtime-demo/3005-runtime-host/src/index.html",
"baseHref": "/",
"main": "apps/runtime-demo/3005-runtime-host/src/index.ts",
"tsConfig": "apps/runtime-demo/3005-runtime-host/tsconfig.app.json",
"styles": [],
"scripts": [],
"webpackConfig": "apps/runtime-demo/3005-runtime-host/webpack.config.js",
"babelUpwardRootMode": true
"command": "pnpm run build",
"cwd": "apps/runtime-demo/3005-runtime-host"
},
"configurations": {
"development": {
"extractLicenses": false,
"optimization": false,
"sourceMap": true,
"vendorChunk": true
"command": "pnpm run build:development",
"cwd": "apps/runtime-demo/3005-runtime-host"
},
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": false,
"vendorChunk": false
"command": "pnpm run build",
"cwd": "apps/runtime-demo/3005-runtime-host"
}
},
"dependsOn": [
Expand All @@ -45,21 +31,20 @@
]
},
"serve": {
"executor": "@nx/webpack:dev-server",
"executor": "nx:run-commands",
"defaultConfiguration": "production",
"options": {
"buildTarget": "3005-runtime-host:build",
"hmr": true,
"port": 3005,
"devRemotes": ["3006-runtime-remote"]
"command": "pnpm run serve:production",
"cwd": "apps/runtime-demo/3005-runtime-host"
},
"configurations": {
"development": {
"buildTarget": "3005-runtime-host:build:development"
"command": "pnpm run serve",
"cwd": "apps/runtime-demo/3005-runtime-host"
},
"production": {
"buildTarget": "3005-runtime-host:build:production",
"hmr": false
"command": "pnpm run serve:production",
"cwd": "apps/runtime-demo/3005-runtime-host"
}
},
"dependsOn": [
Expand Down
36 changes: 36 additions & 0 deletions apps/runtime-demo/3005-runtime-host/src/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import WebpackPng from './webpack.png';
import WebpackSvg from './webpack.svg';
import { WebpackPngRemote, WebpackSvgRemote } from './Remote1';
import Remote2 from './Remote2';
import WorkerNativeDemo from './components/WorkerNativeDemo';
import WorkerLoaderDemo from './components/WorkerLoaderDemo';

const Root = () => (
<div>
Expand Down Expand Up @@ -89,6 +91,40 @@ const Root = () => (
</tr>
</tbody>
</table>

<h3>check workers</h3>
<table border={1} cellPadding={5}>
<thead>
<tr>
<td></td>
<td>Test case</td>
<td>Expected</td>
<td>Actual</td>
</tr>
</thead>
<tbody>
<tr>
<td>✅</td>
<td>Native new Worker(new URL(...))</td>
<td>
<div className="worker-expected">Expected worker response: 1</div>
</td>
<td>
<WorkerNativeDemo />
</td>
</tr>
<tr>
<td>✅</td>
<td>worker-loader integration</td>
<td>
<div className="worker-expected">Expected worker response: 1</div>
</td>
<td>
<WorkerLoaderDemo />
</td>
</tr>
</tbody>
</table>
</div>
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useEffect, useState } from 'react';

export function WorkerLoaderDemo() {
const [result, setResult] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
try {
const worker = new Worker(
new URL('../worker/loader-worker.js', import.meta.url),
{
name: 'mf-loader-worker',
},
);

worker.onmessage = (event) => {
setResult(event.data ?? null);
};

worker.onerror = (event) => {
setError((event as unknown as ErrorEvent).message ?? 'Worker error');
};

worker.postMessage({ value: 'foo' });

return () => {
worker.terminate();
};
} catch (err) {
setError((err as Error).message);
}

return undefined;
}, []);

return (
<div>
<div className="worker-expected">Expected worker response: 1</div>
<pre className="worker-loader-result">
{result ? JSON.stringify(result, null, 2) : 'n/a'}
</pre>
{error ? <div className="worker-error">Worker error: {error}</div> : null}
</div>
);
}

export default WorkerLoaderDemo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useEffect, useState } from 'react';

export function WorkerNativeDemo() {
const [result, setResult] = useState<any>(null);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
try {
const worker = new Worker(
new URL('../worker/native-worker.js', import.meta.url),
{
name: 'mf-native-worker',
},
);

worker.onmessage = (event) => {
setResult(event.data ?? null);
};

worker.onerror = (event) => {
setError((event as unknown as ErrorEvent).message ?? 'Worker error');
};

worker.postMessage({ value: 'foo' });

return () => {
worker.terminate();
};
} catch (err) {
setError((err as Error).message);
}

return undefined;
}, []);

return (
<div>
<pre className="worker-native-result">
{result ? JSON.stringify(result, null, 2) : 'n/a'}
</pre>
{error ? <div className="worker-error">Worker error: {error}</div> : null}
</div>
);
}

export default WorkerNativeDemo;
15 changes: 15 additions & 0 deletions apps/runtime-demo/3005-runtime-host/src/worker/loader-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* eslint-env worker */
import { workerMap } from './map.js';

self.onmessage = (event) => {
const value = event.data && event.data.value;
const federation =
typeof __webpack_require__ !== 'undefined'
? __webpack_require__.federation || {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is some debug code? Because in my project i got this problem, when federation is undefined (i was unable to reproduce it, but found another error, that i was reported in issue)

: {};
const federationKeys = Object.keys(federation);
self.postMessage({
answer: workerMap[value] ?? null,
federationKeys,
});
};
4 changes: 4 additions & 0 deletions apps/runtime-demo/3005-runtime-host/src/worker/map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const workerMap = {
foo: '1',
bar: '2',
};
15 changes: 15 additions & 0 deletions apps/runtime-demo/3005-runtime-host/src/worker/native-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* eslint-env worker */
import { workerMap } from './map.js';

self.onmessage = (event) => {
const value = event.data && event.data.value;
const federation =
typeof __webpack_require__ !== 'undefined'
? __webpack_require__.federation || {}
: {};
const federationKeys = Object.keys(federation);
self.postMessage({
answer: workerMap[value] ?? null,
federationKeys,
});
};
9 changes: 9 additions & 0 deletions apps/runtime-demo/3005-runtime-host/src/worker/worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* eslint-env worker */
import { workerMap } from './map';

self.onmessage = (event) => {
const value = event.data && event.data.value;
self.postMessage({
answer: workerMap[value] ?? null,
});
};
Loading
Loading