Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
it('should be able to handle spaces in path to exposes', async () => {
const { default: test1 } = await import('./test 1');
const { default: test2 } = await import('./path with spaces/test-2');
expect(test1()).toBe('test 1');
expect(test2()).toBe('test 2');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function test() {
return 'test 2';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function test() {
return 'test 1';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const { ModuleFederationPlugin } = require('../../../../dist/src');

module.exports = {
mode: 'development',
devtool: false,
output: {
publicPath: 'http://localhost:3000/',
},
plugins: [
new ModuleFederationPlugin({
name: 'remote',
filename: 'remoteEntry.js',
manifest: true,
exposes: {
'./test-1': './test 1.js',
'./test-2': './path with spaces/test-2.js',
},
}),
],
};
20 changes: 19 additions & 1 deletion packages/manifest/src/ModuleHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,25 @@ class ModuleHandler {
// identifier: container entry (default) [[".",{"import":["./src/routes/page.tsx"],"name":"__federation_expose_default_export"}]]'
const data = identifier.split(' ');

JSON.parse(data[3]).forEach(([prefixedName, file]) => {
let entries: Array<
[exposeKey: string, { import: string[]; name?: string }]
> = [];

try {
// Prefer parsing exposes from stats first
entries = JSON.parse(data[3]);
} catch {
// If that fails, fallback to the original options
const exposes = this._options.exposes;

if (!exposes || typeof exposes !== 'object') {
return;
}

entries = Object.entries(exposes);
}

entries.forEach(([prefixedName, file]) => {
// TODO: support multiple import
exposesMap[getFileNameWithOutExt(file.import[0])] = getExposeItem({

Choose a reason for hiding this comment

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

[P1] Normalize fallback exposes before accessing import

When JSON parsing of identifier fails, the code falls back to this._options.exposes and iterates the entries assuming each value already looks like { import: [...] }. For typical module federation configs the values are plain strings (e.g. exposes: { './foo': './foo.js' }), so file is a string and file.import[0] throws, causing the Stats plugin to crash in the same spaces-in-path scenario this change is supposed to fix. The fallback needs to normalize string/array expose definitions into an object with an import array (or skip them) before dereferencing file.import.

Useful? React with 👍 / 👎.

Copy link
Member Author

Choose a reason for hiding this comment

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

@codex fix this

Choose a reason for hiding this comment

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

Summary

Testing

  • pnpm exec jest --config packages/manifest/jest.config.js

View task →

exposeKey: prefixedName,
Expand Down
Loading