Skip to content
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9c9eb54
feat(module-federation): add opencode config for alias resolution in …
ScriptedAlchemy Aug 28, 2025
6e829a7
feat(enhanced): improve module sharing with alias resolution
ScriptedAlchemy Sep 2, 2025
5d4cd6d
refactor(enhanced): simplify consume factorize; rename option; refine…
ScriptedAlchemy Sep 5, 2025
42a9b47
feat(enhanced): add alias-aware consume matching via resolverFactory;…
ScriptedAlchemy Sep 5, 2025
5a67bc8
feat(enhanced): alias-aware share-key derivation
ScriptedAlchemy Sep 6, 2025
667a941
chore: debugging
ScriptedAlchemy Sep 8, 2025
ad9b72e
Revert "chore: debugging"
ScriptedAlchemy Sep 8, 2025
2bf170b
Revert "feat(enhanced): alias-aware share-key derivation"
ScriptedAlchemy Sep 8, 2025
4c8ab16
Revert "feat(enhanced): add alias-aware consume matching via resolver…
ScriptedAlchemy Sep 8, 2025
2ec299f
feat(enhanced): add alias-aware providing and consuming for shared mo…
ScriptedAlchemy Sep 8, 2025
baf0d9d
Merge branch 'main' into feat/share-resolver
ScriptedAlchemy Sep 8, 2025
c0810a2
Delete opencode.json
ScriptedAlchemy Sep 8, 2025
097e612
test: add missing aliased target stub for share-with-aliases-provide-…
ScriptedAlchemy Sep 8, 2025
7e502bf
Apply suggested changes
ScriptedAlchemy Sep 8, 2025
f76b386
ci: trigger build
ScriptedAlchemy Sep 9, 2025
7c86fb0
test(enhanced): force sync startup in alias-sharing cases so harness …
ScriptedAlchemy Sep 9, 2025
27e09a9
Merge branch 'main' into feat/share-resolver
ScriptedAlchemy Sep 9, 2025
f15e761
chore: remove unused aliasResolver.ts file
ScriptedAlchemy Sep 9, 2025
e29ec0f
Merge branch 'main' into feat/share-resolver
ScriptedAlchemy Sep 11, 2025
48d4dfd
Delete prompts/alias-resolver.md
ScriptedAlchemy Sep 11, 2025
180e9bf
Merge branch 'main' into feat/share-resolver
ScriptedAlchemy Sep 12, 2025
d897b6f
Merge remote-tracking branch 'origin/main' into feat/share-resolver
ScriptedAlchemy Sep 22, 2025
0522c50
Merge branch 'feat/share-resolver' of github.com:module-federation/co…
ScriptedAlchemy Sep 22, 2025
65812e4
test(enhanced): mock finishModules hook for ConsumeSharedPlugin.facto…
ScriptedAlchemy Sep 22, 2025
c7a0d1d
Merge branch 'main' into feat/share-resolver
ScriptedAlchemy Sep 27, 2025
6c7174e
refactor(enhanced): resolve alias-aware consumes in afterResolve with…
ScriptedAlchemy Sep 30, 2025
d7c4772
Merge branch 'main' into feat/share-resolver
ScriptedAlchemy Sep 30, 2025
5270815
Merge remote-tracking branch 'origin/main' into feat/share-resolver
ScriptedAlchemy Oct 8, 2025
edc4550
Revert "Merge remote-tracking branch 'origin/main' into feat/share-re…
ScriptedAlchemy Oct 8, 2025
a36af48
test: consolidate SharePlugin suite
ScriptedAlchemy Oct 8, 2025
6364503
Merge remote-tracking branch 'origin/main' into feat/share-resolver
ScriptedAlchemy Oct 8, 2025
978dc15
Merge remote-tracking branch 'origin/main' into feat/share-resolver
ScriptedAlchemy Oct 8, 2025
d160214
chore: merge main into feat/share-resolver
ScriptedAlchemy Oct 15, 2025
4b05c67
test: sync enhanced and bridge tests
ScriptedAlchemy Oct 15, 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
16 changes: 16 additions & 0 deletions .changeset/fix-alias-aware-consume-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@module-federation/enhanced': patch
---

fix(enhanced): ConsumeSharedPlugin alias-aware and virtual resource handling

- Skip `data:` (virtual) resources in `afterResolve` and `createModule` so webpack's scheme resolver handles them (fixes container virtual-entry compile failure)
- Broaden alias-aware matching in `afterResolve` to include deep-path shares that start with the resolved package name (e.g. `next/dist/compiled/react`), ensuring aliased modules are consumed from federation when configured
- Avoid converting explicit relative/absolute requests into consumes to preserve local nested resolution (fixes deep module sharing version selection)
- Keep prefix and node_modules suffix matching intact; no behavior change there

These changes restore expected behavior for:
- Virtual entry compilation
- Deep module sharing (distinct versions for nested paths)
- Alias-based sharing (Next.js compiled React)

4 changes: 2 additions & 2 deletions .github/workflows/e2e-manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ jobs:

- name: E2E Test for Manifest Demo Development
if: steps.check-ci.outcome == 'success'
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=2 && npx kill-port 3013 3009 3010 3011 3012 4001
run: node tools/scripts/run-manifest-e2e.mjs --mode=dev

- name: E2E Test for Manifest Demo Production
if: steps.check-ci.outcome == 'success'
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
run: node tools/scripts/run-manifest-e2e.mjs --mode=prod
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ apps/**/dist
**/cypress/downloads

# test cases
!packages/enhanced/test/configCases/**/**/node_modules
packages/enhanced/test/js
.ignored
**/.mf
Expand Down Expand Up @@ -89,3 +88,9 @@ vitest.config.*.timestamp*
ssg
.claude
__mocks__/

# test mock modules
# Keep ALL test configCases node_modules (and all nested files) tracked,
# so we don't need per-path exceptions like next/dist.
!packages/enhanced/test/configCases/**/node_modules/
!packages/enhanced/test/configCases/**/node_modules/**
23 changes: 23 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# AGENTS.md - Module Federation Core Repository Guidelines

## Build/Test Commands
```bash
pnpm build # Build all packages (tag:type:pkg)
pnpm test # Run all tests via nx
pnpm lint # Lint all packages
pnpm lint-fix # Fix linting issues
pnpm nx run <pkg>:test # Test specific package
npx jest path/to/test.ts --no-coverage # Run single test file
```

## Code Style
- **Imports**: External → SDK/core → Local (grouped with blank lines)
- **Type imports**: `import type { ... }` explicitly marked
- **Naming**: camelCase functions, PascalCase classes, SCREAMING_SNAKE constants
- **Files**: kebab-case or PascalCase for class files
- **Errors**: Use `@module-federation/error-codes`, minimal try-catch
- **Comments**: Minimal, use `//` inline, `/** */` for deprecation
- **Async**: Named async functions for major ops, arrow functions in callbacks
- **Exports**: Named exports preferred, barrel exports in index files
- **Package manager**: ALWAYS use pnpm, never npm
- **Parallelization**: Break tasks into 3-10 parallel subtasks minimum
1 change: 1 addition & 0 deletions nx.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"useDaemonProcess": false,
"targetDefaults": {
"build": {
"inputs": ["production", "^production"],
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"name": "module-federation",
"version": "0.0.0",
"engines": {
"node": "^18",
"pnpm": "^8.11.0"
},
"packageManager": "[email protected]",
Expand Down Expand Up @@ -38,7 +37,7 @@
"build:website": "nx run website-new:build",
"extract-i18n:website": "nx run website:extract-i18n",
"sync:pullMFTypes": "concurrently \"node ./packages/enhanced/pullts.js\"",
"app:next:dev": "nx run-many --target=serve --configuration=development -p 3000-home,3001-shop,3002-checkout",
"app:next:dev": "NX_TUI=false nx run-many --target=serve --configuration=development -p 3000-home,3001-shop,3002-checkout",
"app:next:build": "nx run-many --target=build --parallel=2 --configuration=production -p 3000-home,3001-shop,3002-checkout",
"app:next:prod": "nx run-many --target=serve --configuration=production -p 3000-home,3001-shop,3002-checkout",
"app:node:dev": "nx run-many --target=serve --parallel=10 --configuration=development -p node-host,node-local-remote,node-remote,node-dynamic-remote-new-version,node-dynamic-remote",
Expand Down
1 change: 1 addition & 0 deletions packages/bridge/bridge-react/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export default defineConfig({
external: [
...perDepsKeys,
'@remix-run/router',
'react-error-boundary',
/react-dom\/.*/,
'react-router',
'react-router-dom/',
Expand Down
1 change: 1 addition & 0 deletions packages/enhanced/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"@types/btoa": "^1.2.5",
"ajv": "^8.17.1",
"enhanced-resolve": "^5.0.0",
"memfs": "^4.36.0",
"terser": "^5.37.0"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ export type ConsumeOptions = {
*/
include?: ConsumeSharedModuleIncludeOptions;
/**
* Enable reconstructed lookup for node_modules paths for this share item
* Allow matching against path suffix after node_modules for this share item
*/
nodeModulesReconstructedLookup?: boolean;
allowNodeModulesSuffixMatch?: boolean;
};
const TYPES = new Set(['consume-shared']);
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ export interface ConsumeSharedPluginOptions {
* Share scope name used for all consumed modules (defaults to 'default').
*/
shareScope?: string | string[];
/**
* Experimental features configuration.
*/
experiments?: {
/** Enable alias-aware consuming via NormalModuleFactory.afterResolve (experimental). */
aliasConsumption?: boolean;
};
}
/**
* Modules that should be consumed from share scope. Property names are used to match requested modules in this compilation. Relative requests are resolved, module requests are matched unresolved, absolute paths will match resolved requests. A trailing slash will match all requests with this prefix. In this case shareKey must also have a trailing slash.
Expand Down Expand Up @@ -92,5 +99,5 @@ export interface ConsumesConfig {
request?: string;
exclude?: IncludeExcludeOptions;
include?: IncludeExcludeOptions;
nodeModulesReconstructedLookup?: boolean;
allowNodeModulesSuffixMatch?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ export interface ProvidesConfig {
*/
include?: IncludeExcludeOptions;
/**
* Node modules reconstructed lookup.
* Allow matching against path suffix after node_modules.
*/
nodeModulesReconstructedLookup?: any;
allowNodeModulesSuffixMatch?: any;
/**
* Original prefix for prefix matches (internal use).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ export interface SharePluginOptions {
* Modules that should be shared in the share scope. When provided, property names are used to match requested modules in this compilation.
*/
shared: Shared;
/**
* Experimental features configuration.
*/
experiments?: {
/** Enable alias-aware consuming via NormalModuleFactory.afterResolve (experimental). */
aliasConsumption?: boolean;
};
}
/**
* Modules that should be shared in the share scope. Property names are used to match requested modules in this compilation. Relative requests are resolved, module requests are matched unresolved, absolute paths will match resolved requests. A trailing slash will match all requests with this prefix. In this case shareKey must also have a trailing slash.
Expand Down Expand Up @@ -96,9 +103,9 @@ export interface SharedConfig {
*/
include?: IncludeExcludeOptions;
/**
* Node modules reconstructed lookup.
* Allow matching against path suffix after node_modules.
*/
nodeModulesReconstructedLookup?: boolean;
allowNodeModulesSuffixMatch?: boolean;
}

export interface IncludeExcludeOptions {
Expand Down
11 changes: 9 additions & 2 deletions packages/enhanced/src/lib/container/ModuleFederationPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ class ModuleFederationPlugin implements WebpackPluginInstance {
(new RemoteEntryPlugin(options) as unknown as WebpackPluginInstance).apply(
compiler,
);

// Do not use process.env for alias consumption; flag is forwarded via options
if (options.experiments?.provideExternalRuntime) {
if (options.exposes) {
throw new Error(
Expand Down Expand Up @@ -212,10 +214,15 @@ class ModuleFederationPlugin implements WebpackPluginInstance {
}).apply(compiler);
}
if (options.shared) {
new SharePlugin({
// Build SharePlugin options and pass through aliasConsumption directly
const shareOpts = {
shared: options.shared,
shareScope: options.shareScope,
}).apply(compiler);
experiments: {
aliasConsumption: options.experiments?.aliasConsumption,
},
};
new SharePlugin(shareOpts).apply(compiler);
}
});

Expand Down
Loading