ZhenHe17 / blog

个人博客,希望能让各位看官有所收获,喜欢可以 star || watch ^_^ 🎉
169 stars 6 forks source link

webpack5 模块联邦 #20

Open ZhenHe17 opened 4 years ago

ZhenHe17 commented 4 years ago

webpack5有一项令人激动的新特性:模块联邦 module federation,看看他能做些什么

应用场景

可以解决跨项目的相互依赖,假设目前有两个项目 app1 和 app2,app1 想使用 app2 项目里的某个组件比如 src/components/Button.js。我们可能会将 components 拆成公共的组件库分别在 app1、app2 里引入,但是维护和更新组件库会比较啰嗦,提取每一个模块也可能会造成过度抽象,但是模块联邦可以无痛解决这个问题。

使用

webpack5 官方文档里还没有相应的介绍,先推荐一个示例仓库 module-federation-examples ,里面有多个场景的完整用例。

简单使用

app1 依赖 app2 的模块:

  // app1/webpack.config.js
    new ModuleFederationPlugin({
      name: "app1",
      library: { type: "var", name: "app1" },
      remotes: {
        app2: "app2"
      },
      shared: ["react", "react-dom"]
    }),
  // app2/webpack.config.js
    new ModuleFederationPlugin({
      name: "app2",
      library: { type: "var", name: "app2" },
      filename: "remoteEntry.js",
      exposes: {
        Button: "./src/Button",
      },
      shared: ["react", "react-dom"]
    }),

介绍一下用到的配置

怎么实现的跨应用依赖

首先通过上面的配置,app2 会打包出体积很小的,记录着 app2 所有模块信息的 remoteEntry.js,app1 需要先引入这份 remoteEntry.js。app1 在运行时,发现依赖了 app2/Button ,此时通过 remoteEntry.js 查找出 Button.js 打包后对应的地址并加载执行就 OK 了。

可以看出,依赖是运行时的,在需要的时候按照 remoteEntry.js 记录的信息来加载模块。remoteEntry.js 体积较小,不应该被缓存,以确保 app1 能够拿到最新的 app2 代码。app2 更新之后,app1 不需要任何修改,就可以使用到新版本的 app2 代码。

pccBo-fe commented 3 years ago

在此种场景下 如何减少远程模块的请求次数呢, 例如: a用了大量的b项目模块,那a在加载时用到的每一个组件都会发起请求

ZhenHe17 commented 3 years ago

@pccBo-fe 可以将b项目整理出一个统一入口文件index.js,通过模块化引入所有b项目的组件。这样a只会加载一次index入口文件,不会发起多次请求

flyingbirdhub commented 3 years ago

@pccBo-fe 可以将b项目整理出一个统一入口文件index.js,通过模块化引入所有b项目的组件。这样a只会加载一次index入口文件,不会发起多次请求

这样的话,如果被多个项目依赖(依赖组件不完全一样),就需要每个项目适配一个index.js,是不是不太通用

ZhenHe17 commented 3 years ago

@pccBo-fe 可以将b项目整理出一个统一入口文件index.js,通过模块化引入所有b项目的组件。这样a只会加载一次index入口文件,不会发起多次请求

这样的话,如果被多个项目依赖(依赖组件不完全一样),就需要每个项目适配一个index.js,是不是不太通用

依赖差距不大的时候可以用同一个入口,差距比较大的时候建议单独封装成私库以按需加载