Introduction to webpack federation module and sorting out problems in dumi

15941973:

Tip: After the article is written, the table of contents can be automatically generated. How to generate it can refer to the help document on the right


foreword

Module Federation refers to a technique for building micro-frontend architectures that allows different independent builds (independent front-end applications or modules) to dynamically share code and modules at runtime. This mode allows multiple teams to independently develop and deploy their own front-end applications, and at the same time, they can load and share each other's modules through the network at runtime to realize dynamic connection and interaction of modules.

In the micro front-end architecture, each independent front-end application can be regarded as an autonomous module, and these modules can be integrated through the mechanism of federated modules to form an overall front-end application. Federation modules allow dependencies, code, and state to be shared between modules, enabling better code reuse, higher development efficiency, and better team collaboration.

Webpack's ModuleFederationPlugin is a tool for implementing federated modules, which allows you to specify which modules can be shared and how to dynamically load these shared modules at runtime when building individual front-end applications. This approach can make the development and deployment of front-end applications more flexible and efficient.

In this article, we will introduce the meaning of the parameters of ModuleFederationPlugin, and sort out the problems and solutions encountered when using ModuleFederationPlugin in dumi.


1. What are the parameters of ModuleFederationPlugin?

The commonly used fields and their meanings are listed below

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 
        },
      }
    }),
  ],
};

2. How to use it in dumi and sort out problems

1. How to use it in dumi (this configuration is easy to use)

remote side:

    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 side:

  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. Organize related issues

2.1 Question 1

Problem Description:

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

Solution:

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

2.2 Question 2

Problem Description:

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

Because the error is that useMeme cannot be read, we try to share react. At this time, we found that the error report has changed, and the content of the error report is as follows:
注意:要在host和react同时共享,否则即使执行了下边的插件也不好使

Error: Shared module is not available for eager consumption

This problem is quite common, including official documents that also provide solutions. For details, see this link . The general idea is that a bootstrap file needs to be added. This is relatively easy to solve in our normal react projects, just follow the official documentation, but in dumi, how should we find the entry file?
After some searching, we found that some students solved this problem with the help of the umi-plugin-mf-bootstrap plug-in ( link to the original text ). After trying it, we found that there was no solution. We suspect that there is a high probability that there is a problem with the entry file, so after many attempts, Solved this problem by writing a local plug-in, the plug-in content is as follows:
如果想要尝试umi-plugin-mf-bootstrap插件,但umi版本是3.5+,需要在.dumirc.ts手动配置插件,这个配置是在大部分文章中没有提到的。 配置可参考:https://umijs.org/docs/guides/use-plugins

// @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")',
    });
  });
};

The plugin needs to be placed in this location
insert image description here


Summarize

There are still many pitfalls in dumi, and there are few ways to seek help when encountering problems. I hope this article can give some help to friends who are or will be using dumi+federal modules.

おすすめ

転載: blog.csdn.net/qq_39544148/article/details/131947186