Skip to content

Commit 9e32644

Browse files
ScriptedAlchemysquadronai[bot]github-advanced-security[bot]2heal1
authored
feat(enhanced): fully hoisted runtime (#2932)
Co-authored-by: squadronai[bot] <170149692+squadronai[bot]@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Hanric <[email protected]>
1 parent b2bfa48 commit 9e32644

File tree

71 files changed

+26729
-21426
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+26729
-21426
lines changed

.changeset/ai-brave-tiger.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"@module-federation/data-prefetch": patch
3+
---
4+
5+
Refactored the way prefetch entries are imported for improved dynamic loading handling.
6+
7+
- Changed the import of prefetch entries to use a function wrapper for more dynamic control.
8+
- Updated data types to ensure consistency with the new function-based import approach.
9+
- Modified the `injectPrefetch` function structure to incorporate the new import method.
10+
- Modified the `MFDataPrefetch` class to handle the new import function when resolving exports.

.changeset/ai-brave-wolf.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@module-federation/nextjs-mf": minor
3+
---
4+
5+
Simplified InvertedContainerPlugin by removing configuration dependencies and improving runtime module integration.
6+
7+
- Refactored `InvertedContainerPlugin` to remove redundant configurations.
8+
- Deleted `EmbeddedContainerPlugin` and moved its logic into `InvertedContainerPlugin`.
9+
- Modified `InvertedContainerRuntimeModule` to dynamically locate and integrate container entry modules.
10+
- Commented out runtime chunk creation in `configureServerCompilerOptions`.
11+
- Enhanced module dependency handling using `FederationModulesPlugin` hooks.

.changeset/ai-hungry-wolf.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"@module-federation/runtime": patch
3+
---
4+
5+
Added comprehensive integration tests for the API synchronization and enhanced the embedded module proxy implementation.
6+
7+
- Added detailed integration tests for API consistency between embedded and index modules.
8+
- Tests include export comparison and method consistency for `FederationHost` and `Module` classes.
9+
- Introduced and updated the `embedded.ts` file to dynamically access the runtime modules at runtime.
10+
- Included detailed implementations for accessing and wrapping existing runtime functions.
11+
- Exposed the previously private `formatOptions` method in the `FederationHost` class publicly.
12+
- Enhanced error handling for uninstantiated or unregistered runtime access.
13+
```

.changeset/ai-lazy-cat.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@module-federation/enhanced": patch
3+
---
4+
5+
Added support for hoisting federation runtime modules and enhancing dependency management.
6+
7+
- Introduced `FederationModulesPlugin` to handle federation-related hooks and dependencies.
8+
- Added new `FederationRuntimeDependency` and logic to include it conditionally.
9+
- Enhanced `ContainerPlugin` and related plugins to support experimental `federationRuntime` options.
10+
- Modified `HoistContainerReferencesPlugin` to hoist additional modules in chunks.
11+
- Implemented changes across multiple files to support the new plugin and dependency management features.

.changeset/ai-quick-lion.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@module-federation/sdk": patch
3+
---
4+
5+
Added experimental option for federation runtime in ContainerPluginOptions.
6+
7+
- Extended `ContainerPluginOptions` to include an `experiments` property.
8+
- Within `experiments`, added a `federationRuntime` option.
9+
- `federationRuntime` can be either `false` or `'hoisted'`.

.changeset/ai-sleepy-lion.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@module-federation/enhanced": patch
3+
---
4+
5+
Refactor `HoistContainerReferencesPlugin` to optimize module disconnection and cleanup logic.
6+
7+
- Removed `moduleToDelete` set as it was redundant.
8+
- Ensured all referenced modules are disconnected from unused chunks directly.
9+
- Added call to `cleanUpChunks` within the main loop to clean up chunks using `allReferencedModules`.

.changeset/chilly-rocks-deliver.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
"@module-federation/runtime": patch
3+
---
4+
5+
- Refactor `embedded.ts` to use a proxy pattern for better runtime compatibility:
6+
- Implement FederationHost and Module classes that delegate to the actual runtime implementation
7+
- Expose all public methods and properties from the original classes
8+
- Use a lazy initialization approach to ensure proper runtime loading
9+
- Add comprehensive test suite for API synchronization between embedded.ts and index.ts
10+
- Introduce new test file `sync.spec.ts` with extensive tests for API compatibility
11+
- Ensure FederationHost and Module classes have the same methods in both files
12+
- Test various scenarios including remote loading, manifest handling, and circular dependencies
13+
- Modify `core.ts` to make `formatOptions` method public
14+

.changeset/eight-comics-reflect.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@module-federation/enhanced': patch
3+
---
4+
5+
handle chunk entry modules correctly in MfStartupChunkDependenciesPlugin

.github/workflows/build-and-test.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,17 @@ jobs:
3636
- name: Check Code Format
3737
run: npx nx format:check
3838

39+
- name: Warm Nx Cache
40+
run: npx nx run-many --targets=build --projects=tag:type:pkg
41+
3942
- name: Run Build for All
4043
run: npx nx run-many --targets=build --projects=tag:type:pkg --skip-nx-cache
4144

4245
- name: Run Affected Test
4346
run: npx nx affected -t test --parallel=2 --exclude='*,!tag:type:pkg' --skip-nx-cache
4447

45-
- name: Warm Nx Cache
46-
run: npx nx run-many --targets=build --projects=tag:type:pkg
48+
- name: Run Affected Experimental Tests
49+
run: npx nx affected -t test:experiments --parallel=2 --exclude='*,!tag:type:pkg' --skip-nx-cache
4750

4851
e2e-modern:
4952
needs: checkout-install

.github/workflows/devtools.yml

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,35 @@ jobs:
3535
run: pnpm install
3636

3737
- name: Run Affected Build
38-
run: npx nx run-many --targets=build --projects=tag:type:pkg --skip-nx-cache
38+
run: npx nx run-many --targets=build --projects=tag:type:pkg
3939

4040
- name: Configuration xvfb
4141
shell: bash
4242
run: sudo apt-get update && sudo apt-get install xvfb
4343

44-
- name: E2E Chrome Devtools
45-
run: pnpm run app:manifest:dev & echo "done" && npx wait-on tcp:3009 tcp:3010 tcp:3011 tcp:3012 && sleep 10 && npx nx e2e:devtools chrome-devtools
44+
- name: E2E Chrome Devtools Dev
45+
uses: nick-fields/retry@v3
46+
with:
47+
timeout_minutes: 10
48+
max_attempts: 3 # Initial attempt + 2 retries
49+
command: |
50+
npx kill-port 3009 3010 3011 3012 3013 4001 &&
51+
pnpm run app:manifest:dev & echo "done" && \
52+
npx wait-on tcp:3009 tcp:3010 tcp:3011 tcp:3012 tcp:3013 && \
53+
sleep 10 &&
54+
npx nx e2e:devtools chrome-devtools
55+
56+
- name: E2E Chrome Devtools Prod
57+
uses: nick-fields/retry@v3
58+
with:
59+
timeout_minutes: 10
60+
max_attempts: 3 # Initial attempt + 2 retries
61+
command: |
62+
npx kill-port 3009 3010 3011 3012 3013 4001 &&
63+
pnpm run app:manifest:prod & echo "done" && \
64+
npx wait-on tcp:3009 tcp:3010 tcp:3011 tcp:3012 tcp:3013 && \
65+
sleep 10 &&
66+
npx nx e2e:devtools chrome-devtools
4667
4768
- name: kill port
48-
run: lsof -ti tcp:3008,3009,3010,3011,3012 | xargs kill
69+
run: npx kill-port 3013 3009 3010 3011 3012 4001

.github/workflows/e2e-manifest.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ jobs:
4141
id: check-ci
4242
run: node tools/scripts/ci-is-affected.mjs --appName=manifest-webpack-host
4343

44-
- name: E2E Test for Manifest Demo
44+
- name: E2E Test for Manifest Demo Development
4545
if: steps.check-ci.outcome == 'success'
4646
run: pnpm run app:manifest:dev & echo "done" && npx wait-on tcp:3009 && npx wait-on tcp:3012 && npx wait-on http://127.0.0.1:4001/ && npx nx run-many --target=e2e --projects=manifest-webpack-host --parallel=1 && npx kill-port 3013 3009 3010 3011 3012 4001
47+
48+
- name: E2E Test for Manifest Demo Production
49+
if: steps.check-ci.outcome == 'success'
50+
run: pnpm run app:manifest:prod & echo "done" && npx wait-on tcp:3009 && npx wait-on tcp:3012 && npx wait-on http://127.0.0.1:4001/ && npx nx run-many --target=e2e --projects=manifest-webpack-host --parallel=1 && npx kill-port 3013 3009 3010 3011 3012 4001

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,4 @@ packages/enhanced/test/js
6666
**/cache/**
6767
**/dist-test/**
6868
**/cypress/downloads
69+
/packages/data-prefetch/jest/cache/

ai-lint-fix.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/env node
2+
3+
const { execSync, execFileSync } = require('child_process');
4+
const fs = require('fs');
5+
const path = require('path');
6+
const { OpenAI } = require('openai');
7+
const yargs = require('yargs/yargs');
8+
const { hideBin } = require('yargs/helpers');
9+
const glob = require('glob');
10+
// Initialize OpenAI client
11+
const openai = new OpenAI({
12+
apiKey: process.env.OPENAI_API_KEY,
13+
});
14+
15+
// Parse command line arguments
16+
const argv = yargs(hideBin(process.argv))
17+
.option('pattern', {
18+
alias: 'p',
19+
type: 'string',
20+
description: 'Glob pattern to match files',
21+
})
22+
.option('path', {
23+
alias: 'f',
24+
type: 'string',
25+
description: 'Path to a specific file',
26+
})
27+
.check((argv) => {
28+
if (!argv.pattern && !argv.path) {
29+
throw new Error('You must provide either a --pattern or --path argument');
30+
}
31+
return true;
32+
})
33+
.help()
34+
.alias('help', 'h').argv;
35+
36+
async function lintFileContent(fileContent) {
37+
const prompt = `Perform safe cleanup and linting on the following file content.
38+
RULES:
39+
-Should preserve uses of normalizeWebpackPath
40+
-Should preserve uses of ts-ignore
41+
-Removed commented out code
42+
-Return only the updated file content with no other response text:
43+
44+
${fileContent}`;
45+
46+
const response = await openai.chat.completions.create({
47+
model: 'gpt-4o',
48+
messages: [{ role: 'user', content: prompt }],
49+
max_tokens: 4096,
50+
});
51+
52+
let res = response.choices[0].message.content.trim().split('\n');
53+
if (res[0].startsWith('`')) {
54+
res[0] = undefined;
55+
}
56+
57+
if (res[res.length - 1].startsWith('`')) {
58+
res[res.length - 1] = undefined;
59+
}
60+
61+
return res.filter((r) => r).join('\n');
62+
}
63+
64+
async function processFile(filePath) {
65+
const fileContent = fs.readFileSync(filePath, 'utf8');
66+
try {
67+
const lintedContent = await lintFileContent(fileContent);
68+
fs.writeFileSync(filePath, lintedContent, 'utf8');
69+
console.log(`File has been linted and updated successfully: ${filePath}`);
70+
const tsConfigPath = findTsConfig(filePath);
71+
try {
72+
const tscOutput = execFileSync(
73+
'tsc',
74+
['--noEmit', '--project', tsConfigPath],
75+
{
76+
stdio: 'pipe',
77+
},
78+
).toString();
79+
console.log(`TypeScript check passed for ${filePath}:\n${tscOutput}`);
80+
} catch (error) {
81+
console.error(
82+
`TypeScript check failed for ${filePath}:\n${error.stdout.toString()}`,
83+
);
84+
}
85+
} catch (error) {
86+
console.error(`Error performing linting on ${filePath}:`, error.message);
87+
process.exit(1);
88+
}
89+
}
90+
91+
function findTsConfig(filePath) {
92+
let dir = path.dirname(filePath);
93+
while (dir !== path.resolve(dir, '..')) {
94+
const tsConfigPath = path.join(dir, 'tsconfig.json');
95+
if (fs.existsSync(tsConfigPath)) {
96+
return tsConfigPath;
97+
}
98+
dir = path.resolve(dir, '..');
99+
}
100+
throw new Error('tsconfig.json not found');
101+
}
102+
103+
async function main() {
104+
if (argv.path) {
105+
await processFile(argv.path);
106+
} else if (argv.pattern) {
107+
console.log('pattern', argv.pattern);
108+
try {
109+
const files = await glob.glob(argv.pattern);
110+
111+
for (const filePath of files) {
112+
await processFile(filePath);
113+
}
114+
} catch (err) {
115+
console.error('Error finding files:', err.message);
116+
process.exit(1);
117+
}
118+
}
119+
execSync('nx format:write');
120+
}
121+
122+
main();

apps/manifest-demo/3009-webpack-provider/webpack.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ module.exports = composePlugins(
5555
config.optimization = {
5656
...config.optimization,
5757
runtimeChunk: false,
58-
minimize: false,
5958
};
6059
return config;
6160
},

apps/manifest-demo/webpack-host/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "manifest-webpack-host",
3-
"$schema": "../../node_modules/nx/schemas/project-schema.json",
3+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
44
"sourceRoot": "apps/manifest-demo/webpack-host/src",
55
"projectType": "application",
66
"targets": {

apps/manifest-demo/webpack-host/webpack.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ module.exports = composePlugins(withNx(), withReact(), (config, context) => {
5757
scriptType: 'text/javascript',
5858
};
5959
config.optimization = {
60+
...config.optimization,
6061
runtimeChunk: 'single',
6162
minimize: false,
6263
moduleIds: 'named',

apps/modernjs/modern.config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,21 @@ export default defineConfig({
3737
}
3838

3939
appendPlugins([
40-
new AsyncBoundaryPlugin({
41-
excludeChunk: chunk => chunk.name === 'app1',
42-
eager: module => /\.federation/.test(module?.request || ''),
43-
}),
4440
new ModuleFederationPlugin({
4541
name: 'app1',
4642
exposes: {
4743
'./thing': './src/test.ts',
4844
'./react-component': './src/components/react-component.tsx',
4945
},
5046
runtimePlugins: ['./runtimePlugin.ts'],
47+
filename: 'remoteEntry.js',
5148
shared: {
5249
react: { singleton: true },
5350
'react-dom': { singleton: true },
5451
},
52+
experiments: {
53+
federationRuntime: 'hoisted',
54+
},
5555
dataPrefetch: true,
5656
}),
5757
]);

apps/modernjs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"dev": "modern dev",
88
"build": "modern build",
99
"start": "modern start",
10-
"serve": "modern serve",
10+
"serve": "PORT=4001 modern serve",
1111
"new": "modern new",
1212
"lint": "modern lint",
1313
"upgrade": "modern upgrade"

0 commit comments

Comments
 (0)