-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Document webpack change: Versioned shared modules for Module Federation #3757
Comments
should update on webpack.js.org |
Looking forward to proper API documentation for MF 🐶 |
Just to be sure - in case of a shared module is not marked as a singleton and the version of the module is the same at all of the modules, the shared module will be loaded only once? |
@zshlomyz Yes. And warnings will pop up if a different version is requested by any dependency. (Not sure how it is resolved in that case though.) |
how to make shared modules "eager"? |
A pull request by @sokra was merged and maintainers requested a documentation change.
See pull request: webpack/webpack#10960
This PR brings Module Federation to a whole new level. It's a complete reimplementation and redesign of the shared modules.
TL;DR:
shared
modules are now based on versions.Before this PR hosts were able to override (overridable) modules of remotes.
Hosts always had priority and 2 remotes could only share modules if the host shares it to both.
That wasn't that bad. The control was clear from host to remote.
But there were weird cases with circular host remote relationships or multiple hosts using the same remote, which allowed to break the control direction.
The system had holes...
After all I think it's best break with the old system in favor of a different approach.
The new system is based on versions of shared modules.
In group of federated builds all parts will agree on the highest version of a shared module.
On the other hand the version of the shared module will be checked against a version requirement based on semver (lite).
If allowed, multiple versions of a shared module might exist and will be consumed based on the required version.
This allows remotes to provide a higher version of a shared module to the federated app.
It also allows two remotes to share a module without the host being involved into that.
And it allows to share two different (major) version of a module, while still reusing compatible versions.
In this end remotes get more decoupled from the host and upgrade to a higher dependency version alone.
There is a singleton mode for shared modules, in which only a single version of the shared module is allowed. This version can be provided from any remote of the application. It might be a deep nested remote that requires a higher version of the shared module. This one would be used for the whole app.
You might choose to only consume a shared module, but don't provide one.
This can make sense to reduce build time and deploy size when the container is always used within a shell that provides these shared modules. E.g. for framework parts.
You can choose between strict and loose version checking for each shared module.
In strict mode a shared module won't be used if the version is not in valid range. If a fallback is provided this will be used instead.
In loose mode shared module will always used, but a warning will be printed. Fallback will only be used when no shared module is available.
When a fallback module is provided strict is the safest choice. It's also the default in this case.
When no fallback module is available, loose mode is the default, as it would thow an error otherwise.
Strict mode can still make sense for modules without fallback, if you have code in place to handle these errors.
You can make shared modules "eager", which doesn't put the modules in a async chunk, but provides them synchronously.
This allows to use these shared modules in the initial chunk. But be careful as all provided and fallback modules will always be downloaded.
There it's wise to provide it only at one point of your app, e. g. the shell.
It's still a valid a approach to wrap your entry point with
import("./bootstrap")
. When doing so, make sure to inline the entry chunk into the HTML for best performance (no double round trip).This is now the recommended approach. The old "fix" no longer works as remotes could provide shared modules to the app, which requires an async step before using shared modules.
Maybe we provide some flag for the entry option in future to do this automatically.
There is an initialization phase in which all remotes (and remotes of remotes) have the chance to provide shared modules.
That means once you want to use the first shared module, this will load all remotes (if they are async loaded).
This is important as some deep nested remote might need a higher version of a shared module and it need to have a chance to provide it.
It's possible to have multiple share scopes in which modules are shared. Not sure about a use case for that yet, but it might be handy in future.
For now it's fine to always go with the default share shope.
The container interface has been changed to
get
andinit
.init
is an possible async method that is called with one argument: the share scope object. This object is used as share scope in the container and is filled with the provided modules.To dynamically use a container:
The container might try to provide shared modules, but if the shared module has already been used this will result in a warning and the provided shared module will be ignored. The container might still use it as fallback.
The same way you could dynamically load an A/B test, which provides some newer versions of a shared module.
Examples:
For
requiredVersion
:^
,~
,>=
and exact matching is allowed. Complex ranges are not supported as it would required a significat amount of runtime code to cover that logic.What kind of change does this PR introduce?
feature, refactoring
Did you add tests for your changes?
yes
Does this PR introduce a breaking change?
yes
What needs to be documented once your changes are merged?
a lot about shared modules in module federation, see above
The text was updated successfully, but these errors were encountered: