各位观众老爷,晚上好!我是你们的老朋友,今天咱们不聊八卦,就聊聊技术——聊聊怎么用 Vite
的 module federation
插件,把 Vue 微前端架构玩出新花样,实现代码共享和版本管理。
一、 啥是 Module Federation? 别跟我扯一堆概念!
先别晕,Module Federation 其实没那么玄乎。你可以把它想象成乐高积木,每个积木块(也就是模块)都可以独立开发、部署,最后拼在一起组成一个完整的房子(也就是应用)。
-
传统方式的痛点: 假设你有三个 Vue 项目,都要用到一个公用的按钮组件。 传统的做法就是把这个组件复制粘贴到每个项目里。 问题来了:
- 代码冗余: 占用空间不说,改一个地方要改三个地方,简直是噩梦。
- 版本不一致: 某个项目偷懒没更新,就导致各个项目用的按钮样式不一样,UI 风格不统一,甲方爸爸会骂娘的!
-
Module Federation 的优势: Module Federation 允许一个应用(host)动态地加载另一个应用(remote)的模块,并且这些模块可以共享依赖。 也就是说,那个公用的按钮组件可以放在一个单独的项目里,其他项目直接引用,避免了代码冗余和版本不一致的问题。
二、 Vite + Module Federation: 天生一对!
Vite
快,那是公认的。 Module Federation 可以把应用拆成小块,按需加载,进一步提升性能。 两者结合,简直是微前端架构的最佳拍档!
三、 实战演练: 手把手教你搭建一个简单的微前端 Demo
为了更好地理解,咱们来做一个简单的 Demo,包含一个 Host 应用和一个 Remote 应用,Remote 应用暴露一个组件给 Host 应用使用。
1. 创建项目
首先,用 Vite
创建两个 Vue 项目:
npm create vite@latest host-app --template vue
npm create vite@latest remote-app --template vue
2. 安装 Module Federation 插件
进入两个项目的根目录,安装 @originjs/vite-plugin-federation
插件:
cd host-app
npm install @originjs/vite-plugin-federation --save-dev
cd ../remote-app
npm install @originjs/vite-plugin-federation --save-dev
3. 配置 Remote 应用 (remote-app)
Remote 应用负责暴露组件。
-
创建组件: 在
remote-app/src/components
目录下创建一个RemoteButton.vue
组件:<template> <button @click="handleClick">Remote Button (Version: {{ version }})</button> </template> <script setup> import { ref } from 'vue'; const version = '1.0.0'; // 组件版本号 const emit = defineEmits(['click']); const handleClick = () => { emit('click'); }; </script>
-
修改
vite.config.js
: 配置 Module Federation:import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import federation from "@originjs/vite-plugin-federation"; export default defineConfig({ plugins: [ vue(), federation({ name: 'remote_app', // 必须唯一 filename: 'remoteEntry.js', // 远程入口文件名 exposes: { './RemoteButton': './src/components/RemoteButton.vue', // 暴露的模块 }, shared: ['vue'] // 共享的依赖 }) ], server: { port: 5001, // 端口号 } })
name
:Remote 应用的名称,必须唯一。filename
:远程入口文件名,Host 应用会通过这个文件加载 Remote 应用暴露的模块。exposes
:暴露的模块,键是模块的名称,值是模块的路径。shared
:共享的依赖,Remote 应用和 Host 应用都会用到vue
,所以需要共享,避免重复加载。
-
启动 Remote 应用:
npm run dev
4. 配置 Host 应用 (host-app)
Host 应用负责加载 Remote 应用暴露的组件。
-
修改
vite.config.js
: 配置 Module Federation:import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import federation from "@originjs/vite-plugin-federation"; export default defineConfig({ plugins: [ vue(), federation({ name: 'host_app', // 必须唯一 remotes: { remote_app: 'http://localhost:5001/remoteEntry.js', // 远程应用地址 }, shared: ['vue'] // 共享的依赖 }) ], server: { port: 5000, // 端口号 } })
name
:Host 应用的名称,必须唯一。remotes
:远程应用列表,键是 Remote 应用的名称,值是 Remote 应用的远程入口文件地址。shared
:共享的依赖,和 Remote 应用保持一致。
-
使用 Remote 组件: 在
host-app/src/App.vue
中引入 Remote 组件:<template> <h1>Host App</h1> <RemoteButton @click="handleClick" /> <p>Count: {{ count }}</p> </template> <script setup> import { ref } from 'vue'; import { defineAsyncComponent } from 'vue'; // 动态加载 Remote 组件 const RemoteButton = defineAsyncComponent(() => import('remote_app/RemoteButton')); const count = ref(0); const handleClick = () => { count.value++; alert('Button clicked from Remote App!'); }; </script>
defineAsyncComponent
:异步加载 Remote 组件,避免阻塞主应用。remote_app/RemoteButton
:Remote 组件的名称,和 Remote 应用的exposes
配置中的键对应。
-
启动 Host 应用:
npm run dev
5. 运行效果
分别启动 Host 应用和 Remote 应用,在浏览器中访问 http://localhost:5000
,可以看到 Host 应用成功加载了 Remote 应用的 RemoteButton
组件。
四、 代码共享: 不止是组件,还能共享啥?
Module Federation 不仅仅能共享组件,还能共享:
- 状态管理: 可以把 Vuex 或者 Pinia 的 store 放在一个单独的项目里,其他项目直接引用,实现状态共享。
- 工具函数: 可以把常用的工具函数封装成一个模块,其他项目直接引用,提高开发效率。
- UI 库: 可以把自定义的 UI 库放在一个单独的项目里,其他项目直接引用,统一 UI 风格。
五、 版本管理: 如何保证各个项目用的都是最新版本?
版本管理是 Module Federation 的一个重要环节。
- 组件版本号: 在 Remote 组件中定义版本号,方便 Host 应用识别。 比如上面的
RemoteButton.vue
组件中的version
变量。 - CDN: 把 Remote 应用部署到 CDN 上,可以方便地更新版本,并且减少 Host 应用的打包体积。
- 版本控制: 使用 Git 等版本控制工具管理 Remote 应用的代码,方便回滚和查看历史版本。
- CI/CD: 使用 CI/CD 工具自动化部署 Remote 应用,保证每次更新都能及时发布。
六、 高级玩法: 动态 Remote 应用
上面的例子中,Remote 应用的地址是写死的。 如果 Remote 应用的地址经常变化,或者需要根据不同的环境加载不同的 Remote 应用,怎么办?
- 环境变量: 可以把 Remote 应用的地址放在环境变量中,Host 应用在运行时读取环境变量,动态加载 Remote 应用。
- 配置中心: 可以使用配置中心(比如 Apollo、Nacos)管理 Remote 应用的地址,Host 应用从配置中心获取 Remote 应用的地址。
- 服务发现: 可以使用服务发现机制(比如 Consul、Eureka)自动发现 Remote 应用的地址,Host 应用通过服务发现机制获取 Remote 应用的地址。
七、 踩坑指南: 注意事项
- 依赖冲突: 共享的依赖版本要保持一致,否则可能会出现运行时错误。 可以使用
shared
配置项的requiredVersion
属性指定依赖的版本范围。 - 循环依赖: 避免 Remote 应用和 Host 应用之间出现循环依赖,否则可能会导致加载失败。
- 性能优化: 合理划分模块,避免过度拆分,否则可能会增加网络请求,影响性能。
- 安全问题: 注意 Remote 应用的安全问题,防止恶意代码注入。
八、 总结
Module Federation 是一种强大的微前端架构解决方案,可以实现代码共享和版本管理,提高开发效率和代码质量。 Vite
的 module federation
插件,让这一切变得更加简单。 当然,Module Federation 也有一些缺点,比如配置复杂、调试困难等。 在实际项目中,需要根据具体情况选择合适的微前端架构方案。
希望今天的讲解对你有所帮助,祝你早日成为微前端架构大师! 下次有机会再和大家分享更多有趣的技术!