记一次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...
相关推荐
用户2181697049308 分钟前
Flutter(十)Container Center Align
前端
小p18 分钟前
nextjs学习9: Next.js 渲染与缓存
前端·后端
乘风gg19 分钟前
AI 时代,你的编程能力在第几层?我敢说,大多数人卡在第一层
前端·ai编程·claude
东风破_20 分钟前
React Router v7 实战:用路由配置、懒加载与嵌套路由搭建一个完整的 SPA
前端
引山洪0820 分钟前
Babylon.js 8.x 中文文档整理——Node篇 (上)
前端·webgl
柒和远方22 分钟前
V058:前端路由的第一性原理:从 hashchange 手写路由,到 React Router 的嵌套与懒加载
前端·javascript·react.js
计算机魔术师23 分钟前
阿里云上线 One Key MCP 服务:兼容 Qoder、Codex 等,可一键调用多家 MCP 服务
前端
Darling噜啦啦25 分钟前
React Router 全家桶实战:从路由懒加载到嵌套路由的 6 大核心玩法
前端·react.js
Goodbye26 分钟前
组件详解:从起源到未来的全方位解读
前端
无糖可可果28 分钟前
从前端路由的起源到 React Router 实战
前端