首先我们可以去了解一下webpack5的模块联邦技术的思想,在现在的开发中,微前端的思想和技术已经得到了相对广泛的应用.
我们模拟2个团队,团队app1开发组件部署到线上给团队app2使用,团队app2使用远程组件。
详细代码可以参照一下代码:
本地端(团队app1):
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: 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')
}),
// name string 必传值,即输出的模块名,被远程引用时路径为${name}/${expose}
// library object 声明全局变量的方式,name为umd的name
// filename string 构建输出的文件名
// remotes object 远程引用的应用名及其别名的映射,使用时以key值作为name
// exposes object 被远程引用时可暴露的资源路径及其别名
// shared object 与其他应用之间可以共享的第三方依赖,使你的代码中不用重复加载同一份依赖
new ModuleFederationPlugin({
// 提供给其他服务加载的文件
filename: "remoteEntry.js",
// 唯一ID,用于标记当前服务
name: "app1",
library: { type: "var", name: "app1" },
// 需要暴露的模块,使用时通过 `${name}/${expose}` 引入
exposes: {
'./Header': "./src/components/Header.vue",
}
})
]
}
远程端(团队app2):
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的name filename
app1: "app1@http://localhost:3000/remoteEntry.js",
}
})
]
}
这个时候有一个很重要的知识点就是在app2中使用app1中暴露出来的组件的时候,需要采用异步加载的方式,可以参考以下的实现方式:
<template>
<div>
<Header name="app2" />
</div>
</template>
<script>
export default {
components: {
// Header: () => import("app1/Header"),
Header(resolve) {
require(["app1/Header"], resolve);
}
},
};
</script>
<style lang="scss" scoped></style>
项目到这里就可以完整的实现模块联邦技术了,从原理上来说,是可以采用webpack5+vue3+ts重新搭建一套基线项目的.
如果还是有问题,可以直接参考以下项目代码:
详细项目demo可以参考以下demo:
下载demo , 然后通过npm run start
将两个项目都启动起来