在大型應用中, 我們可能會對其進行拆分,分成容器、主應用和多個子應用,使拆分後的應用獨立開發與部署,更加容易維護。但無論是微應用、公共模塊應用,都需要放到容器中才能使用。
如果多個應用之間希望資源共享,除了使用 npm 包的形式,基於Webpack 5 Module Federation(模塊聯邦)實現的EMP微前端方案也可以一試,它不限制技術棧,但依賴於 Webpack5。
使用場景
如果應用B需要使用應用A中的User模塊,那麼應用B就相當於容器,同時應用A也可以使用來自應用C的Menu模塊,此時應用A變成了容器。
如何使用
要想使用 Module Federation,肯定是需要搭建 webpack 環境,配置方式也比較簡單,使用 ModuleFederationPlugin 分別導出/導出即可。
A應用導出文件
webpack配置需要導出的文件路徑和名稱
// 其餘配置省略
const Mfp = require('webpack').container.ModuleFederationPlugin;
module.exports = {
plugins: [
new Mfp({
// 對外提供打包後的文件名
filename: 'user.js',
// 導出的應用/組織什麼名字
name: 'userComponent',
// 要導出哪一個文件,key值為引入時的名字,value為當前文件路徑
exposes: {
'./username': './src/username.js',
'./userHobby': './src/userHobby.js',
}
})
]
}
B應用導入文件
webpack設置需要導入的資源地址和名稱
const Mfp = require('webpack').container.ModuleFederationPlugin
plugins: [
new Mfp({
name: 'root',
// key值為導入後使用的名字,value為導出的 filename@文件地址/name,設置本地服務地址方便調試
remotes: {
userComponent: 'userComponent@http://localhost:3001/user.js'
}
})
]
在需要使用的js文件中異步導入,userComponent 是定義的導入後的名字,斜槓(/)加上導出文件webpack配置exposes屬性的文件名
const Username = React.lazy(()=>import('userComponent/username'))
const UserHobby = React.lazy(()=>import('userComponent/userHobby'))
return (
<React.Suspense fallback="loading">
<Username/>
<UserHobby/>
</React.Suspense>)
引入後,http://localhost:3001/user.js 將會被加載,並且資源內容掛載到 window 對象中。
這樣,便可以達到應用之間共享組件的目的。
以上就是 Webpack Module Federation(模塊聯邦) 的介紹, 更多有關 前端、工程化 的內容可以參考我其它的博文,持續更新中~