简介

Module federation 解决了一次构建可以拆分为多次构建的问题,并且构建产物也可以为其他应用提供服务。

本质上 webpack 的能力是用来增强不同 bundle 之间 code sharing  的能力。

 

Multiple separate builds should form a single application. These separate builds should not have dependencies between each other, so they can be developed and deployed individually.

This is often known as Micro-Frontends, but is not limited to that.

多个独立的构建可以形成一个应用程序。这些独立的构建不会相互依赖,因此可以单独开发和部署它们。这通常被称为微前端,但并不仅限于此。

概念

从官网的描述可以简单看出,MF 希望做的事情就是将多个独立部署构建的应用合并成一个。因此,MF 引出下面

概念:

Container: 一个被模块联邦插件打包出来的模块称为一个 Container, 他可以被其他的 bundle 进行消费的。

host应用:消费 webpack 构建出的 Container 的 module。(引用了其他应用的应用)
remote应用:被消费的 Container.(被其他应用所使用的应用)

使用

MF 是webpack5 自带的,我们只需要创建一个 ModuleFederationPlugin 即可,简单的配置如下:

name:应用名称,当作为 remote 被引用是,路径为 ${name}/${expose}
library:声明全局变量的方式,name为umd的name

filename:构建输出的文件名
remotes:远程引用的应用名及其别名的映射,使用时以key值作为name,host 应用需要配置

exposes:被远程引用时可暴露的资源路径及其别名,rremote 应用需要配置
shared:与其他应用之间可以共享的第三方依赖,使你的代码中不用重复加载同一份依赖

配置

const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
	// 其他配置
    plugins: [
      new ModuleFederationPlugin({
        name: 'website2', // remote 子应用名称
        library: { type: 'var', name: 'website2' },//声明全局变量的方式umd, cjs,name为umd的name
        filename: 'remoteEntry.js', // 打包出的文件名
        exposes: {
          './router': './src/entries/router.ts',
          './public-path': './config/public-path.js',
          ...appComponents,
          },
        // 优先用 Host 的依赖,如果 Host 没有,再用自己的
        shared: ['react', 'react-dom']
      }),
  ],
}

  

使用

获取远程应用的模块

import ('dpapp_catalog/router').then(data => {
	// console.log(data); // 远程子应用模块
})
import React, { lazy, Suspense, useState } from 'react';
import Footer from './Footer';
import Footer2 from 'website2/Footer'; // federated

const Title = lazy(() => import('website2/Title')); // federated

export default () => {
	return (
		<>
			<Suspense fallback={'fallback'}>
				<Title />
			</Suspense>
		
			<Footer />
			<Footer2 />
		</>
	);
};