• 【Webpack】webpack5 模块联邦(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: {},
        }),
      ],
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    项目模块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: {},
        }),
      ],
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    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);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

    总结

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

  • 相关阅读:
    【LeetCode】【剑指offer】【顺时针打印矩阵】
    Android 查看路由表
    d唐的导入C的经验
    数据工程师日记:10年职场老鸟,我居然被新人给上了一课
    深入理解 Jetpack Compose 内核:SlotTable 系统
    剑指offer链表篇
    Docker常用命令
    关于美国服务器IP的几个常见问题
    【JavaEE基础与高级 第58章】Java中的单元测试Junit、Junit常用注解、Junit使用的基本流程
    考CISAW的N个理由!
  • 原文地址:https://blog.csdn.net/Jessieeeeeee/article/details/125430619