To reduce the initial load of my app, i try to do code splitting. For exemple, i successfully split twilio-video, to load and initialize when user press "call"
import('twilio-video').then(Video => {
Video.connect(twilioInfo.data.token, options).then(room => {
...
});
});
Webpack correctly split the code and load it when needed.
Now i would like to do the same with components, or routes (to not load user profil while we stand on login page). Is there any equivalent of
const OtherComponent = React.lazy(() => import('./OtherComponent'));
or
const Home = lazy(() => import('./routes/Home'));
or any other way to load component when a route path is hitted?
It used to be very difficult. These days, Webpack Module Federation makes it a breathe.
They have tons of samples to get you started. For example, the basic-host-remote sample has a simple scenario that fits your need. Just fetch the entire Github repo, cd
into this sample, and run it (as explained in each sample's README
).
Keep an eye open for the Network tab. Components are not loaded until they are explicitely requested.
The basic-host-remote sample has two separate packages: app1
and app2
.
app1
wants to use components from app2
app2
to its remotes
in its WMF configapp2
provides a Button
component
app2
exposes
Button
in its WMF config.app1
requests a component using dynamic import
.const RemoteButton = React.lazy(() => import("app2/Button"));
useEffect
, or a Route.render
callback etc.app1
can use that Button
, once it's loaded. While loading, it shows a loading message, using Suspense
:
<React.Suspense fallback={<LoadingScreen />}>
<RemoteButton />
</React.Suspense>
lazy
and Suspense
, you can just take the promise returned from the import(...)
statement and handle the asynchronous loading any way you prefer. Of course, WMF
is not at all restricted to react
and can load any module dynamically.app1
and app2
have the same shared
setup, making sure that those shared dependencies are only loaded one time, and not bundled/duplicated with remotely loaded code:{
// ...
shared: { react: { singleton: true }, "react-dom": { singleton: true } },
}
Note that WMF
dynamic loading must use dynamic import
(i.e. import(...)
), because:
require
" cannot be bundled by webpack since browsers have no concept of commonjs
(unless you use some hacks, in which case, you will lose the relevant "loading promise
").WMF takes a bit of learning, but all its samples have the following common elements:
webpack.config.js
development
mode, you usually serve up everything using the nicely integrated webpack-dev-server
.
production
mode, you want to make some small adjustments to your config. When webpack-dev-server
is out of the picture, your build just adds some additional remoteEntry.js
files to your build output.shared
configuration. (Usually you want them to act as singletons, meaning, everyone should share common dependencies, and not pack their own.)expose
it and add its own (independent) components to its own remotes
. Not sure if it works, but its worth trying.Again, it will take a bit of a learning curve, but I find it's definitely worth it. Feels like one of the most sophisticated dynamic build + load systems I have seen.
Most annoyingly, WMF still does not currently have proper API documentation on the Webpack page, but I'm sure it'll come soon enough. Currently, there is only a not all too polished collection of conceptual notes.
The WMF author himself promises to provide better documentation soon™️.
Luckily, for learning, the samples are really good, actively maintained and still being enhanced.