微前端架构的核心是将一个完整的前端应用拆分为多个独立开发、独立部署的子应用,主应用负责子应用的加载与调度。支持热更新的微前端架构可以让子应用发布新版本后,用户无需刷新整个页面就能获取最新功能,避免传统整页刷新带来的体验断层。

核心设计思路
要实现微前端热更新,需要解决三个核心问题:子应用资源的版本管理、主应用对子应用资源的动态拉取、子应用实例的无缝替换。整体流程如下:
- 子应用构建时生成带版本哈希的静态资源,并将版本信息同步到版本管理服务
- 主应用定时或按需从版本管理服务拉取子应用最新版本信息
- 当检测到子应用版本更新时,主应用动态卸载旧版本子应用实例,加载新版本资源并重新挂载
基于qiankun的实现方案
qiankun是目前主流的微前端框架,本身提供了子应用加载、卸载的生命周期管理,我们可以在其基础上扩展热更新能力。
1. 子应用配置
子应用需要配置输出带哈希的文件名,同时暴露版本信息接口,以下是vue子应用的vite配置示例:
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
// 输出带哈希的文件名,避免缓存
rollupOptions: {
output: {
entryFileNames: `assets/[name].[hash].js`,
chunkFileNames: `assets/[name].[hash].js`,
assetFileNames: `assets/[name].[hash].[ext]`
}
}
},
// 配置跨域,允许主应用加载
server: {
port: 8081,
cors: true
}
})
子应用还需要提供一个接口返回当前版本信息,例如:
// 子应用服务端接口示例
app.get('/version', (req, res) => {
res.json({
version: '1.0.1', // 每次构建更新版本号
assets: {
js: '/assets/main.abc123.js',
css: '/assets/main.def456.css'
}
})
})
2. 主应用版本检测与热更新逻辑
主应用需要维护子应用的版本映射,定时检测子应用版本变化,以下是核心实现代码:
// 主应用版本管理模块
import { loadMicroApp, unmountMicroApp } from 'qiankun'
// 存储已加载的子应用实例和版本信息
const microAppMap = new Map()
// 子应用配置列表
const microApps = [
{
name: 'subApp1',
entry: 'http://localhost:8081',
container: '#subapp-container',
activeRule: '/subapp1'
}
]
// 初始化加载子应用
export const initMicroApps = () => {
microApps.forEach(app => {
const instance = loadMicroApp(app)
microAppMap.set(app.name, {
instance,
version: null
})
// 初始加载后获取版本信息
fetch(`${app.entry}/version`)
.then(res => res.json())
.then(data => {
microAppMap.get(app.name).version = data.version
})
})
}
// 定时检测子应用版本更新
export const startVersionCheck = (interval = 30000) => {
setInterval(async () => {
for (const app of microApps) {
const currentInfo = microAppMap.get(app.name)
const res = await fetch(`${app.entry}/version`)
const newVersionInfo = await res.json()
// 版本不一致则触发热更新
if (currentInfo.version !== newVersionInfo.version) {
console.log(`子应用${app.name}检测到新版本,开始热更新`)
await unmountMicroApp(currentInfo.instance)
const newInstance = loadMicroApp(app)
microAppMap.set(app.name, {
instance: newInstance,
version: newVersionInfo.version
})
}
}
}, interval)
}
关键注意事项
在实际落地时需要注意以下几点:
- 子应用卸载时需要清理全局副作用,比如定时器、全局事件监听、全局变量,避免内存泄漏
- 主应用加载子应用资源时可以添加缓存策略,版本未更新时直接使用缓存,减少请求开销
- 热更新过程中可以添加加载态提示,避免用户操作子应用区域时出现异常
- 如果子应用和主应用共享状态,热更新后需要同步最新状态到新加载的子应用实例
适用场景与局限性
这种热更新方案适合子应用迭代频繁、需要快速触达用户的场景,比如运营类微前端应用、内部管理系统。但如果是子应用做了破坏性更新,比如修改了与主应用的通信协议,可能需要引导用户刷新页面保证功能正常。同时热更新会增加一定的主应用复杂度,小型微前端项目可以根据实际需求选择是否开启该能力。