基于 Webpack Module Federation 的 Vue 微前端实践

260 阅读4分钟

Vue 微前端实践项目

基于 Webpack Module Federation 的 Vue 微前端架构实践,实现独立开发、独立部署、模块共享的前端微服务方案。

项目简介

本项目通过 Webpack 5 的 Module Federation 特性实现了微前端架构,包含三个应用:

  • 宿主应用(host-app):提供统一入口和导航,负责加载和管理微应用
  • 用户模块(user-app):独立的用户管理模块,暴露用户列表和用户详情组件
  • 订单模块(order-app):独立的订单管理模块,暴露订单列表组件

三个应用共享 Vue 和 Vue Router 依赖,避免重复加载,提升性能。

技术栈

  • Vue 3
  • Vue Router 4
  • Webpack 5 (Module Federation)
  • Vue CLI

项目结构

vue-module-federation/
├── host-app/             # 宿主应用
│   ├── src/              # 源代码
│   ├── package.json      # 项目依赖
│   └── vue.config.js     # Webpack 配置
├── user-app/             # 用户模块应用
│   ├── src/              # 源代码
│   ├── package.json      # 项目依赖
│   └── vue.config.js     # Webpack 配置
└── order-app/            # 订单模块应用
    ├── src/              # 源代码
    ├── package.json      # 项目依赖
    └── vue.config.js     # Webpack 配置

快速开始

1. 安装依赖

需要分别为三个应用安装依赖:

# 安装宿主应用依赖
cd host-app
npm install

# 安装用户模块依赖
cd ../user-app
npm install

# 安装订单模块依赖
cd ../order-app
npm install

2. 启动应用

需要同时启动三个应用,它们将运行在不同的端口:

方法一:使用多个终端分别启动

# 终端 1:启动宿主应用
cd host-app
npm run serve

# 终端 2:启动用户模块
cd user-app
npm run serve

# 终端 3:启动订单模块
cd order-app
npm run serve

方法二:使用根目录提供的并行启动脚本(推荐)

项目根目录已配置了便捷的脚本,可以一键安装所有依赖并启动所有应用:

# 在项目根目录执行

# 安装所有应用的依赖(仅第一次需要)
npm install
npm run install:all

# 同时启动所有三个应用
npm run serve:all

# 同时构建所有三个应用(用于生产环境)
npm run build:all

这些脚本使用了 concurrently 工具来并行启动多个服务,极大地简化了开发流程。

3. 访问应用

启动成功后,打开浏览器访问:http://localhost:8080

在首页可以看到系统介绍,点击顶部导航栏可以访问用户管理和订单管理模块,这些模块内容来自于远程应用。

构建部署

1. 构建应用

为每个应用执行构建命令:

# 构建宿主应用
cd host-app
npm run build

# 构建用户模块
cd ../user-app
npm run build

# 构建订单模块
cd ../order-app
npm run build

2. 部署配置

构建完成后,需要将各应用的构建产物部署到服务器或 CDN。部署时需要注意:

  1. 确保各应用的 publicPath 配置正确(在 vue.config.js 中)
  2. 确保宿主应用能够正确访问到远程应用的 remoteEntry.js 文件
  3. 生产环境下,建议将共享依赖(如 Vue、Vue Router)抽离到 CDN,进一步减少重复加载

核心配置说明

宿主应用(host-app)配置

vue.config.js 中,通过 remotes 配置声明了要加载的远程应用:

new ModuleFederationPlugin({
  name: 'hostApp',
  remotes: {
    userApp: 'userApp@http://localhost:8081/remoteEntry.js',
    orderApp: 'orderApp@http://localhost:8082/remoteEntry.js'
  },
  shared: {
    vue: { singleton: true, requiredVersion: require('./package.json').dependencies.vue },
    'vue-router': { singleton: true, requiredVersion: require('./package.json').dependencies['vue-router'] }
  }
})

远程应用(user-app/order-app)配置

在远程应用的 vue.config.js 中,通过 exposes 配置声明了要暴露的模块:

new ModuleFederationPlugin({
  name: 'userApp',
  filename: 'remoteEntry.js',
  exposes: {
    './UserList': './src/components/UserList.vue',
    './UserDetail': './src/views/UserDetail.vue'
  },
  shared: {
    vue: { singleton: true, requiredVersion: require('./package.json').dependencies.vue },
    'vue-router': { singleton: true, requiredVersion: require('./package.json').dependencies['vue-router'] }
  }
})

动态加载远程组件

在宿主应用的路由配置中,通过动态导入加载远程组件:

const UserList = () => import('userApp/UserList')
const OrderList = () => import('orderApp/OrderList')

注意事项

  1. 版本一致性:确保各应用使用的共享依赖版本兼容
  2. 跨域问题:开发环境下,需要在远程应用的 devServer 中配置 Access-Control-Allow-Origin: *
  3. singleton 配置:Vue 等框架类依赖必须设置 singleton: true,确保全局只有一个实例
  4. 构建顺序:生产环境部署时,建议先部署远程应用,再部署宿主应用
  5. 热更新:Module Federation 与 HMR 结合使用时,可能需要额外配置以获得最佳开发体验

常见问题

Q: 远程组件加载失败怎么办?

A: 检查以下几点:

  • 远程应用是否已启动
  • 远程应用的端口和 publicPath 是否配置正确
  • 宿主应用的 remotes 配置是否正确指向远程应用的 remoteEntry.js
  • 检查浏览器控制台是否有跨域错误

Q: 为什么修改了远程应用的代码,宿主应用没有更新?

A: Module Federation 依赖远程应用的构建产物,修改代码后需要重新构建或启动开发服务器,才能在宿主应用中看到更新。