Webpackwebpack5 模块联邦(Module Federation)

Posted 嘻嘻的妙妙屋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Webpackwebpack5 模块联邦(Module Federation)相关的知识,希望对你有一定的参考价值。

webpack5 模块联邦(Module Federation)

Webpack 5 增加了一个新的功能 “模块联邦”,它允许多个 webpack 构建一起工作。 从运行时的角度来看,多个构建的模块将表现得像一个巨大的连接模块图。 从开发者的角度来看,模块可以从指定的远程构建中导入,并以最小的限制来使用。

多个独立的构建可以组成一个应用程序,这些独立的构建之间不应该存在依赖关系,因此可以单独开发和部署它们。这通常被称作微前端,但并不仅限于此。

Webpack5 模块联邦让 Webpack 达到了线上 Runtime 的效果,让代码直接在项目间利用 CDN 直接共享,不再需要本地安装 Npm 包、构建再发布了! 我们知道 Webpack 可以通过 DLL 或者 Externals 做代码共享时 Common Chunk, 但不同应用和项目间这个任务就变得困难了,我们几乎无法在项目之间做到按需热插拔。

模块联邦可以将一个应用的包应用于另一个应用,同时具备整体应用一起打包的公共依赖抽取能力。

举个例子

假设我们现在有两个项目模块,分别是项目A以及项目B,我们需要在项目模块A中应用项目模块B。

项目模块B

webpack.config.js

const htmlWebpackPlugin = require('html-webpack-plugin');
const  ModuleFederationPlugin  = require('webpack').container;

module.exports = 
  mode: 'production',
  entry: './src/index.js',
  devServer: 
    port: '3001',
  ,
  plugins: [
    new HtmlWebpackPlugin(),

    new ModuleFederationPlugin(
      // 模块联邦名字,提供给其他模块使用
      name: 'app2',
      // 提供给外部访问的资源入口
      filename: 'App2RemoteEntry.js',
      // 引用的外部资源列表
      remotes: ,
      // 暴露给外部的资源列表
      exposes: 
        /**
         *  ./Header 是让外部应用使用时基于这个路径拼接引用路径,如:App2/Header
         *  ./src/Header.js 是当前应用的要暴露给外部的资源模块路径
         */
        './Header': './src/Header.js',
      ,
      // 共享模块,值当前被 exposes 的模块需要使用的共享模块,如lodash
      shared: ,
    ),
  ],
;

项目模块A

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const  ModuleFederationPlugin  = require('webpack').container;

module.exports = 
  mode: 'production',
  entry: './src/index.js',
  devServer: 
    port: '3000',
  ,
  plugins: [
    new HtmlWebpackPlugin(),

    new ModuleFederationPlugin(
      // 模块联邦名字,提供给其他模块使用
      name: 'app1',
      // 提供给外部访问的资源入口
      filename: 'App1RemoteEntry.js',
      // 引用的外部资源列表
      remotes: 
        /**
         *  App2 引用其他应用模块的资源别名
         *  app2 是 APP2 的模块联邦名字
         *  http://localhost:3001 是 APP2 运行的地址
         *  App2RemoteEntry.js 是 APP2 提供的外部访问的资源名字
         *  可以访问到 APP2 通过 exposes 暴露给外部的资源
         */
        App2: 'app2@http://localhost:3001/App2RemoteEntry.js',
      ,
      // 暴露给外部的资源列表
      exposes: ,
      // 共享模块,如lodash
      shared: ,
    ),
  ],
;

src/index.js

import Home from './Home';

/**
 *  需要异步导入
 *  App2 为 remotes 中定义的资源别名
 *  ./Header 为 APP2 exposes 定义的 ./Header
 */

import('App2/Header').then((Header) => 
  const body = document.createElement('div');
  body.appendChild(Header.default());
  document.body.appendChild(body);
);

APP1 执行 npx webpack 可以看到 dist/main.js 包含了 APP1 的 Header 模块,它依然是通过 CDN 引入的,APP1 执行 npx webpack serve 可以看到模块联邦使用成功!验证了模块联邦可以将一个应用的包应用于另一个应用,同时具备整体应用一起打包的公共依赖抽取的能力。

总结

试想一下,你有一个组件包通过 npm 发布后,你的10个业务项目引用这个组件包。当这个组件包更新了版本,你的10个项目想要使用最新功能就必须一一升级版本、编译打包、部署,这很繁琐。但是模块联邦让组件包利用CDN的方式共享给其他项目,这样一来,当你到组件包更新了,你的10个项目中的组件也自然更新了。

以上是关于Webpackwebpack5 模块联邦(Module Federation)的主要内容,如果未能解决你的问题,请参考以下文章

webpack模块联邦

Fate1.6 支持的机器学习算法

webpack5模块联邦

webpack5模块联邦

Python入门指南3,模块

云原生联邦学习平台 KubeFATE 原理详解