loadable-components
loadable-components copied to clipboard
feat: add moduleFederation option
Summary
This PR was created to add support for Module Federation it is originated from this issue: https://github.com/gregberge/loadable-components/issues/926
It aims to add a new option to the loadabel babel-plugin called moduleFederation, it's a boolean option so we just need to set it to true to enable the support for Module Federation.
{
"plugins": [
["@loadable/babel-plugin", { "moduleFederation": true }],
// ...
]
// ...
}
This PR also adds some JSDoc typedefs to the plugin, which will help users to understand the plugin better.
Test plan
To test it you can clone the sample project using this branch as base for the test
The branch with our samples fixed https://github.com/brunos3d/loadable-module-federation-react-ssr/tree/demo-loadable-fix
The PR of the fixed branch to check the diff https://github.com/brunos3d/loadable-module-federation-react-ssr/pull/1
Per my understanding, the essence of this change is to disable code splitting for federation, not to "support" federation keeping the current constraints.
The question is how to ensure this configuration is used properly - only for server-side bundle.
woud we set a DefinePlugin like 'process.isBrowser' and if its false webpack could remove the dead code? Not sure if that would work or not
@theKashey yeah, your right about using it only on server-side, I will work to make it work as expected, don't have ideas on how we can make it
@theKashey just removed every unrelated change and forced push it to avoid overwriting the git history, I also removed the federated option, now we need to figure out how to ensure that it uses require(ID) only on server-side
👍 @brunos3d, now the change is short and sound.
Define Plugin stuff might now work, as long as in case of process.isBrowser is not defined it will be kept "as it", while we need condition to be removed to hide require from webpack.
What we can do - add a check for browser/clientside/webpack-target and ➡️ throw an error in case of misconfiguration. So not fail the build, but fail the runtime.
That would put customers without tests into a little dangerous situation, so we might also not document new property for now
@theKashey just added the suggested warnings. As I'm not too used to babel/webpack plugins I will ask you for code suggestions to solve this issue without workarounds :smile:
Hey, folks as we didn't find a proper way to pass the serverSideModuleFederation option from the LoadablePlugin (webpack) to babel, I just decide to inject the value to process using directly, as it will be used only during the compilation time, I can't see any problems on that solution. Excited to see your suggestions about it
cc: @theKashey @bwhitty @ScriptedAlchemy
@theKashey any input here - would be great to move this forwards if we can
Before we processed with the merge, I want to ask one question - Where is the best place to handle this stuff? Having the problem of "federation gap", ie one's inability to simply require yet undefined stuff, there are two options:
- make a sync require in the loadable (this PR). That would solve problem only for loadable and in a very specific way.
- preload all known components in the loadable (not which are not currently tracked)
- preload all federated sources via
ModuleFederationPlugin. Ie go via all known remotes and import them before starting a server
This does module federation for all modules. Should we do it as a option on loadable call?
This does module federation for all modules. Should we do it as a option on loadable call?
It does, but should be only used on the server-side, in the past I had put it as an option for the loadable function, it was a option called 'federated'. But the problem is, MF plugin changes the way imports happen even non-federated containers get these __webpack_modules__[moduleId] is not a function errors
So that is the question: if one technology should adapt to support another technology - could there be a third technology to change as well?
For example, @fivethreeo is working on React 18 update with a "proper suspense" on the server side - https://github.com/gregberge/loadable-components/pull/923 - which technically can allow us to use plain import without require.resolve
Proper suspense would work for everything moving forwards, but we would still need a solve for async-node target / lower react versions :P
@theKashey @ScriptedAlchemy An issue we're facing right now is when we try to consume a container from some remote using loadable and the remote is down, MF tries to generate a fake remote and a fake container, but loadable throws multiple errors saying that the provided module is not a react component (cause it's an empty object), an a bunch of other errors.




By now I'm using the following workaround for local linked and patched @loadable/component
// on InnerLoadable component at the top of the "render" function
if (result && typeof result === 'object' && Object.keys(result).length === 0) {
console.log('probably the fake container')
result = `<span>failed to load remote container</span>`
}
// ...
It checks if the result (the loaded/resolved module) is not undefined and verifies if its an empty object (the fake container generated by MF) then it replaces it with the warning message
There is a resolveComponent option you can provide to loadable, and the one capable to check imported object and throw and error (to emulate load failure, as it is a failure). Wondering if can call another check just after it and throw an error if component was resolved to nothing. That should trigger "normal" error branches (fallback or ErrorBoundary), not break createElement.
A little different issue, but quite related
@brunos3d i might be able to help with the fake remote which returns null. We could modify node federation or allow it to throw a rejection. Generally I avoid that since throwing errors in sync imported components can cause webpack runtime to crash
great work! @gregberge any plan to merge it soon? :)
@ranshamay Probably we will not merge this PR, but I'm working on some stuff:
- An article (WIP)
- These loadable adapters
- This repo with samples on how to use @mf/loadable-adapters
I will post the updates here soon as I finish everything, but its also good to keep an eye on https://valor-software.com/articles too 🚀
@brunos3d I saw this example that you prepared: https://github.com/module-federation/module-federation-examples/tree/88c252fbc3fdc3262e0d8e3d03a945276bd0a165/loadable-react-16
In my server-side micro frontend application, I will use module federation to combine shared libraries (react, react-dom, axios). Is it problematic to use this? I am eagerly waiting for your answer.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.