记一次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...
相关推荐
xiao-xiang几秒前
jenkins-通过api获取所有job及最新build信息
前端·servlet·jenkins
C语言魔术师17 分钟前
【小游戏篇】三子棋游戏
前端·算法·游戏
匹马夕阳1 小时前
Vue 3中导航守卫(Navigation Guard)结合Axios实现token认证机制
前端·javascript·vue.js
你熬夜了吗?1 小时前
日历热力图,月度数据可视化图表(日活跃图、格子图)vue组件
前端·vue.js·信息可视化
桂月二二8 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
沈梦研9 小时前
【Vscode】Vscode不能执行vue脚本的原因及解决方法
ide·vue.js·vscode
hunter2062069 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb9 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角9 小时前
CSS 颜色
前端·css
轻口味9 小时前
Vue.js 组件之间的通信模式
vue.js