基于webpack 5 ModuleFederationPlugin 实现微前端
有这么一个需求,项目里有很多业务模块,它们都有引用一些公共组件,每个业务模块打包后都是一个独立的应用,当公共组件修改时,单独打包公共组件,其他应用能够不需要重新构建,就能直接使用最新的公共组件,要怎么实现?
一开始我想到的是使用网络资源,就是把公共组件打包后的js文件放到服务器,其他应用通过script请求使用,尝试了一下,难以实现,放弃了。
后来找到了webpack 5的ModuleFederationPlugin,看了一下官方文档,完全适合这个需求,记录一下实现过程。
主要使用webpack 5的ModuleFederationPlugin插件实现模块共享和引用。
一、先创建两个vue-cli项目,分别是app1和app2
app1作为公共应用,把组件共享给其他应用使用
app2作为业务应用,引用app1共享的组件
这里就不介绍vue-cli创建步骤了,直接跳过
二、app1新增组件button.vue和divider.vue
index.js提供按需引用
1 2 3 4 5 6 7 | // button/index.js import Button from './button.vue' export default { install(Vue) { Vue.component( 'PtButton' , Button) } } |
common.js提供全量注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // common.js import './style.css' import Button from './button/index' import Divider from './divider/index' const install = async (vue) => { [ Button, Divider ].forEach(component => { vue.use(component) }) } export default { install, Button, Divider } |
vue.config.js 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | // vue.config.js module.exports = { // 共享模块必须是完整路径,不能是相对路径,否则无法请求额外的css和js资源 publicPath: process.env.NODE_ENV === 'production' ? "http://localhost:2020/peento" : "http://localhost:8095", chainWebpack: (config) => { /* splitChunks可能会和 ModuleFederationPlugin 造成冲突,先移除 */ config.optimization. delete ( "splitChunks" ); config .plugin( "module-federation-plugin" ) .use(require( "webpack" ).container.ModuleFederationPlugin, [ { name: "peento" , // 模块名称 filename: "peento.js" , // 输出的文件名称 exposes: { // 对外暴露的组件 "./peento-ui" : "./src/components/common.js" , // 暴露所有组件,通过use方法使用 "./button" : "./src/components/button/button" , // 暴露单独组件,需要注册使用 }, remotes: {} }, ]); }, devServer: { port: 8095, hot: true }, }; |
三、app2引用app1共享出来的组件
app2的vue.config.js配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // app2 vue.config.js module.exports = { chainWebpack(config) { config.optimization. delete ( 'splitChunks' ) config .plugin( "module-federation-plugin" ) .use(require( "webpack" ).container.ModuleFederationPlugin, [ { remotes: { // 生产环境所有应用域名相同的情况下,可以使用相对路径,否则需要使用完整路径 peento: process.env.NODE_ENV === 'production' ? "peento@http://localhost:2020/peento/peento.js" : "peento@http://localhost:8095/peento.js" } } ]) }, devServer: { port: 8085, hot: true }, }; |
app2的mian.js引用app1的组件
1 2 3 4 5 6 7 8 9 10 | // app2 main.js import Vue from 'vue' import App from './App.vue' import ( 'peento/peento-ui' ).then(res => { const peento = res. default Vue.use(peento) // 全量注册,可直接在组件里使用 new Vue({ render: h => h(App), }).$mount( '#app' ) }) |
也可以直接在组件中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // app2 App.vue <template> <div id= "app" > <PtButton>895621</PtButton> </div> </template> <script> export default { name: 'App' , components: { PtButton: () => import ( 'peento/button' ) } } </script> |
四、分布运行app1和app2开发环境,app2页面正常显示app1的button组件,实践成功!
下面是我根据上面的需求实现的一个多模块项目,有兴趣的可以看一下;
点击查看:vue-cli-module
项目结构和配置展示:
分类:
Vue
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!