This is a very simplistic example of mixing RequireJS and Webpack in order to allow for a "federated front-end" (a.k.a., micro-frontend), without duplicating dependencies.
There are two sub-folders:
shell
: this is the "shell" of our app, which (asynchronously) loads the federated "remote" front-endremote
: this is just a bundle, built as AMD, that gets asynchronously loaded and used by the "shell"
This example is built using React, but presumably different frameworks could work with a similar approach.
To run this example:
- Open two terminal windows (or tabs).
- In one tab, go to the
shell
folder, and typeyarn start
(<-- should default to port 8080>) - In another tab, go to the
remote
folder, and typeyarn start
(<-- should default to port 8081>) - Visit http://localhost:8080
I'm not going to go into a justification for federated front-ends here. You can read more here if you're really interested.
It's a bit weird, honestly, but it's mostly just a matter of configuring Webpack and RequireJS correctly to pull it all together.
- We have a
requirejs-config.js
file that tells RequireJS where to find the remote, as well has how any dependencies that are used by the remote (e.g., in this case,react
andreact-dom
) - In
webpack-config.js
, we:- add additional key-value pairs to the
entry
object for all of the dependencies that we want to externalize to be shared between both the shell and the remotes - for each additional key-value pair we added in the
entry
object, we list that same module identifier in theexternals
array - in the
output
section, we name the files and modules dynamically (using[name]
), and tell webpack to use AMD modules (with thelibraryTarget
directive) rather than the default
- add additional key-value pairs to the
- In
src/app.js
, you can see whererequirejs
is invoked to dynamically load the remote module
- In
webpack-config.js
, we:- list out only our actual entry points in the
entry
object - in the
output
section, we name the files and modules dynamically (using[name]
), and tell webpack to use AMD modules (with thelibraryTarget
directive) rather than the default - list any dependencies that we plan to get from the shell in the
externals
array
- list out only our actual entry points in the
- It may be possible to use a different (perpahs lighter-weight?) AMD loader instead of RequireJS.
- This approach leaves it up to the developers of the "shell" and the "remote" to sort out a process to ensure that the dependencies remain in sync.
See the LICENSE file.