Skip to content
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

rspack module federation not firing onLoad and other hooks when exposed modules from other remotes are loaded #2537

Open
5 tasks done
MadaraUchiha-314 opened this issue May 23, 2024 · 13 comments

Comments

@MadaraUchiha-314
Copy link
Contributor

Describe the bug

rspack rewrites the import for an exposed module from a remote to a static import rather than a dynamic import using loadRemote

This is causing 2 issues:

  1. The lifecycle hooks like onLoad and other hooks are not triggered for the exposed modules loaded
  2. Once the parent remote entry is loaded, all child remote entries are loaded by default because they are static imports and not dynamic.
    • This is a cause of concern as it has serious performance impact for large projects

Example:

I have 2 remotes:

  • project-a
  • project-b

project-a imports the button (which is an exposed module) from project-b.

import Button, { someThingElse } from 'project-b/button';

rspack converts it to this:

import * as __WEBPACK_EXTERNAL_MODULE_webpack_container_reference_project_b__ from 'https://rollup-plugin-module-federation-project-b.vercel.app/rspack/esm/my-remote-entry.js';

My rollup plugin rollup-plugin-module-federation converts it to:

const Button = (await loadRemote('project-b/button')).default;
const { someThingElse } = (await loadRemote('project-b/button'));

My implementation fixes both the bugs I mentioned above.

  1. Since exposed modules are loaded using loadRemote it fires all the hooks
  2. Since the exposed module is actually loaded only when it's required, it doesn't trigger additional network calls when the remote for project-a is loaded

Working example:

Just click on the buttons from left to right and check the console logs and the network tabs.

Reproduction

Provided above.

Used Package Manager

npm

System Info

NA

Validations

@zhoushaw
Copy link
Collaborator

I may not understand what you mean, do you mean that the resource is loaded repeatedly when the following dependencies: host -> remote-a -> remote-b, should not be added to the remote-b resource when loading remote-a @MadaraUchiha-314

@MadaraUchiha-314
Copy link
Contributor Author

I may not understand what you mean, do you mean that the resource is loaded repeatedly when the following dependencies: host -> remote-a -> remote-b, should not be added to the remote-b resource when loading remote-a @MadaraUchiha-314

Yes, that's one of the issue.

the other issue is that rspack internally doesn't use loadRemote, it just does a regular import of the remote.

@ScriptedAlchemy
Copy link
Member

@MadaraUchiha-314 hoe are you configuring the remote? Rspack seems to be inlining the external url for import from. Can you share the Rspack build config

@MadaraUchiha-314
Copy link
Contributor Author

@ScriptedAlchemy
Copy link
Member

@MadaraUchiha-314 does webpack handle the same?
@zhoushaw @2heal1 how do we implement esm mode for federation in VMOK?

It seems that bundler will use esm http external imports for remoteType module

@MadaraUchiha-314
Copy link
Contributor Author

@MadaraUchiha-314 does webpack handle the same?

Webpack also handles it the same way that rspack does. Direct import like:

import*as __WEBPACK_EXTERNAL_MODULE_http_localhost_8080_packages_examples_project_b_dist_webpack_esm_my_remote_entry_js_46592bd8__ from "http://localhost:8080/packages/examples/project-b/dist/webpack/esm/my-remote-entry.js";

@MadaraUchiha-314
Copy link
Contributor Author

@ScriptedAlchemy Another bug that's happening due to this raw import is that when I use the mf-manifest.json to refer to a remote entry rather than the direct url, the import is something like:

import * as __WEBPACK_EXTERNAL_MODULE_webpack_container_reference_project_b__ from "http://localhost:8080/packages/examples/project-b/dist/rspack/esm/mf-manifest.json";

and I am getting the error:

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/json". Strict MIME type checking is enforced for module scripts per HTML spec.

Reproducible URL: https://rollup-plugin-module-federation.netlify.app/packages/examples/project-a/dist/rspack/esm/

This means that federation 2.0 in rspack using ESM and mf-manifest.json just doesn't work!!

I think having these raw HTTP imports to externals is not the right design.

In my rollup federation, I convert these to loadRemote calls and let the federation runtime handle things and it works perfectly!

@ScriptedAlchemy
Copy link
Member

Use remotetype: 'script' in the plugin

Also why use esm outputs vs normal js?

Copy link
Contributor

github-actions bot commented Sep 7, 2024

Stale issue message

@MadaraUchiha-314
Copy link
Contributor Author

IMO both of these issues are still existing.

  1. The 1st issue of the onLoad hook firing is a critical one and needs to be addressed.
  2. The 2nd issue of the remote entry being static imports is an implementation detail but would be good to get fixed as otherwise there's no way to resolve issue-1

@ScriptedAlchemy LMK if this issue can be prioritized. This is blocking adoption of rspack + ESM (for SSR purposes) in our enterprise.

@ScriptedAlchemy
Copy link
Member

It requires the creation of new module types. Currently, both depend on ExternalModule. I'll have to either update the external module and everything related to externals, or I need to make a new module type.

Either way, this requires core changes that will have to be implemented into webpack, then rspack.

The best alternative is to treat remoteType as a script and use a runtime plugin to handle loading the entry via esm or some custom runtime.

Copy link
Contributor

Stale issue message

@ScriptedAlchemy
Copy link
Member

Workarounds exist. Treating the remote as type script still and using a runtime plugin to use import() on loadEntry should suffice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants