本文主要介紹webpack 5 的新特性之一 "module federation"(聯邦模塊),涉及聯邦模塊特性、使用方法、適用範圍。css
webpack 5引入聯邦模式是爲了更好的共享代碼。 在此以前,咱們共享代碼通常用npm發包來解決。 npm發包須要經歷構建,發佈,引用三階段,而聯邦模塊能夠直接引用其餘應用代碼,實現熱插拔效果。對比npm的方式更加簡潔、快速、方便。html
假設咱們有app1,app2兩個應用,端口分別爲3001,3002。 app1應用要想引用app2裏面的js,直接用script標籤便可。前端
例如app1應用裏面index.html引入app2應用remoteEntry.jsreact
<head>
<script src="http://localhost:3002/remoteEntry.js"></script>
</head>複製代碼
app1的webpack配置:webpack
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
//....
plugins: [
new ModuleFederationPlugin({
name: "app1",
library: { type: "var", name: "app1" },
remotes: {
app2: "app2",
},
shared: ["react", "react-dom"],
}),
],
};
複製代碼
對於app2的webpack配置以下git
plugins: [
new ModuleFederationPlugin({
name: "app2",
library: { type: "var", name: "app2" },
filename: "remoteEntry.js",
exposes: {
"./Button": "./src/Button",
},
shared: ["react", "react-dom"],
})
],複製代碼
能夠看到app1和app2的配置基本相同,除了app2 多了filename和exposes之外。github
參數解釋web
name
應用名,全局惟一,不可衝突。library
。UMD標準導出,和name保持一致便可。remotes
聲明須要引用的遠程應用。如上圖app1配置了須要的遠程應用app2.filename
遠程應用時被其餘應用引入的js文件名稱。對應上面的remoteEntry.js
exposes
遠程應用暴露出的模塊名。shared
依賴的包。["react", "react-dom"]
,而它被app1所消費,因此webpack會先查找app1是否存在這兩個包,若是不存在就使用app2自帶包。 app1裏面一樣申明瞭這兩個參數,由於app1是本地應用,因此會直接用app1的依賴。對於app1/App.js代碼使用app2的組件,代碼以下:npm
import React from "react";
const RemoteButton = React.lazy(() => import("app2/Button"));
const App = () => (
<div>
<h1>Basic Host-Remote</h1>
<h2>App 1</h2>
<React.Suspense fallback="Loading Button">
<RemoteButton />
</React.Suspense>
</div>
);
export default App;複製代碼
具體這一行sass
const RemoteButton = React.lazy(() => import("app2/Button")); 複製代碼
使用方式爲:import('遠程應用名/暴露的模塊名'),對應webpack配置裏面的name和expose。使用方式和引入一個普通異步組件無差異。
因爲share這個屬性的存在,因此本地應用和遠程應用的技術棧和版本必須兼容,統一用同一套。好比js用react,css用sass等。
聯邦模塊和微前端的關係:由於expose這個屬性便可以暴露單個組件,也能夠把整個應用暴露出去。同時因爲share屬性存在,技術棧必須一致。因此加上路由,能夠用來實現single-spa這種模式的微前端。
使用場景:新建專門的組件應用服務來管理全部組件和應用,其餘業務層只須要根據本身業務所需載入對應的組件和功能模塊便可。模塊管理統一管理,代碼質量高,搭建速度快。特別適用矩陣app,或者可視化頁面搭建等場景。
例子的github地址