What is Module Federation?
Module Federation is a concept introduced in webpack5. It provides us with a new construction model: program submodules can be developed, built and deployed independently of each other. This pattern is commonly referred to as a micro front end, but it offers more than that.
What are the features of Module Federation?
- Module split: program submodules have completely independent development process, do not affect each other;
- Module resource sharing: You can share dependent packages of each module to avoid repeated loading.
- Global state sharing: For frameworks like React and Vue, using Module Federation makes it easy to share global state between modules without additional processing.
How to use Module Federation in a project?
Before using Module Federation, define the concepts of local and remote modules:
- Local modules are common modules that are part of the current application; A remote module does not exist in the current application and is a module referenced from somewhere else at run time.
- A local module is opposed to a remote module. A module can be either a local module or a remote module (which can reference or be referenced by other modules).
ModuleFederationPlugin plug-in
Import the WebPack5 ModuleFederationPlugin plug-in to the original project and modify the configuration items without performing other operations.
- ModuleFederationPlugin Plugin reference
const {ModuleFederationPlugin} = require("webpack").container;
Copy the code
- ModuleFederationPlugin Plugin configuration item
module.exports = {
...
plugins: [
new ModuleFederationPlugin({
// A configuration item that must be provided as a remote module
name: 'remote'.// Alias of the current application, used as the module name when referenced by other modules
filename: 'remoteEntry.js'.// The entry file name referenced by other modules as a remote module.
exposes: { // A component provided for use by other modules. Key is the relative path when other modules are introduced
"./About": "./src/views/About.js",},// Optional when used as remote module
library: { // Define how to expose the output to the application.
type: 'var'.// To expose variables, such as var and window, var is used by default.
name: 'remote' // The name of the variable exposed to external applications
},
// A configuration item that must be provided as a local module
remotes: { // Load entry files for other remote modules
remote: "remote@http://localhost:8001/remoteEntry.js",},// As an optional configuration item shared by local and remote modules
shared: {
'vue': {
import: 'false'./ / false | string,
singleton: false.// Whether to enable singleton mode.
// This function is disabled by default. If the dependency versions of the current module are inconsistent with those shared by other modules, the dependency versions are loaded separately.
// After this function is enabled, the version of the dependency to be loaded is higher than that of the shared version. (This function is not enabled for the local module but is enabled for the remote module. Only the local module is loaded. The remote module is not loaded even if its version is higher.)
version: '3.2.6'.// Specify the shared dependency version
requiredVersion: '3.2.6'.// Specifies the version required by the current module. The default value is the dependent version of the current application
strictVersion: 'false'.// Whether strict version control is required. If this function is enabled, strictVersion in singleton mode will throw an exception if strictVersion is inconsistent with the actual dependent version.
packageName: 'string'.// The package name used to determine the desired version from the description file. Do this only if the package name cannot be automatically determined from the request.
sharedKey: 'string'.// Shared dependency alias. Default value Key value of shared configuration items.
shareScope: 'default' // Specifies the scope of the current shared dependency. The default value is default
eager: false.// Whether shared dependencies are split into separate files during packaging. Default split packaging. If true, shared dependencies are packaged into entry files and not separated out, losing the meaning of sharing.}},})]}Copy the code
A simple example
- Remote application module Settings
plugins: [
new ModuleFederationPlugin({
name: "remote".filename: "remoteEntry.js".exposes: { // Button and About components are provided
"./Button": "./src/components/Button.js"."./About": "./src/views/About.js",}})],Copy the code
- Local application module Settings
plugins: [
new ModuleFederationPlugin({
remotes: {
remote: "remote@http://localhost:8002/remoteEntry.js".// The production environment is replaced with the real URL}}),].Copy the code
- A component that introduces a remote module to a local application
const About = () = > import("remote/About");
const routes = [
...
{
path: '/about'.name: 'About'.component: About
},
]
Copy the code
That’s all you need to do with the ModuleFederationPlugin, and it’s as simple as that.
How the ModuleFederationPlugin works
1. Load remote module components
Using the above configuration, the local environment is started and the page loads the About component for the remote module (port 8000 is the local module service, port 8002 is the remote module service).
We can find that the remote module has 3 JS files loaded, they are respectively:
- Remoteentry. js: entry file of the remote module
- Node_modules_vue_dist_vue_runtime_esm-bundler_js. js: Dependency file of the remote module
- Src_views_about_vue. js: The About component file of the remote module
If you look at the configuration of the local module, you can see that the local module simply references the entry file remoteentry.js for the remote module. So how are the dependency files and component files of the remote module loaded?
First, let’s look at what files are packaged as remote modules:
- The entry file is remoteentry.js
- Depend on the file
- Several component files (each component is individually packaged)
The entry file remoteentry. js is loaded synchronously when the local project runs. It maps the name of each remote module component to the resource address (recorded by both dependencies and the component itself). When a remote component is used by the local module, the required resources are loaded asynchronously. So, dependency files and component files are loaded asynchronously through entry files.
2. Rely on the implementation of sharing
Dependency Sharing Configuration
Add the dependency information to be shared in the ModuleFederationPlugin configuration item
Local Module Configuration
new ModuleFederationPlugin({
remotes: {
remote: "remote@http://localhost:8002/remoteEntry.js",},shared: {
vue: {
version: '3.2.5'.singleton: true,}}}),Copy the code
Remote Module Configuration
plugins: [
new ModuleFederationPlugin({
name: "remote".filename: "remoteEntry.js".exposes: { // Button and About components are provided
"./Button": "./src/components/Button.js"."./About": "./src/views/About.js",},shared: {
vue: {
version: '3.2.0'.singleton: true}},})],Copy the code
Restart the service and you can see that the dependency files for the remote module have not been loaded. Instead, use the local module’s dependency files (the local dependency files are of a higher version; If the dependency version of the remote module is higher, the remote module dependency is loaded, the local module dependency is not loaded).
Dependency sharing principle
When modules are configured with shared information, each dependency is packaged separately into a file.
- The remote module entry file records the version information of shared dependencies and dependency loading rules.
- After the local module loads the import file of the remote module, the local module selects the version of the dependent file to load according to the sharing rules.
Shared dependency files are asynchronously loaded to avoid repeated loading of dependencies among multiple modules.
(… To be continued)
Refer to the article
Module Federation
Explore Webpack5 Module Federation’s “weird tricks”
Webpack.js.org/concepts/mo…
Webpack.js.org/plugins/mod…
Extension to understand
YY team is based on Module Federation micro-front-end framework EMP