马鞍山市网站建设_网站建设公司_虚拟主机_seo优化
2026/1/16 10:26:49 网站建设 项目流程

记录一次微前端改造:把 10+ 个独立 Vue 项目整合到一起

最近主导了公司前端项目的微前端化改造,踩了不少坑,也有一些收获。趁着记忆还新鲜,把过程记录下来,希望能给有类似需求的同学一些参考。

声明:我也是第一次做微前端,很多地方可能不够规范,欢迎大家指正。

一、背景:我们遇到了什么问题?

1.1 项目现状

公司的前端项目经过几年发展,变成了这样:

  • 10+ 个独立的 Vue 项目:认证系统、主业务平台、教育模块、社区模块、H5 移动端等
  • 每个项目都是独立的 Git 仓库,有自己的 CI/CD 流程,独立部署
  • 技术栈不太统一:有的是 Vue 2 + Vue CLI,有的是 Vue 3 + Vite
  • 用户体验比较割裂:在不同系统间跳转时,要重新加载整个页面

1.2 想解决的问题

问题具体表现
体验不连贯系统间跳转白屏时间长,感觉像在用不同的网站
登录状态虽然用 Cookie 共享了 token,但体验还是不够好
重复建设每个项目都有一套类似的基础代码

说实话,一开始我对微前端也没什么概念,是领导提出想把这些系统整合成一个统一入口,我才开始研究这个方向。

二、技术选型:为什么选 micro-app?

2.1 调研过的方案

方案我的理解为什么没选/选了
iframe最简单,天然隔离体验不好,通信麻烦
qiankun最成熟,基于 single-spa配置比较复杂,子应用改造成本高
micro-app京东出的,基于 Web Components接入简单,改造成本低 ✅
Module FederationWebpack 5 的功能我们有的项目还在用 Vue CLI 4

2.2 选择 micro-app 的原因

说实话,主要是因为简单

看了官方文档后,发现子应用几乎不需要怎么改,基座应用也就几行代码:

// 基座应用启动importmicroAppfrom'@micro-zoe/micro-app'microApp.start()// 加载子应用就一个标签<micro-app name="app1"url="http://localhost:8081/"></micro-app>

对于我这种微前端新手来说,能快速跑起来比什么都重要。

三、项目结构

3.1 实际情况

需要说明的是,我们的项目结构是这样的:

# 这些都是独立的 Git 仓库,我只是在本地建了个文件夹把它们放一起方便开发 project/ # 本地文件夹(不是 Git 仓库) ├── project-base/ # 基座应用 - 独立 Git 仓库 ├── project-main/ # 主业务 - 独立 Git 仓库 ├── project-auth/ # 认证系统 - 独立 Git 仓库 ├── project-edu/ # 教育模块 - 独立 Git 仓库 ├── project-community/ # 社区模块 - 独立 Git 仓库 └── ...

每个项目都是独立部署的,有自己的 Docker 镜像和部署流程。微前端改造并没有改变这一点,只是加了一个基座应用来统一加载它们。

3.2 端口规划

本地开发时,我给每个应用分配了不同的端口:

应用端口路由前缀
project-base8080/
project-main8081/main
project-auth8082/auth
project-community8083/communities
project-edu8085/edu

四、具体怎么做的

4.1 基座应用

基座应用是新建的,用的 Vite + Vue 3。

1. 安装和初始化 micro-app

// project-base/src/main.tsimportmicroAppfrom"@micro-zoe/micro-app";microApp.start({plugins:{modules:{},},});

2. Vite 需要配置一下,不然会报错

// project-base/vite.config.tsvue({template:{compilerOptions:{// 告诉 Vue:micro-app 是自定义元素,别当组件解析isCustomElement:(tag)=>/^micro-app/.test(tag),},},});

3. 路由配置

// 用通配符匹配子应用的所有路由constroutes=[{path:"/main/:page*",component:()=>import("@/views/main.vue"),},{path:"/auth/:page*",component:()=>import("@/views/auth.vue"),},// ...];

4. 子应用挂载组件

<!-- project-base/src/views/main.vue --> <template> <micro-app name="project-main" :url="url" baseroute="/main" /> </template> <script setup> const url = "http://localhost:8081/child/main/"; </script>

4.2 子应用改造

子应用的改造确实不多,主要是这几步:

1. 新建 public-path.ts

// src/public-path.tsif(window.__MICRO_APP_ENVIRONMENT__){__webpack_public_path__=window.__MICRO_APP_PUBLIC_PATH__;}

2. 改造入口文件

// src/main.tsimport"./public-path";// 必须放最前面letapp=null;letrouter=null;lethistory=null;functionmount(){history=createWebHistory(window.__MICRO_APP_BASE_ROUTE__||process.env.BASE_URL);router=createRouter({history,routes});app=createApp(App);app.use(router);app.mount("#app");}functionunmount(){app?.unmount();history?.destroy();app=null;router=null;history=null;}// 判断运行环境if(window.__MICRO_APP_ENVIRONMENT__){// 微前端环境window[`micro-app-${window.__MICRO_APP_NAME__}`]={mount,unmount};}else{// 独立运行mount();}

3. 配置跨域(开发环境)

// vue.config.jsmodule.exports={devServer:{headers:{"Access-Control-Allow-Origin":"*",},},};

4.3 状态共享

这块我承认做得不太规范。

按理说应该用 micro-app 提供的通信机制,但我们之前的项目已经有一套基于 localStorage + Cookie 的方案在用了,而且子应用还需要支持独立运行,所以就没改。

// 公共组件库里的 storeexportdefault{set(key,data){localStorage.setItem(key,JSON.stringify({data}));},get(key){constcache=localStorage.getItem(key);returncache?JSON.parse(cache).data:null;},// token 用 cookie 存,这样可以跨子域共享set_cookie(name,value){document.cookie=`${name}=${value}; path=/; max-age=${30*24*60*60}`;},};

这个方案的问题

  • 不够实时,一个应用改了数据,另一个应用需要刷新才能看到
  • 没有利用 micro-app 的能力

但也有好处

  • 简单,团队都能理解
  • 子应用可以独立运行
  • 刷新页面不丢数据

后续有时间可能会改成用 micro-app 的setGlobalData,但目前这样也能用。

五、部署

每个应用还是独立部署,只是 Nginx 配置需要调整一下。

基座应用

server { listen 80; location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; } }

子应用

server { listen 80; location /child/main { root /usr/share/nginx/html; try_files $uri $uri/ /child/main/index.html; } }

六、踩过的坑

6.1 静态资源 404

子应用的图片加载不出来,因为路径变了。

解决:确保public-path.ts配置正确,而且要放在入口文件最前面 import。

6.2 路由跳转 URL 不变

子应用内部跳转后,浏览器地址栏没变化。

解决:路由的 base 要用window.__MICRO_APP_BASE_ROUTE__

6.3 热更新有问题

开发时子应用热更新会导致页面白屏。

解决:子应用关闭热更新hot: false。有点麻烦,但暂时没找到更好的办法。

6.4 样式偶尔会串

虽然 micro-app 有样式隔离,但有些全局样式还是会影响。

解决:尽量用 scoped 样式,避免写太通用的选择器。

七、目前的效果

改造完成后:

  • ✅ 用户可以在一个页面里切换不同的系统,不用重新加载
  • ✅ 各个子应用还是可以独立开发、独立部署
  • ✅ 子应用也可以单独访问(方便开发调试)

还存在的问题:

  • ⚠️ 状态共享方案不够优雅
  • ⚠️ 没有用到 micro-app 的很多高级功能(预加载、keep-alive 等)
  • ⚠️ 首次加载子应用还是有点慢

八、后续想做的

  1. 研究一下预加载:micro-app 支持 preFetch,应该能提升切换速度
  2. 优化状态共享:看看能不能用 micro-app 的全局数据机制
  3. 统一技术栈:慢慢把 Vue 2 的项目升级到 Vue 3

九、一些想法

做完这次改造,有几点感受:

  1. 微前端不是银弹。如果项目本身就不大,或者团队就几个人,可能真没必要搞这么复杂。

  2. 先跑起来再说。一开始不要想着做到完美,能用就行,后面再慢慢优化。

  3. 保持子应用的独立性。我觉得这点很重要,子应用能独立运行,开发调试都方便很多。

  4. 文档很重要。我们内部写了一份接入文档,新同事照着做基本都能跑起来。

十、参考资料

  • micro-app 官方文档
  • micro-app GitHub

以上就是这次微前端改造的记录。如有错误或者更好的方案,欢迎评论区交流~

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询