2

百度关于EMP的探索:落地生产可用的微前端架构

 2 years ago
source link: https://my.oschina.net/u/4939618/blog/5114834
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

图片

导读:随着 Web 前端工程‬日趋复杂,也‬带来了更大的工程理治‬挑战,微前端在‬大型前端工架程‬构解决方案中成已‬为重要思路之一。本文详细描述 EMP 的诞生背景、使用场景、生态以及如何使用,可以帮助大家能更简单、更高效的构建生产可用微前端架构。

全文3740字,预计阅读时间9分钟。

一、EMP是什么


EMP 是一个微前端架构解决方案集合,旨在帮助大家能更简单、更高效的构建生产可用微前端架构。https://github.com/efoxTeam/emp

2020年5月开始,我们团队开始探索微前端架构。调研从主流的 iframe、Single SPA 到那时刚刚问世的 module federation,最后选择性能和比较有前景的 module federation 作为基础技术进行架构 EMP 微前端解决方案。至今有一年多,已经 releases 53 个版本,解决 108 个 issues,同时具有一定程度生态,有 43 种使用场景的 Demo,支持 7 种 EMP UI 插件支持(包括但不限于 React、Vue、Angular、Preact),4 个编译器支持(babel、esbuild、swc、esm),1 个 Webpack Plugin,目前 EMP 已在服务的线上应用具有一定的稳定性和扩展性。

二、EMP 出现的背景


随着 Web 应用的日渐强大,随之而来的是前端项目不断膨胀。业务需求不断叠加的情况下,巨石项目越来越难维护,编译时间越来越难等。具体来说是,可能会出现 几 MB 的 Bundle Size、十几甚至几十号前端开发人员、一个前端代码库(含 node_modules)会有几 GB。所以需要思考如何把庞大的 Web 项目分解成若干个项目,以便于团队分工协作。

业务开发中,不同项目之间会存在很多可复用的模块。通用的用户数据、UI架构风格、相似的业务逻辑都可以复用,例如一个时间戳转时间的函数就可以到处复用而无需重写甚至引库。所以需要思考如何可以让多个应用项目直接共享这些可复用的模块。当然拆成 NPM 包是一个不错的想法,也是最常用的。

三、EMP 的优势


  • 巨型项目解耦。把巨型项目分解成多个小型项目,分团队开发维护。

  • 快速封装可复用模块。无需单独拆包发布到 NPM,可直接暴露需要共享的模块。引入端仅需要简单配置输出端的地址即可在代码上使用该共享模块。

  • 动态更新。把复用的业务模块放在同一个基站应用之中进行管理和维护,并且暴露出去可以给多个应用使用。如果业务模块需要更新逻辑的话,只需要发布部署基站应用,其他应用并不需要任何操作,只需要访问时刷新,即可使用最新业务模块。

图片

- 远端模块,由于引入端无需手动更新,远端模块的灵活维护和引入端可以自由组合,甚至可以运行时引入使用远端模块。

图片

- 加速构建。因为引入其他项目暴露的模块,不需要本地构建这些子模块的代码,减小了构建体积,提升整个应用的构建速度。- 减少单个项目 Bundle Size。因为引入其他项目暴露的模块,减少各个项目 Bundle Size。

图片

- 下图时对旧项目改造使用了 EMP 微前端方案后带来的速度提升的实际数据

图片

四、EMP 架构设计


图片

五、EMP 生态


EMP 针对不同的UI框架和使用场景都有进行适配和优化。

图片

六、EMP 开箱即用

1.初始化

npx @efox/emp-cli init

  • 可以选择以下模板项目进行初始化,推荐试用 React Typescript 模板

    图片

  • 按提示执行 cd my-emp && yarn && yarn dev 之后,项目将会自动打开在浏览器。

  • React 基站:

    图片

+ React 项目:

图片

  • 如果你想预先安装 @efox/emp-cli,可以通过全局安装 npm install -g @efox/emp-cliyarn global add @efox/emp-cli

  • 建议你卸载该包使用 npm uninstall -g @efox/emp-cli or yarn global remove @efox/emp-cli 确保 npx 使用的 @efox/emp-cli 是最新版本。

2. EMP 唯一的配置文件 emp-config.js ,

以 React 为例,解释配置核心:
/**
 * @type {import('@efox/emp-cli').EMPConfig}
 */
module.exports = {
  webpack() {
    return {
      devServer: {
        /**
         * 设置 devServer
         */
        port: 8002,
      },
    }
  },
  async moduleFederation() {
    return {
      /**
      * name: 对外暴露项目名,
      */
      name: 'demo',
      /**
      * filename: 对外暴露引用文件名,
      */
      filename: 'emp.js',
      /**
      * remotes 远程模块
      * remotes: {
      * '引用别名': '远程模块项目名@远程模块的emp.js文件地址',
      * },
      */
      remotes: {
        '@emp/demo1': 'demo1@http://localhost:8001/emp.js',
      },
      /**
      * exposes 暴露模块
      * exposes: {
      * '对外暴露的相对路径': '当前项目相对路径',
      * },
      */
      exposes: {
        './components/Hello': 'src/components/Hello',
        './helper': 'src/helper',
      },
      /**
      * shared 共享的第三方依赖
      * shared: ['依赖名'],
      */
      shared: ['react', 'react-dom'],
    }
  },
}


以 Vue2 为例,解释配置核心:
const withVue2 = require('@efox/emp-vue2')
module.exports = withVue2(({config}) => {
  const projectName = 'vue2Project'
  const port = 8008
  config.output.publicPath(`http://localhost:${port}/`)
  config.devServer.port(port)
  config.plugin('mf').tap(args => {
    args[0] = {
      ...args[0],
      ...{
        /**
         * name: 对外暴露项目名,
         */
        name: projectName,
        /**
        * filename: 对外暴露引用文件名,
        */
        filename: 'emp.js',
        /**
         * remotes 远程模块
         * remotes: {
         * '引用别名': '远程模块项目名@远程模块的emp.js文件地址',
         * },
         */
        remotes: {
          '@v2b': 'vue2Base@http://localhost:8009/emp.js',
        },
        /**
        * exposes 暴露模块
        * exposes: {
        * '对外暴露的相对路径': '当前项目相对路径',
        * },
        */
        exposes: {
          './Content': './src/components/Content',
        },
        /**
        * shared 共享的第三方依赖
        * shared: ['依赖名'],
        */
        shared: ['vue/dist/vue.esm.js'],
      },
    }
    return args
  })

  config.plugin('html').tap(args => {
    args[0] = {
      ...args[0],
      ...{
        title: 'EMP Vue2 Project',
      },
    }
    return args
  })
})

七、已有项目无痛升级到 EMP 微前端架构


  • @vue/cli Vue2 模版升级到微前端 EMP

  • React CRA 项目升级到微前端 EMP

八、跨框架调用实现


EMP 不推荐大家跨框架调用,因为这样会增加维护成本和风险。但是我们还是支持:

  • Vue3 调用 Vue2 组件

  • Vue&React 互相调用

九、对比 NPM 拆包


  • 但是 npm 拆包有一定工作量:
  1. 需要把可复用模块从业务项目抽离到一个新的 package

  2. 搭建新的构建配置

  3. 单独建 repo

  4. 在原有业务项目重新引用

  5. 可能会因为封装,需要重新设计 API

  • 但是业务模块抽离成 npm 包后,使用 npm 包的更新流程繁琐复杂:
  1. 更新 npm 包版本

  2. 更新 A 应用的npm包版本

  3. 重启 A 应用进行验证

  4. 发布部署 A 管理系统应用

  5. 对 B 和C 应用循环2和3、4步骤

图片

  • 但是 npm 包会拖慢构建速度:通过 npm 引入 n 个的业务模块后,在构建时相当于将n个业务模块的代码“复制”到了项目中,构建时需要同步去构建这些业务子模块,导致 bundle size 变大,构建时长会增加,开发体验变差,发布效率也会随之降低。

图片

十、总结

  • 本文用较短的篇幅介绍了 EMP 的诞生背景、使用场景、生态以及如何无痛使用。

  • EMP 在不断迭代升级,同时生态日渐完善,欢迎各位来了解、使用 EMP 微前端解决方案。

  • 期待大家一起探讨,欢迎来提issue或者新功能:

    https://github.com/efoxTeam/emp

十一、QA


招聘信息:

百度直播研发部招聘研发岗位,包括客户端-Android/iOS方向,服务端-Go/PHP方向。我们负责百度直播业务,对直播业务感兴趣欢迎加入我们。

关注同名公众号百度Geek说,输入内推即可,我们期待你的加入!

推荐阅读:

百度C++工程师的那些极限优化(并发篇)

百度C++工程师的那些极限优化(内存篇)

|百度大规模Service Mesh落地实践

一种基于实时分位数计算的系统及方法

---------- END ----------

百度Geek说

百度官方技术公众号上线啦!

技术干货 · 行业资讯 · 线上沙龙 · 行业大会

招聘信息 · 内推信息 · 技术书籍 · 百度周边

欢迎各位同学关注


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK