从前有匹马叫代码
心若没有栖息的地方,到哪里都是流浪

今天查阅Rsbuild的文档,发现有一个菜单“模块联邦”,从来没听说过,便点进去看一看究竟,官方说法如下:

Module Federation 是一种 JavaScript 应用分治的架构模式(类似于服务端的微服务),它允许你在多个 JavaScript 应用程序(或微前端)之间共享代码和资源。

Rspack 团队与 Module Federation 的开发团队密切合作,并为 Module Federation 提供一流的支持。

也就是说这个是可以跨项目共享代码和资源的,听起来好像微前端架构?但是模块联邦与之前的微前端方案略有不同,区别在我看来主要是是这个:

 模块联邦 并不会借助类似iframe或者shadow dom的方案来实现代码之间的共享,而是采用了script 插入远程 js chunk 入口, 然后通过创建新的 ExternalModule 模块去加入核心的动态加载模块的 runtime 代码

那么今天借着这个机会正好学一下,模块联邦在rsbuild中如何使用,以及记录一下坑

首先通过rsbuild脚手架创建两个项目:

pnpm create rsbuild@latest

然后我这里选择的是vue3框架,根据官网配置模块联邦模块联邦 - Rsbuild,然后坑点来了,

基座应用跟远程应用的入口必须采用动态import格式,否则会报错:

 解决这个问题,首先在src下创建一个bootstrap.js文件,然后将index.js中的内容粘到bootstrap.js中,最后在index.js中

import("./bootstrap")

基座应用的rsbuild.config.js如下:

import { defineConfig } from '@rsbuild/core';
import { pluginVue } from '@rsbuild/plugin-vue';

export default defineConfig({
  plugins: [pluginVue()],
  moduleFederation:{
    options:{
      name:"root",
      remotes:{
        'child':'child@http://localhost:3001/entry.js'
      },
      shared:{
        vue:{
          singleton:true,
        }
      }
    }
  }
});

子应用的rsbuild.config.js如下:

import { defineConfig } from "@rsbuild/core";
import { pluginVue } from "@rsbuild/plugin-vue";
export default defineConfig({
  plugins: [pluginVue()],
  server: {
    port: 3001,
  },
  moduleFederation:{
    options:{
      name:'child',
      exposes:{
        './MButton.vue':'./src/MButton.vue'
      },
      filename:'entry.js',
      shared:{
        vue:{
          singleton:true,
        }
      }
    }
  }
});

需要注意的一点是,子应用的exposes中"./MButton",必须要用./相对路径开头,如果直接写MButton.vue,则会报错:

 最后在基座应用中,这样使用:

<template>
  <div class="content">
    <h1>主应用</h1>
    <p>Start building amazing things with Rsbuild.</p>

    <MButtonFromChild text="主应用使用" @clicked="onClick" />
  </div>
</template>


<script setup lang="ts">
import { defineAsyncComponent } from 'vue';

const MButtonFromChild = defineAsyncComponent(()=>import('child/MButton.vue'))


function onClick() {
  console.log('主应用点击')
}

</script>

<style scoped>
.content {
  display: flex;
  min-height: 100vh;
  line-height: 1.1;
  text-align: center;
  flex-direction: column;
  justify-content: center;
}

.content h1 {
  font-size: 3.6rem;
  font-weight: 700;
}

.content p {
  font-size: 1.2rem;
  font-weight: 400;
  opacity: 0.5;
}
</style>

最后来看看效果:

 DONE!

posted on 2024-10-24 20:10  从前有匹马叫代码  阅读(69)  评论(0编辑  收藏  举报