core icon indicating copy to clipboard operation
core copied to clipboard

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

Open sbvice opened this issue 1 year ago • 11 comments

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

  • [X] Read the Contributing Guidelines.
  • [X] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.

sbvice avatar Sep 18 '24 21:09 sbvice

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

2heal1 avatar Sep 20 '24 02:09 2heal1

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

sbvice avatar Oct 03 '24 20:10 sbvice

@sbvice @2heal1 Hi. Any updates here?

corbie1 avatar Dec 02 '24 08:12 corbie1

Hey @ScriptedAlchemy would you like me to re-open the PR? Have you had an opportunity to look at the example I shared?

sbvice avatar Dec 02 '24 21:12 sbvice

Yeah let's re open the pr

ScriptedAlchemy avatar Dec 03 '24 01:12 ScriptedAlchemy

@ScriptedAlchemy It doesn't look like I can re-open. You might be able to do that. I can create a new PR -- I do need to rebase the changes and update documentation in zh too. So I can do that and create a new PR tomorrow if you'd like.

sbvice avatar Dec 03 '24 01:12 sbvice

Reopened

ScriptedAlchemy avatar Dec 03 '24 06:12 ScriptedAlchemy

Is there any workaround for this at the moment while we wait for the merge

econneely avatar Dec 11 '24 12:12 econneely

@econneely

I've been working basically without the DTS feature for now (similar to what MF1 had), where I will either have stubbed .d.ts files, or I'll pull the remote also as an npm dependency just to use the types.

If you want to use the DTS feature there are a few options that might work for you:

  1. Set up a separate webpack or rspack configuration with absolute remotes that you run first. Unless you are testing live type changes where you are coding on the remote as you re also coding on the host, you really only need one run to generate the @mf-types folder.
  2. Depending on your setup, you may have a well-defined host for the environments that need the types (usually an alpha, beta, or staging environment) for build pipelines and such. In those environments you could have a configuration or environment variable that you use for your base URL. Something like:
// rsbuild.config.ts
const remoteBase = process.env.REMOTE_BASE ?? '';
export default defineConfig({
	plugins: [
		pluginModuleFederation({
			name: 'host',
			remotes: {
				'buttons': `buttons@${remoteBase}/module/buttons/mf-manifest.json`
			}
		}),
	],
});

sbvice avatar Dec 12 '24 21:12 sbvice

Stale issue message

github-actions[bot] avatar Feb 11 '25 15:02 github-actions[bot]

Hey @ScriptedAlchemy @2heal1,

I've had a fix ready to go for a while on this one, including an example repo all set up for review. It seems like there is community consensus that this would be a valuable improvement. Please let me know if you agree and if we can move forward with the change.

sbvice avatar Feb 11 '25 17:02 sbvice

Stale issue message

github-actions[bot] avatar Apr 14 '25 15:04 github-actions[bot]