记一次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...
相关推荐
hackeroink1 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者3 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-3 小时前
验证码机制
前端·后端
燃先生._.4 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖5 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235245 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240256 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar6 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人7 小时前
前端知识补充—CSS
前端·css