ModuleFederation-模块联邦
简介
Module federation 解决了一次构建可以拆分为多次构建的问题,并且构建产物也可以为其他应用提供服务。
本质上 webpack 的能力是用来增强不同 bundle 之间 code sharing
的能力。
Multiple separate builds should form a single application. These separate builds should not have dependencies between each other, so they can be developed and deployed individually.
This is often known as Micro-Frontends, but is not limited to that.
多个独立的构建可以形成一个应用程序。这些独立的构建不会相互依赖,因此可以单独开发和部署它们。这通常被称为微前端,但并不仅限于此。
概念
从官网的描述可以简单看出,MF 希望做的事情就是将多个独立部署构建的应用合并成一个。因此,MF 引出下面
概念:
Container: 一个被模块联邦插件打包出来的模块称为一个 Container, 他可以被其他的 bundle 进行消费的。
- host应用:消费 webpack 构建出的 Container 的 module。(引用了其他应用的应用)
- remote应用:被消费的 Container.(被其他应用所使用的应用)
使用
MF 是webpack5 自带的,我们只需要创建一个 ModuleFederationPlugin 即可,简单的配置如下:
- name:应用名称,当作为 remote 被引用是,路径为 ${name}/${expose}
- library:声明全局变量的方式,name为umd的name
- filename:构建输出的文件名
- remotes:远程引用的应用名及其别名的映射,使用时以key值作为name,host 应用需要配置
- exposes:被远程引用时可暴露的资源路径及其别名,rremote 应用需要配置
- shared:与其他应用之间可以共享的第三方依赖,使你的代码中不用重复加载同一份依赖
配置
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); module.exports = { // 其他配置 plugins: [ new ModuleFederationPlugin({ name: 'website2', // remote 子应用名称 library: { type: 'var', name: 'website2' },//声明全局变量的方式umd, cjs,name为umd的name filename: 'remoteEntry.js', // 打包出的文件名 exposes: { './router': './src/entries/router.ts', './public-path': './config/public-path.js', ...appComponents, }, // 优先用 Host 的依赖,如果 Host 没有,再用自己的 shared: ['react', 'react-dom'] }), ], }
使用
获取远程应用的模块
import ('dpapp_catalog/router').then(data => { // console.log(data); // 远程子应用模块 })
import React, { lazy, Suspense, useState } from 'react'; import Footer from './Footer'; import Footer2 from 'website2/Footer'; // federated const Title = lazy(() => import('website2/Title')); // federated export default () => { return ( <> <Suspense fallback={'fallback'}> <Title /> </Suspense> <Footer /> <Footer2 /> </> ); };