今天聊聊 Vite+Vue3 生态下最主流的 5 种微前端方案,附代码示例和选型指南,看完直接抄作业~
先唠句废话:2025 年还不用 Vite+Vue3 的前端团队,怕是要被卷到沙滩上了。
qiankun 作为微前端领域的 "老大哥",2025 年依然活跃,关键是它对 Vite 做了专项优化(以前老吐槽它和 Vite 八字不合)。
还是基于 single-spa 的路由劫持 + 应用沙箱,但现在能自动识别 Vite 子应用的 ES 模块格式,不用再手动配置vite-plugin-qiankun的一堆参数了。
ts<!-- main-app/src/App.vue -->
<template>
<div>
<nav>
<button @click="gotoApp('vue-app1')">应用1</button>
<button @click="gotoApp('vue-app2')">应用2</button>
</nav>
<!-- 子应用挂载点 -->
<div id="micro-app-container"></div>
</div>
</template>
<script setup>
import { registerMicroApps, start } from 'qiankun';
import { useRouter } from 'vue-router';
const router = useRouter();
// 注册子应用
registerMicroApps([
{
name: 'vue-app1',
entry: '//localhost:5173', // Vite子应用开发环境地址
container: '#micro-app-container',
activeRule: '/app1', // 路由匹配规则
// 给子应用传参(Vue3的props风格)
props: {
token: 'main_app_token',
onLogin: (userInfo) => console.log('子应用登录了', userInfo)
}
},
// 应用2配置...
]);
// 启动qiankun
start({
sandbox: {
// 2025新特性:支持CSS变量穿透,解决子应用主题统一问题
cssVars: ['--primary-color', '--font-size']
}
});
const gotoApp = (app) => {
router.push(app === 'vue-app1' ? '/app1' : '/app2');
};
</script>
ts// app1/vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
// qiankun官方Vite插件,2025版已经内置适配
import { qiankunPlugin } from 'qiankun';
export default defineConfig({
plugins: [
vue(),
qiankunPlugin({
name: 'vue-app1' // 必须和主应用注册的name一致
})
],
server: {
port: 5173,
cors: true // 允许跨域,主应用才能访问
}
});
虽然适配了 Vite,但底层还是基于 HTML 入口,和 Vite 的 ES 模块理念有点 "貌合神离" 配置项依然偏多,新手容易在activeRule和sandbox上踩坑
2025 年的模块联邦已经不是 webpack 的专属了,Vite 的vite-plugin-federation插件经过两年迭代,已经成为 Vue3 微前端的首选方案之一。
直接基于 ES 模块共享代码,主应用和子应用就像 "模块超市",你可以按需导入任何子应用的组件、路由甚至状态,完全摆脱 HTML 入口的束缚。
ts// app2/vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import federation from '@originjs/vite-plugin-federation';
export default defineConfig({
plugins: [
vue(),
federation({
name: 'app2', // 子应用名称
filename: 'remoteEntry.js', // 远程入口文件
// 暴露给主应用的模块
exposes: {
'./App': './src/App.vue',
'./routes': './src/routes.ts', // 甚至可以共享路由配置
'./store': './src/store/index.ts' // 共享Pinia状态
},
shared: ['vue', 'vue-router', 'pinia'] // 共享依赖,避免重复加载
})
]
});
ts<!-- main-app/src/views/App2View.vue -->
<template>
<div>
<h2>这是来自app2的组件</h2>
<App2Component />
</div>
</template>
<script setup>
// 直接导入子应用暴露的组件(开发环境也能实时热更新!)
const App2Component = defineAsyncComponent(() =>
import('app2/App') // 'app2'对应子应用的name
);
// 甚至能直接用子应用的路由
import app2Routes from 'app2/routes';
console.log('app2的路由配置', app2Routes);
</script>
<style scoped>
/* 样式隔离?直接用CSS Modules或scoped即可,Vite会自动处理 */
</style>
Garfish 是字节跳动开源的微前端框架,2025 年已经更新到 3.x 版本,对 Vue3 的支持堪称 "亲儿子级别"。
基于 "应用容器" 模型,每个子应用运行在独立的容器中,支持 JS 沙箱、样式隔离、预编译等特性,同时内置了 Vue3 的加载器,不用额外配置。
ts// main-app/src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import { Garfish } from 'garfish';
const app = createApp(App);
// 初始化Garfish
const garfish = new Garfish({
// 容器列表,指定子应用挂载点
containers: [
{
name: 'app-container',
el: '#app-container'
}
],
// 子应用配置
apps: [
{
name: 'vue3-app',
entry: '//localhost:3000', // Vite子应用地址
activeWhen: '/vue3-app', // 激活路径
// Vue3专属配置:自动识别Composition API
props: {
app: app // 甚至能把主应用的app实例传过去
}
}
],
// 2025新特性:支持Vite的HMR代理,开发环境无缝衔接
vite: {
hmr: true
}
});
// 启动
garfish.start();
app.mount('#app');
ts// vue3-app/src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
// Garfish的Vue3适配器(2025版已内置自动检测)
import { vue3Adapter } from '@garfish/adapter-vue3';
const app = createApp(App);
// 导出子应用生命周期
export const provider = vue3Adapter({
app,
// 挂载函数
mount({ el }) {
app.mount(el);
},
// 卸载函数
unmount() {
app.unmount();
}
});
腾讯开源的无界微前端框架,在 2025 年也崭露头角,以其对 Vite 的友好支持和诸多实用特性受到关注。
基于 webcomponent 容器 + iframe 沙箱,利用 iframe 的原生隔离特性,解决了子应用的运行上下文隔离问题,同时借助 webcomponent 的自定义元素能力,将子应用封装成可复用的组件形式,便于在主应用中灵活使用。
使用无界提供的基于 Vue 封装的wujie-vue(以 Vue3 为例):
ts<template>
<div>
<wujie-vue name="sub-app1" :url="subAppUrl1" :props="subAppProps" :preload="true"></wujie-vue>
</div>
</template>
<script setup>
import WujieVue from 'wujie-vue3';
import { ref } from 'vue';
const subAppUrl1 = ref('//localhost:5174');// Vite子应用地址
const subAppProps = {
// 传递给子应用的参数
someData: 'from main app'
};
</script>
在main.ts中引入并注册wujie-vue:
import { createApp } from 'vue';
import App from './App.vue';
import WujieVue from 'wujie-vue3';
const app = createApp(App);
app.use(WujieVue);
app.mount('#app');
子应用本身不需要过多特殊配置,因为无界的 iframe 沙箱原生支持 ESModule 脚本,即 Vite 构建的产物。如果子应用需要单独运行,也能轻松实现,只需遵循常规的 Vite 项目启动方式即可。
「相对较新」:相较于一些老牌框架如 qiankun,无界的社区和生态系统尚在发展中,第三方插件和相关技术文章相对较少,遇到复杂问题时,可参考的资料可能有限。
京东开源的 micro - app 微前端方案,采用了独特的组件化渲染思路,在 Vite+Vue3 生态中也有不错的表现。
借鉴了 WebComponent 的思想,通过 CustomElement 结合自定义的 ShadowDom,将微前端封装成一个类似 webComponents 组件。这种方式使得每个子应用都能以独立的组件形式存在,拥有自己的作用域,包括样式和脚本,从而实现了较好的隔离性。
在主应用中引入micro - app的相关库并配置子应用:
ts// main - app/src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import microApp from '@micro - app/vue3';
const app = createApp(App);
app.use(microApp, {
apps: [
{
name:'sub - app - vue',
entry: '//localhost:5175',// Vite子应用地址
container: '#sub - app - container',
activeRule: '/sub - app'
}
]
});
app.mount('#app');
在模板中使用:
ts<template>
<div id="sub - app - container"></div>
</template>
子应用需要使用@micro - app/vite - plugin插件进行改造:
ts// sub - app/vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin - vue';
import microAppPlugin from '@micro - app/vite - plugin';
export default defineConfig({
plugins: [
vue(),
microAppPlugin({
name:'sub - app - vue'
})
],
server: {
port: 5175,
cors: true
}
});
「个人经验」:中小团队如果追求新体验且无历史包袱,直接冲模块联邦,开发体验真的香;有老项目的团队,鉴于兼容性和稳定性,先用 qiankun 过渡,后续再逐步迁移到 Vite + 模块联邦;如果是字节系内部团队或对稳定性要求极高,Garfish 是很好的选择;若看重轻量和丰富功能,腾讯无界值得尝试;喜欢组件化思维构建微前端的则可以考虑京东 micro - app。
本文作者:小白菜
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!