module-federation / core

Module Federation is a concept that allows developers to share code and resources across multiple JavaScript applications
https://module-federation.io/
MIT License
1.54k stars 240 forks source link

Add option to supply a base path when resolving types from relative remote urls #2963

Open sbvice opened 2 months ago

sbvice commented 2 months ago

Clear and concise description of the problem

I would like a way to specify the absolute url of remotes for type generation, but use a relative path to resolve the module at runtime. Relative remote paths allow for simpler configuration for domain agnostic deployments across dev and prod environments. Unfortunately without specifying the absolute URL the dts-plugin does not know where to grab the types.

For example a host may have the following remote configuration:

MyRemote: 'MyRemote@/relative-path/mf-manifest.json'

Loading the host app up under http://localhost:3000 would correctly resolve the relative path as http://localhost:3000/relative-path/mf-manifest.json. However the dts-plugin will try to load the types directly from the relative path and fails with this warning found in typesGenerate.log

[ERROR] downloadTypesArchive - Error during types archive download: Network error: Unable to download federated mocks for 'MyRemote' from '/relative-path/@mf-types.zip' because 'Invalid URL'

Suggested solution

One solution could be to add a new configuration option to the DtsHostOptions in the sdk package:

export interface DtsHostOptions {
  //...
  /**
   * Used as the default base path for relative remote URLs when locating types
   */
  remoteBasePath?: string;
}

We would use this option as the base path whenever we are supplied a relative remote in the dts-plugin package:

const fileBase = 'file:';

const defaultOptions = {
  //...
  remoteBasePath: fileBase,
} satisfies Partial<HostOptions>;

const resolveRelativeUrl = (
  hostOptions: Required<HostOptions>,
  entryUrl: string,
) => {
  const remoteUrl = new URL(entryUrl, hostOptions.remoteBasePath);
  return remoteUrl.protocol === fileBase ? remoteUrl.pathname : remoteUrl.href;
};

Alternative

An alternative could be to leverage the host's publicPath and or the getPublicPath function. I'm not sure this would be the correct application of those features.

Additional context

This is a similar use-case outlined by @adamdharrington and partially solved in https://github.com/module-federation/core/issues/2406

I also know I did this backwards, but I have a WIP implementation available for more context.

Validations

2heal1 commented 2 months ago

looks nice , since you have known how to fix it , can you help to open a pr ?

sbvice commented 1 month ago

You bet. https://github.com/module-federation/core/pull/3042