模塊聯(lián)邦本身是一個Webpack 插件 ModuleFederationPlugin,插件有幾個重要參數(shù):
- name 必須,唯一 ID,作為輸出的模塊名,使用的時通過 name/{name}/name/{expose} 的方式使用;。
- remotes 可以將其他項目的 name 映射到當前項目中,遠程其他共享模塊的加載地址。
- exposes 表示導出的模塊,只有在此申明的模塊才可以作為遠程依賴被使用。
- shared 是非常重要的參數(shù),制定了這個參數(shù),可以讓遠程加載的模塊對應依賴改為使用本地項目。
一、 創(chuàng)建應用app1
1.首先創(chuàng)建vue項目app1,新建webpack.config.js,進行模塊聯(lián)邦配置(注意VueLoaderPlugin的使用)
const path = require('path');
// vue-loader在15.*之后的版本都是 vue-loader的使用都是需要伴生 VueLoaderPlugin的,
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin');
const { ModuleFederationPlugin } = require("webpack").container;
module.exports = {
devtool: false,
entry: './src/main.js',
mode: "development",
devServer: {
port: 3000,
contentBase: path.join(__dirname, "dist"),
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
// 請確保引入這個插件!
new VueLoaderPlugin(),
new HTMLWebpackPlugin({
template: path.resolve(__dirname, './public/index.html')
}),
new ModuleFederationPlugin({
// 提供給其他服務加載的文件
filename: "remoteEntry.js",
// 唯一ID,用于標記當前服務
name: "app1",
library: { type: "var", name: "app1" },
// 需要暴露的模塊,使用時通過 `${name}/${expose}` 引入
exposes: {
'./Button': "./src/components/Button.vue",
}
})
]
}
2.依賴安裝
在配置模塊聯(lián)邦時遇到了很多兼容問題,比如babel版本沖突等,demo項目中package.json配置如下
{
"scripts": {
"start": "webpack serve",
"build": "webpack"
},
"devDependencies": {
"@babel/core": "7.9.6",
"babel-loader": "^8.1.0",
"html-webpack-plugin": "^4.5.0",
"vue-loader": "^15.9.3",
"vue-template-compiler": "^2.6.12",
"webpack": "^5.0.0",
"webpack-dev-server": "^3.11.0"
},
"dependencies": {
"vue": "^2.6.12",
"webpack-cli": "^4.0.0"
}
}
二、創(chuàng)建應用app2
1.首先創(chuàng)建vue項目app2,新建webpack.config.js,進行模塊聯(lián)邦配置
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin');
const { ModuleFederationPlugin } = require("webpack").container;
module.exports = {
devtool: false,
entry: './src/main.js',
mode: "development",
devServer: {
port: 3001,
contentBase: path.join(__dirname, "dist"),
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
// 請確保引入這個插件!
new VueLoaderPlugin(),
new HTMLWebpackPlugin({
template: path.resolve(__dirname, './public/index.html')
}),
new ModuleFederationPlugin({
name: "app2",
remotes: {
app1: "app1@http://localhost:3000/remoteEntry.js",
}
})
]
}
2.依賴安裝
{
"scripts": {
"start": "webpack serve",
"build": "webpack"
},
"devDependencies": {
"@babel/core": "7.9.6",
"babel-loader": "^8.1.0",
"html-webpack-plugin": "^4.5.0",
"vue-loader": "^15.9.3",
"vue-template-compiler": "^2.6.12",
"webpack": "^5.0.0",
"webpack-dev-server": "^3.11.0"
},
"dependencies": {
"vue": "^2.6.12",
"webpack-cli": "^4.0.0"
}
}
三、在app2中調(diào)用app1
webpack配置好之后,我們通過地址訪問可以看到http://localhost:3000/remoteEntry.js 中的文件已經(jīng)被共享,在app2中直接以組件形式進行引用即可。
import("app1/Button") 會被解析大致為: loadScript("http://localhost:3000/remoteEntry.js").then(() => require('Content'))
<template>
<div id="app">
<h1>我是子應用</h1>
<p>我將使用主應用的共享組件</p>
<ul>
<li>
<Button />
</li>
</ul>
</div>
</template>
<script>
export default {
components: {
Button: () => import("app1/Button"),
},
};
</script>
【注:本篇文章是學習的時候看到的,轉(zhuǎn)載過來做筆記記錄。轉(zhuǎn)自掘金作者:寇寇菌,原文鏈接:https://juejin.cn/post/6992374705890000927】