-
-
Notifications
You must be signed in to change notification settings - Fork 370
fix(enhanced): Populate buildMeta
and buildInfo
on ConsumeSharedPlugin
using fallbacks
#4038
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
4af58aa
bcaa36a
a22e8e1
6ca32b9
12c245d
897cd53
4f880bf
be65c3c
3f232aa
adcb5aa
cd1631f
8e6a8b0
74566c5
ad4de40
6a82e0f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -181,11 +181,37 @@ class ConsumeSharedModule extends Module { | |
); | ||
if (this.options.eager) { | ||
this.addDependency(dep); | ||
// We'll need to get the module from the fallback dependency | ||
// later to copy its buildMeta and buildInfo | ||
vinicius-at-webflow marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} else { | ||
const block = new AsyncDependenciesBlock({}); | ||
block.addDependency(dep); | ||
this.addBlock(block); | ||
// Same here for async case | ||
vinicius-at-webflow marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
// We need to hook into the compilation process to copy metadata | ||
// after the fallback is fully built | ||
compilation.hooks.finishModules.tap('ConsumeSharedModule', () => { | ||
let dependency; | ||
|
||
if (this.options.eager) { | ||
// For eager mode, get the fallback directly | ||
dependency = this.dependencies[0]; | ||
} else { | ||
// For async mode, get it from the block | ||
dependency = this.blocks[0]?.dependencies[0]; | ||
} | ||
|
||
if (dependency) { | ||
const fallback = compilation.moduleGraph.getModule(dependency); | ||
if (fallback) { | ||
// Copy its buildMeta and buildInfo from fallback module | ||
vinicius-at-webflow marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
this.buildMeta = { ...fallback.buildMeta }; | ||
this.buildInfo = { ...fallback.buildInfo }; | ||
} | ||
} | ||
}); | ||
|
||
} | ||
callback(); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
it('should be able to consume nested modules', async () => { | ||
const { default: main } = await import('package-1'); | ||
expect(main('test')).toEqual('test package-1 package-2'); | ||
}); | ||
ScriptedAlchemy marked this conversation as resolved.
Show resolved
Hide resolved
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
ScriptedAlchemy marked this conversation as resolved.
Show resolved
Hide resolved
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"version": "1.0.0", | ||
"dependencies": { | ||
"package-2": "1.0.0", | ||
"package-1": "1.0.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const { ModuleFederationPlugin } = require('../../../../dist/src'); | ||
|
||
module.exports = { | ||
mode: 'development', | ||
devtool: false, | ||
plugins: [ | ||
new ModuleFederationPlugin({ | ||
name: 'consume-nested', | ||
filename: 'remoteEntry.js', | ||
shared: { | ||
'package-2': { version: '1.0.0' }, | ||
'package-1': { version: '1.0.0' }, | ||
}, | ||
}), | ||
], | ||
ScriptedAlchemy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -265,6 +265,17 @@ describe('ConsumeSharedModule', () => { | |
|
||
describe('build', () => { | ||
it('should add fallback dependency when import exists and eager=true', () => { | ||
const mockCompilation = { | ||
hooks: { | ||
finishModules: { | ||
tap: jest.fn(), | ||
}, | ||
}, | ||
moduleGraph: { | ||
getModule: jest.fn(), | ||
}, | ||
}; | ||
|
||
const module = new ConsumeSharedModule('/context', { | ||
...testModuleOptions.eager, | ||
import: './react', | ||
|
@@ -274,13 +285,30 @@ describe('ConsumeSharedModule', () => { | |
function buildCallback() { | ||
// Empty callback needed for the build method | ||
} | ||
module.build({} as any, {} as any, {} as any, {} as any, buildCallback); | ||
module.build( | ||
{} as any, | ||
mockCompilation as any, | ||
{} as any, | ||
{} as any, | ||
buildCallback, | ||
); | ||
|
||
expect(module.dependencies.length).toBe(1); | ||
expect(module.blocks.length).toBe(0); | ||
}); | ||
|
||
it('should add fallback in async block when import exists and eager=false', () => { | ||
const mockCompilation = { | ||
hooks: { | ||
finishModules: { | ||
tap: jest.fn(), | ||
}, | ||
}, | ||
moduleGraph: { | ||
getModule: jest.fn(), | ||
}, | ||
}; | ||
|
||
const module = new ConsumeSharedModule('/context', { | ||
...testModuleOptions.basic, | ||
import: './react', | ||
|
@@ -290,13 +318,30 @@ describe('ConsumeSharedModule', () => { | |
function buildCallback() { | ||
// Empty callback needed for the build method | ||
} | ||
module.build({} as any, {} as any, {} as any, {} as any, buildCallback); | ||
module.build( | ||
{} as any, | ||
mockCompilation as any, | ||
{} as any, | ||
{} as any, | ||
buildCallback, | ||
); | ||
|
||
expect(module.dependencies.length).toBe(0); | ||
expect(module.blocks.length).toBe(1); | ||
}); | ||
|
||
it('should not add fallback when import does not exist', () => { | ||
const mockCompilation = { | ||
hooks: { | ||
finishModules: { | ||
tap: jest.fn(), | ||
}, | ||
}, | ||
moduleGraph: { | ||
getModule: jest.fn(), | ||
}, | ||
}; | ||
|
||
const module = new ConsumeSharedModule('/context', { | ||
...testModuleOptions.basic, | ||
import: undefined, | ||
|
@@ -306,11 +351,68 @@ describe('ConsumeSharedModule', () => { | |
function buildCallback() { | ||
// Empty callback needed for the build method | ||
} | ||
module.build({} as any, {} as any, {} as any, {} as any, buildCallback); | ||
module.build( | ||
{} as any, | ||
mockCompilation as any, | ||
{} as any, | ||
{} as any, | ||
buildCallback, | ||
); | ||
|
||
expect(module.dependencies.length).toBe(0); | ||
expect(module.blocks.length).toBe(0); | ||
}); | ||
|
||
it('should copy buildMeta and buildInfo from fallback', () => { | ||
|
||
const mockFinishModulesHook = { | ||
tap: jest.fn(), | ||
}; | ||
|
||
const mockFallbackModule = { | ||
buildMeta: { testMeta: 'value' }, | ||
buildInfo: { testInfo: 'data' }, | ||
}; | ||
|
||
const mockCompilation = { | ||
hooks: { | ||
finishModules: mockFinishModulesHook, | ||
}, | ||
moduleGraph: { | ||
getModule: jest.fn().mockReturnValue(mockFallbackModule), | ||
}, | ||
}; | ||
|
||
const module = new ConsumeSharedModule('/context', { | ||
...testModuleOptions.eager, | ||
import: './react', | ||
} as any as ConsumeOptions); | ||
|
||
// Named callback function to satisfy linter | ||
function buildCallback() { | ||
// Empty callback needed for the build method | ||
} | ||
module.build( | ||
{} as any, | ||
mockCompilation as any, | ||
{} as any, | ||
{} as any, | ||
buildCallback, | ||
); | ||
|
||
// Verify the hook was tapped | ||
expect(mockFinishModulesHook.tap).toHaveBeenCalledWith( | ||
'ConsumeSharedModule', | ||
expect.any(Function), | ||
); | ||
|
||
// Simulate the hook being called | ||
const hookCallback = mockFinishModulesHook.tap.mock.calls[0][1]; | ||
hookCallback(); | ||
|
||
// Verify buildMeta and buildInfo were copied | ||
expect(module.buildMeta).toEqual({ testMeta: 'value' }); | ||
expect(module.buildInfo).toEqual({ testInfo: 'data' }); | ||
}); | ||
}); | ||
|
||
describe('codeGeneration', () => { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this hardcoded path really necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probbably not