webpack联邦模块介绍及在dumi中使用问题整理

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

联邦模块(Module Federation)是指一种用于构建微前端架构的技术,它允许不同的独立构建(独立的前端应用或模块)在运行时动态地共享代码和模块。这种模式可以让多个团队独立开发和部署自己的前端应用,同时能够在运行时通过网络加载和共享彼此的模块,实现模块的动态联接和交互。

在微前端架构中,每个独立的前端应用可以被看作是一个自治的模块,这些模块可以通过联邦模块的机制进行集成,形成一个整体的前端应用。联邦模块允许各个模块之间共享依赖、代码和状态,从而实现更好的代码复用、更高的开发效率和更好的团队协作。

Webpack的ModuleFederationPlugin是实现联邦模块的一种工具,它可以让你在构建各个独立的前端应用时,指定哪些模块可以被共享,以及如何在运行时动态加载这些共享模块。这种方式可以使得前端应用的开发和部署更加灵活和高效。

本文我们将介绍一下ModuleFederationPlugin各参数的含义,并且整理一下在dumi中使用ModuleFederationPlugin时遇到的问题及解决方案。


一、ModuleFederationPlugin参数含义?

以下将列举一下常用的字段及其含义

js 复制代码
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'xxx',  // 模块的名称,用于标识模块的唯一性
      filename: 'xxxx.js', // 模块的文件名,用于指定模块的输出路径
      exposes: { // 定义模块中要共享的部分。
        './module1': './src/module1.index.tsx', // ./指的是根目录
        './module2': './src/module2.index.tsx'
      },
      shared: {
        react: {
          requiredVersion: '^18.2.0',  // package.json中要求的版本号
          singleton: true, // 布尔值。此提示只允许共享作用域中有一个共享模块的实例(默认禁用)。一些库使用全局内部状态(例如react,react-dom)。因此,同时只能有一个库的实例运行非常重要。
          eager: true, // 布尔值。此提示允许Webpack在初始块中直接包含所提供的模块和备用模块,而不是通过异步请求获取库。换句话说,这允许在初始加载时使用共享模块。但请注意,启用此提示将始终下载所有提供的和备用模块。
        },
        'react-dom': {
          requiredVersion: '^18.2.0',
          singleton: true 
        },
      }
    }),
  ],
};

二、如何在dumi中使用及问题整理

1. 如何在dumi中使用(这个配置是好使的)

remote端:

js 复制代码
    new ModuleFederationPlugin({
      name: 'components',
      filename: 'index.js',
      exposes: {
        './module1': './src/module1.index.tsx',
        './module2': './src/module2.index.tsx'
      },
      shared: {
        react: { requiredVersion: '^18.2.0', singleton: true },
        'react-dom': { requiredVersion: '^18.2.0', singleton: true },
      },
    }),

host端:

js 复制代码
  chainWebpack(memo: any, { webpack }: any) {
    memo
      .plugin('ModuleFederationPlugin')
      .use(webpack.container.ModuleFederationPlugin, [
        {
          name: 'docs',
          remotes: {
            components: 'components@http://172.16.3.19:3001/index.js',
          },
          shared: {
            react: { singleton: true, eager: true },
          },
        },
      ]);
  },

2.相关问题整理

2.1 问题1

问题描述:

bash 复制代码
error - MFSU dist file: /Users/xxxx/test/doc/node_modules/.cache/mfsu/mf-va_remoteEntry.js not found
error - MFSU latest build error:  AssertionError [ERR_ASSERTION]: dependence not found: xxxx

解决方法:

js 复制代码
// 应该是mfsu和联邦模块有冲突,所以关闭
export default defineConfig({
  mfsu: false,
})

2.2 问题2

问题描述:

bash 复制代码
# 经测试,此处不光是useMemo会报错,所有的hook均会报错,不使用react hooks是不会报错的
Cannot read properties of null (reading 'useMemo')

因为报错是读不到useMeme, 所以我们尝试共享react。此时,我们发现报错有变化,报错内容如下:
注意:要在host和react同时共享,否则即使执行了下边的插件也不好使

bash 复制代码
Error: Shared module is not available for eager consumption

这个问题还是比较常见的,包括官方文档也提供有解决方案, 详情见此链接,大意就是需要增加一个bootstrap文件。这个在咱们正常的react项目都比较容易解决,按官方文档来就可以,但是dumi中,我们应该怎么去找入口文件呢?

经过一番查找,我们发现有部分同学借助umi-plugin-mf-bootstrap这个插件解决了这个问题(原文链接)经尝试后发现没有解决,怀疑大概率是入口文件出问题,所以经过多次尝试,通过写了一个本地插件解决了此问题,插件内容如下:
如果想要尝试umi-plugin-mf-bootstrap插件,但umi版本是3.5+,需要在.dumirc.ts手动配置插件,这个配置是在大部分文章中没有提到的。 配置可参考:https://umijs.org/docs/guides/use-plugins

ts 复制代码
// @ts-nocheck
import { IApi } from '@umijs/types';
import { resolve } from 'path';
import { readFileSync } from 'fs';

export default (api: IApi) => {
  api.onGenerateFiles(() => {
    const path_tb =
      api.env === 'production'
        ? './.dumi/tmp-production/testBrowser.ts'
        : './.dumi/tmp/testBrowser.tsx';
    const TBBuffer = readFileSync(resolve(path_tb));
    const TBContent = String(TBBuffer);

    const path_umi =
      api.env === 'production'
        ? './.dumi/tmp-production/umi.ts'
        : './.dumi/tmp/umi.ts';
    const umiBuffer = readFileSync(resolve(path_umi));
    const umiContent = String(umiBuffer);

    api.writeTmpFile({
      path: '../bootstrap_tb.tsx',
      content: TBContent,
    });
    api.writeTmpFile({
      path: '../testBrowser.tsx',
      content: 'import("./bootstrap_tb")',
    });

    api.writeTmpFile({
      path: '../bootstrap_umi.tsx',
      content: umiContent,
    });
    api.writeTmpFile({
      path: '../umi.ts',
      content: 'import("./bootstrap_umi.tsx")',
    });
  });
};

插件需要放到这个位置


总结

在dumi中使用还是有不少小坑的,遇到问题感觉寻求帮助的路径也比较少,希望此篇文章能给正在或者将要使用dumi+联邦模块的朋友们一些帮助吧

相关推荐
小纯洁w14 小时前
Webpack 的 require.context 和 Vite 的 import.meta.glob 的详细介绍和使用
前端·webpack·node.js
海盗强21 小时前
Webpack打包优化
前端·webpack·node.js
祈澈菇凉1 天前
如何优化 Webpack 的构建速度?
前端·webpack·node.js
懒羊羊我小弟1 天前
常用 Webpack Plugin 汇总
前端·webpack·npm·node.js·yarn
祈澈菇凉2 天前
Webpack的持久化缓存机制具体是如何实现的?
前端·webpack·gulp
懒羊羊我小弟3 天前
Webpack 基础入门
前端·webpack·rust·node.js·es6
刽子手发艺3 天前
Selenium+OpenCV处理滑块验证问题
opencv·selenium·webpack
懒羊羊我小弟4 天前
常用Webpack Loader汇总介绍
前端·webpack·node.js
真的很上进5 天前
【1.8w字深入解析】从依赖地狱到依赖天堂:pnpm 如何革新前端包管理?
java·前端·vue.js·python·webpack·node.js·reactjs
SuperherRo7 天前
信息收集-Web应用&JS架构&URL提取&数据匹配&Fuzz接口&WebPack分析&自动化
javascript·webpack·自动化·fuzz