记一次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...
相关推荐
星星会笑滴3 分钟前
vue+node+Express+xlsx+emements-plus实现导入excel,并且将数据保存到数据库
vue.js·excel·express
彭世瑜23 分钟前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund40424 分钟前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish24 分钟前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five25 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序26 分钟前
vue3 封装request请求
java·前端·typescript·vue
临枫54126 分钟前
Nuxt3封装网络请求 useFetch & $fetch
前端·javascript·vue.js·typescript
RAY_CHEN.27 分钟前
vue3 pinia 中actions修改状态不生效
vue.js·typescript·npm
酷酷的威朗普27 分钟前
医院绩效考核系统
javascript·css·vue.js·typescript·node.js·echarts·html5
前端每日三省27 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript