记一次Vite 项目引入模块联邦

前言

Module Federation 中文直译为"模块联邦",而在 webpack 官方文档中,其实并未给出其真正含义,但给出了使用该功能的 motivation, 即动机,翻译成中文

多个独立的构建可以形成一个应用程序。这些独立的构建不会相互依赖,因此可以单独开发和部署它们。这通常被称为微前端,但并不仅限于此。

该功能很好的解决了多应用模块复用的问题,相比之前的发布成npm包或者使用iframe的方式,更加优雅和灵活。

webpack中可以实现该功能,那么在vite项目中可以实现吗?答案是当然可以啦!!!

如何配置模块联邦

MF 引出下面两个概念:

  • Host:引用了其他应用模块的应用, 即当前应用
  • Remote:被其他应用使用模块的应用, 即远程应用

实战

第一步

先用vite创建两个项目,项目名就叫app1和app2。

在app1中安装如下依赖

sql 复制代码
yarn add @originjs/vite-plugin-federation --dev
yarn add vite-plugin-top-level-await --dev

在app2中安装如下依赖

sql 复制代码
yarn add @originjs/vite-plugin-federation --dev

第二步

在app1项目中vite.config.js配置如下

js 复制代码
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import federation from "@originjs/vite-plugin-federation";
import topLevelAwait from 'vite-plugin-top-level-await'

export default defineConfig({
  plugins: [
    vue(),
    federation({
      name: 'app1',
      filename: 'remoteEntry.js',
      // Modules to expose
      exposes: {
          './Button': './src/Button.vue',
      },
      shared: {
        vue:{
          generate:false
        }
      }
  }),
  // 重要
  topLevelAwait({
    // The export name of top-level await promise for each chunk module
    promiseExportName: "__tla",
    // The function to generate import names of top-level await promise in each chunk module
    promiseImportName: i => `__tla_${i}`
  })
  ]
})

在app1项目中src目录下创建一个组件,叫Button.vue

vue 复制代码
<template>
    <button>确定</button>
</template>
  
<script setup>
  import {onMounted} from 'vue'

  onMounted(()=>{
    console.log('vue3 mf')
  })
</script>
  
<style>
  

第三步

在app2项目中vite.config.ts配置如下

ts 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import federation from "@originjs/vite-plugin-federation";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    federation({
      name: 'host-app',
      remotes: {
          // 注意该路径,写错了可能会在项目中无法引用到远端组件
          app1: "http://localhost:5173/dist/assets/remoteEntry.js",
      },
      shared: ['vue']
  })
  ],
})

在app2项目的main.ts中引入远端组件

ts 复制代码
import App from './App.vue'

import { createApp, defineAsyncComponent } from "vue";
const app = createApp(App);

const RemoteButton = defineAsyncComponent(() => import("app1/Button"));
app.component("RemoteButton", RemoteButton);
app.mount("#app");

然后在app2项目的App组件中使用RemoteButton组件即可

注意:在使用前需要先把app1项目build一次,不能同时在开发环境下使用。由于 Vite 是按需编译,所以 app1 必须先打包启动,2 个 App 无法同时是开发模式。

之后启动app2项目就可以看到正常能加载app1项目中的组件了,可以完美复用。

参考资料

  1. www.npmjs.com/package/@or...
  2. github.com/originjs/vi...
相关推荐
一只韩非子6 分钟前
AI时代,程序员如何优雅地搞定页面设计?
前端·ai编程
新中地GIS开发老师12 分钟前
2025Mapbox零基础入门教程(14)定位功能
前端·javascript·arcgis·gis·mapbox·gis开发·地理信息科学
tager15 分钟前
Vue 3 组件开发中的"双脚本"困境
前端·vue.js·代码规范
烛阴1 小时前
Int / Floor
前端·webgl
excel1 小时前
使用 PWA 时,为什么你必须手动添加更新逻辑,否则会报错?
前端
Moment1 小时前
Node.js 这么多后端框架,我到底该用哪个?🫠🫠🫠
前端·后端·node.js
尚学教辅学习资料1 小时前
SpringBoot3.x入门到精通系列: 2.3 Web开发基础
前端·springboot·web开发
han_2 小时前
前端遇到页面卡顿问题,如何排查和解决?
前端·javascript·性能优化
拾光拾趣录3 小时前
H5适配9大高频题连环炸!第3问90%人翻车?
前端·面试
拾光拾趣录3 小时前
给Electron-Claude应用构建全面的数据统计体系 - 从0到1的实践总结
前端·electron