初识Webpack5联邦模块Module Federation

722 阅读2分钟

webpack5推出的新特性联邦模块,允许在不同项目之间通过CDN共享模块,解决了应用间共享模块的问题,相对于npm包共享的方式更加的便利,可以直接通过CDN来共享模块;

模块共享方式对比

 方式优势 不足 
 NPM1、共享模块 2、支持TS1、组件改动后,需要通知每个依赖该组件的项目去重新编译上线 2、需要将组件安装,再从node_modules引入使用
 UMD/CDN(大部分SDK实现方式,将变量挂载到全局上)1、共享模块 2、runtime(运行时)加载模块1、共享的模块和项目无法通过webpack进一步编译优化 2、无法共享TS
 模块联邦 Module Federation1、共享模块 2、模块升级无需每个项目重新编译上线 3、共享模块和项目可以一起编译,方便进行公共模块提取或者压缩编译优化 1、不支持共享TS,需要再Host收到维护远程模块的类型 2、需要确保共享模块的健壮性,因为其本身的改动升级会直接影响所有依赖它的项目,这一点是优势也是不足 3、需确保消费和被消费的项目Webpack都升级到webpack5

模块共享方式图示对比

模块联邦如何使用?

  

Host:主模块,当消费远程模块时,其被称为Host

Remote:远程模块,当其被消费时,就是Remote远程模块;

一个模块既可以当主模块也可以当远程模块

API说明:

name: 当前应用名称,需要全局唯一

remotes:  作为host时,声明消费哪些模块

exposes:  作为remote(远程模块)时,导出的具体模块

shared:强制远程(Remotes)模块使用主模块(Host)的依赖项,当主模块没有该依赖项时,会直接使用远程模块自身的依赖;

// A项目的配置

const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

module.exports = {
  // other webpack configs...
  plugins: [
    new ModuleFederationPlugin({
      name: "app_A",
      remotes: {
        moduleB: "moduleB@https://localhost:3001/moduleB.js",
        moduleC: "moduleC@https://localhost:3002/moduleC.js"
      },
      shared: ["react", "react-dom", "react-router-dom"]
    }),
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      chunks: ["main"]
    })
  ]
};

// A项目使用远程模块 from格式'remotes的Key/远程模块exposes的key'
import ModuleB from 'moduleB/list';  


// B项目的配置



const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

module.exports = {
  // other webpack configs...
  plugins: [
    new ModuleFederationPlugin({
      name: "app_B",
      remotes: {
        moduleC: "moduleC@https://localhost:3002/moduleC.js"
      },

     filename: 'moduleB.js',


     exposes:{

        list: './src/components/ModuleB.vue'


     },

       shared: ["react", "react-dom", "react-router-dom"]

     }),
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      chunks: ["main"]
    })
  ]
};




// C项目的配置
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

module.exports = {
  // other webpack configs...
  plugins: [
    new ModuleFederationPlugin({
      name: "app_C",
      filename: 'moduleC.js',
      exposes:{
        search: './src/components/ModuleC.vue'
      }
    }),
    new HtmlWebpackPlugin({
      template: "./public/index.html",
      chunks: ["main"]
    })
  ]
};