微前端之 Webpack5 的 module federation

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微前端之 Webpack5 的 module federation相关的知识,希望对你有一定的参考价值。

微前端之 Webpack5 的 module federation

代码在 https://github.com/GoldenaArcher/webpack5-study-case 的 module federation branch 下面,关于其他的配置,可以看 webpack5 查漏补缺系列。

目前的代码配置是这样的:

简单的说一下就是,目前有 3 个项目:

  • hello-world,也就是 home

    remote

  • lion

    remote

  • dashboard

    host

这里的 host 会使用 remote 开放的组件,也就是 home 和 lion 两个页面:

这里导出的是两个页面,但是是机上使用 webpack 也可以导出方法/库让 host 去使用。

remote 配置

remote 的配置如下:

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

module.exports = 
  entry:  lion: './src/lion.js' ,
  output: 
    filename: '[name].[contenthash:8].js',
    path: path.resolve(__dirname, 'dist/'),
    // default for webpack5: publicPath: 'auto'
    // default for webpack4: publicPath: ''
    publicPath: 'http://localhost:9002/',
    clean: true,
  ,
  devServer: 
    port: 9002,
    static: 
      directory: path.resolve(__dirname, './dist'),
    ,
    devMiddleware: 
      index: 'lion.html',
      writeToDisk: true, // by default is false
    ,
  ,
  // ...
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin(
      filename: 'lion.html',
      template: 'src/page-template.hbs',
      title: 'Cute lion',
      description: 'Very cute lion cub',
      chunks: ['lion'],
    ),
    new ModuleFederationPlugin(
      name: 'LionApp',
      filename: 'remoteEntry.js',
      exposes: 
        './LionPage': './src/components/lion-page/lion-page.js',
      ,
    ),
  ],
;

省略了一些不相关的配置,这里最重要的几个配置包括:

  • publicPath

    这里是 webpack 向外暴露的路由,如这个案例中暴露的是 http://localhost:9002/,那么只要使用了 module federation 的插件,那么别的项目就可以使用暴露的对应功能

    另外就是,绝对不能忘了最后一个 /,因为忘了这个我 debug 了好久为什么资源无法访问……

  • devServer

    开发用

  • ModuleFederationPlugin

    这里的配置决定了 remote 中有什么项目会被暴露出去,截至目前的版本,所有的选项都是可选的:

    关于 shared、runtime 这种暂时还没碰到的就不说了,这里讲一下用到的属性:

    • name

      容器的名字

    • filename

      文件名,即其他人可以通过 XXXX/filename 访问的那个文件名,如:

      在 9000 这个端口所访问的文件就是 9001/remoteEntry.js

    • exposes

      容器需要暴露的功能,接受 3 个参数类型,字符串,暴露的对象,以及暴露对象的数组,这里使用的就是数组类型。

remote 其实可以导出任何一个东西,如果想自己从 0 开始配置的话,也可以先试着从 remote 导出一个函数让别的 host 去使用。

host

host 配置

new ModuleFederationPlugin(
  name: 'App',
  remotes: 
    HelloWorldApp: 'HelloWorldApp@http://localhost:9001/remoteEntry.js',
    LionApp: 'LionApp@http://localhost:9002/remoteEntry.js',
  ,
),

这里没有放其他的配置是因为 dashboard 只是作为 consumer 去使用别的 remote 分享的功能。一个 host 同样也可以作为 remote 向别的项目分享功能。

这里 remotes 就是接受别的 remote 分享的功能,格式就是 name@publicPath+filename

host 使用 remotes

因为所有的 remotes 都是异步代码,因此可以使用 callback 或者 async/await,说句题外话,top level await 已经被在 ES2022 中 release 了,并且大部分浏览器支持了,感兴趣的可以试试看:

具体的代码为:

import('HelloWorldApp/HelloWorldPage').then((HelloWorldPageModule) => 
  // const HelloWorldPage = HelloWorldPageModule.default;
  const  HelloWorldPage  = HelloWorldPageModule;
  new HelloWorldPage().render();
);

如果 remote 是 export default ...,那么在 host 使用的时候需要使用注释中的代码。

具体来说,使用 webpack 配置 module federation 并不是很难,而且如果运用得当,使用 monorepo+module federation 的搭配去构建一个微前端的项目也能够解构一些比较复杂的项目。

以上是关于微前端之 Webpack5 的 module federation的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Angular CLI 创建新的遥控器? (Webpack 5 Module Federation 微前端)

基于Webpack5 Federated Module的微服务框架

前端工程化9:Webpack构建流程分析,Webpack5源码解读

深入浅出FE微前端初探

Angular,Webpack5 模块联合:您提供了一个无效的对象,其中需要流

Webpack 5 Module federation micro-frontend 和 react-redux 不工作