Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webpack5 模块联邦 #20

Open
ZhenHe17 opened this issue Apr 22, 2020 · 4 comments
Open

webpack5 模块联邦 #20

ZhenHe17 opened this issue Apr 22, 2020 · 4 comments
Labels

Comments

@ZhenHe17
Copy link
Owner

ZhenHe17 commented Apr 22, 2020

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"]
    }),

介绍一下用到的配置

  • name 模块名
  • library 这个配置比较迷,目前看到的用法有 { type: "var" } { type: "commonjs-module" },可以用来指定模块的使用规范
  • remotes 需要依赖的模块名
  • filename app1 使用 app2 模块的入口,app1 需要先加载 remoteEntry.js
  • exposes app2 暴露出的模块,可以有多个
  • shared app2 打包暴露模块时,不会将 shared 打包,app2 的 Button 将使用 app1 里的 react

怎么实现的跨应用依赖

首先通过上面的配置,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
Copy link

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

@ZhenHe17
Copy link
Owner Author

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

@flyingbirdhub
Copy link

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

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

@ZhenHe17
Copy link
Owner Author

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

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants