-
-
Notifications
You must be signed in to change notification settings - Fork 314
feat(enhanced): add request to consume share #3307
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 all commits
c79b694
23c9252
8e77126
104785a
76b53ca
9671885
92cebbb
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 |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@module-federation/enhanced': minor | ||
--- | ||
|
||
support request option on ConsumeSharePlugin. Allows matching requests like the object key of shared does |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,8 @@ | |
import { normalizeWebpackPath } from '@module-federation/sdk/normalize-webpack-path'; | ||
import type { Compilation } from 'webpack'; | ||
import type { ResolveOptionsWithDependencyType } from 'webpack/lib/ResolverFactory'; | ||
import type { SemVerRange } from 'webpack/lib/util/semver'; | ||
import type { ConsumeOptions } from './ConsumeSharedModule'; | ||
|
||
const ModuleNotFoundError = require( | ||
normalizeWebpackPath('webpack/lib/ModuleNotFoundError'), | ||
|
@@ -13,6 +15,9 @@ const LazySet = require( | |
normalizeWebpackPath('webpack/lib/util/LazySet'), | ||
) as typeof import('webpack/lib/util/LazySet'); | ||
|
||
const RELATIVE_REQUEST_REGEX = /^\.\.?(\/|$)/; | ||
const ABSOLUTE_PATH_REGEX = /^(\/|[A-Za-z]:\\|\\\\)/; | ||
|
||
interface MatchedConfigs<T> { | ||
resolved: Map<string, T>; | ||
unresolved: Map<string, T>; | ||
|
@@ -23,7 +28,19 @@ const RESOLVE_OPTIONS: ResolveOptionsWithDependencyType = { | |
dependencyType: 'esm', | ||
}; | ||
|
||
export async function resolveMatchedConfigs<T>( | ||
function createCompositeKey(request: string, config: ConsumeOptions): string { | ||
if (config.issuerLayer) { | ||
return `(${config.issuerLayer})${request}`; | ||
// layer unlikely to be used, issuerLayer is what factorize provides | ||
// which is what we need to create a matching key for | ||
} else if (config.layer) { | ||
return `(${config.layer})${request}`; | ||
} else { | ||
return request; | ||
} | ||
} | ||
// TODO: look at passing dedicated request key instead of infer from object key | ||
export async function resolveMatchedConfigs<T extends ConsumeOptions>( | ||
compilation: Compilation, | ||
configs: [string, T][], | ||
): Promise<MatchedConfigs<T>> { | ||
|
@@ -35,28 +52,26 @@ export async function resolveMatchedConfigs<T>( | |
contextDependencies: new LazySet<string>(), | ||
missingDependencies: new LazySet<string>(), | ||
}; | ||
// @ts-ignore | ||
const resolver = compilation.resolverFactory.get('normal', RESOLVE_OPTIONS); | ||
const context = compilation.compiler.context; | ||
|
||
await Promise.all( | ||
//@ts-ignore | ||
configs.map(([request, config]) => { | ||
if (/^\.\.?(\/|$)/.test(request)) { | ||
const resolveRequest = config.request || request; | ||
if (RELATIVE_REQUEST_REGEX.test(resolveRequest)) { | ||
// relative request | ||
return new Promise<void>((resolve) => { | ||
resolver.resolve( | ||
{}, | ||
context, | ||
request, | ||
resolveRequest, | ||
resolveContext, | ||
(err, result) => { | ||
if (err || result === false) { | ||
err = err || new Error(`Can't resolve ${request}`); | ||
err = err || new Error(`Can't resolve ${resolveRequest}`); | ||
compilation.errors.push( | ||
// @ts-ignore | ||
new ModuleNotFoundError(null, err, { | ||
name: `shared module ${request}`, | ||
name: `shared module ${resolveRequest}`, | ||
}), | ||
); | ||
return resolve(); | ||
|
@@ -66,15 +81,20 @@ export async function resolveMatchedConfigs<T>( | |
}, | ||
); | ||
}); | ||
} else if (/^(\/|[A-Za-z]:\\|\\\\)/.test(request)) { | ||
} else if (ABSOLUTE_PATH_REGEX.test(resolveRequest)) { | ||
// absolute path | ||
resolved.set(request, config); | ||
} else if (request.endsWith('/')) { | ||
resolved.set(resolveRequest, config); | ||
return undefined; | ||
} else if (resolveRequest.endsWith('/')) { | ||
// module request prefix | ||
prefixed.set(request, config); | ||
const key = createCompositeKey(resolveRequest, config); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. with the request param, i can now support prefix shared etc without a problem |
||
prefixed.set(key, config); | ||
return undefined; | ||
} else { | ||
// module request | ||
unresolved.set(request, config); | ||
const key = createCompositeKey(resolveRequest, config); | ||
unresolved.set(key, config); | ||
return undefined; | ||
} | ||
}), | ||
); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/** | ||
* Loader that injects the multi-pkg layer name as an export | ||
*/ | ||
module.exports = function multiPkgLayerLoader(source) { | ||
return [source, 'export const layer = "multi-pkg-layer";'].join('\n'); | ||
}; |
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 |
---|---|---|
@@ -1,6 +1,7 @@ | ||
/** | ||
* Main test entry point | ||
*/ | ||
import '../tests/layer-inheritance.test'; | ||
import '../tests/unlayered-share.test'; | ||
import '../tests/different-layers.test'; | ||
import '../tests/lib-two.test'; | ||
import '../tests/prefixed-share.test'; |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/** | ||
* Tests for lib-two module sharing with lib-two-required-layer configurations | ||
*/ | ||
|
||
it('should consume lib-two v1.3.4 from lib-two-required-layer with eager loading', async () => { | ||
const { version, layer } = await import('lib-two'); | ||
expect(version).toBe('1.3.4'); | ||
expect(layer).toBe('differing-layer'); // Using the layer from different-layer-loader | ||
}); | ||
|
||
it('should consume lib-two-layered v1.3.4 from lib-two-required-layer with eager loading', async () => { | ||
const { version, layer } = await import('lib-two-layered'); | ||
expect(version).toBe('1.3.4'); | ||
expect(layer).toBe('differing-layer'); // Using the layer from different-layer-loader | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* Tests for prefixed module sharing with different layers | ||
*/ | ||
it('should consume thing1 from multi-pkg with multi-pkg-layer', async () => { | ||
const { version, layer } = await import('multi-pkg/thing1'); | ||
expect(version).toBe('2.0.0'); | ||
expect(layer).toBe('multi-pkg-layer'); | ||
}); | ||
|
||
it('should consume thing2 from multi-pkg with multi-pkg-layer', async () => { | ||
const { version, layer } = await import('multi-pkg/thing2'); | ||
expect(version).toBe('2.0.0'); | ||
expect(layer).toBe('multi-pkg-layer'); | ||
}); |
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.
used for when there is no layer etc,