diff --git a/.changeset/pretty-dragons-destroy.md b/.changeset/pretty-dragons-destroy.md new file mode 100644 index 000000000..678f4c646 --- /dev/null +++ b/.changeset/pretty-dragons-destroy.md @@ -0,0 +1,5 @@ +--- +"@callstack/repack": patch +--- + +Fix handling of MF2 remote assets paths in ResolverPlugin diff --git a/packages/repack/src/modules/FederationRuntimePlugins/ResolverPlugin.ts b/packages/repack/src/modules/FederationRuntimePlugins/ResolverPlugin.ts index 49792f16e..ea9787146 100644 --- a/packages/repack/src/modules/FederationRuntimePlugins/ResolverPlugin.ts +++ b/packages/repack/src/modules/FederationRuntimePlugins/ResolverPlugin.ts @@ -20,8 +20,7 @@ const createScriptLocator = async ( }; const getPublicPath = (url: string) => { - const [protocol, rest] = url.split('://'); - return protocol + '://' + rest.split('/')[0]; + return url.split('/').slice(0, -1).join('/'); }; const getAssetPath = (url: string) => { diff --git a/packages/repack/src/modules/FederationRuntimePlugins/__tests__/ResolverPlugin.test.ts b/packages/repack/src/modules/FederationRuntimePlugins/__tests__/ResolverPlugin.test.ts index 7abc6ae60..8476c04b9 100644 --- a/packages/repack/src/modules/FederationRuntimePlugins/__tests__/ResolverPlugin.test.ts +++ b/packages/repack/src/modules/FederationRuntimePlugins/__tests__/ResolverPlugin.test.ts @@ -67,7 +67,7 @@ describe('RepackResolverPlugin', () => { ); expect(script.locator.url).toBe( - 'https://example-manifest.com/remoteEntry.js' + 'https://example-manifest.com/remote1/remoteEntry.js' ); }); @@ -86,7 +86,9 @@ describe('RepackResolverPlugin', () => { 'https://example-entry.com/remoteEntry.js' ); - expect(script.locator.url).toBe('https://example-entry.com/remoteEntry.js'); + expect(script.locator.url).toBe( + 'https://example-entry.com/remote1/remoteEntry.js' + ); }); it('should allow custom configuration when used in runtime with a config object', async () => { @@ -152,11 +154,11 @@ describe('RepackResolverPlugin', () => { 'chunk1', 'remote1', webpackRequireMock, - 'https://example-entry.com/remote1/assets/nested/chunk1.js' + 'https://example-entry.com/remote1/assets/chunk1.js' ); expect(script.locator.url).toBe( - 'https://example-manifest.com/remote1/assets/nested/chunk1.js' + 'https://example-manifest.com/remote1/chunk1.js' ); expect(script.locator.headers).toEqual({ authorization: 'Bearer token' }); expect(script.locator.fetch).toBe(true); @@ -184,18 +186,37 @@ describe('RepackResolverPlugin', () => { it('should rebase the URL from reference URL to entry URL', async () => { const plugin = RepackResolverPlugin(); // trigger the plugin to register the resolver - plugin.afterResolve!({ remoteInfo: mockRemoteInfo } as any); + plugin.afterResolve!({ + remoteInfo: { + name: 'remote1', + entry: 'https://example.com/ios/remote1/entry.container.js.bundle', + version: 'https://example-manifest.com/remote1/mf-manifest.json', + }, + } as any); // manually resolve the script to verify the result - const script = await ScriptManager.shared.resolveScript( + const script1 = await ScriptManager.shared.resolveScript( + 'remote1', + undefined, + webpackRequireMock, + 'https://example.com/ios/remote1/entry.container.js.bundle' + ); + + // container entry is expected to be at the same level as manifest + expect(script1.locator.url).toBe( + 'https://example-manifest.com/remote1/entry.container.js.bundle' + ); + + const script2 = await ScriptManager.shared.resolveScript( 'asset', 'remote1', webpackRequireMock, - 'https://example-entry.com/remote1/subdir/asset.js' + 'http://localhost:8081/ios/remote1/asset.js' ); - expect(script.locator.url).toBe( - 'https://example-manifest.com/remote1/subdir/asset.js' + // all other assets are expected to be at the same level as manifest + expect(script2.locator.url).toBe( + 'https://example-manifest.com/remote1/asset.js' ); }); });