簡介
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 /> </> ); };