微前端从零到剖析qiankun源码 -- 为什么需要微前端?

4,579 阅读4分钟

一.为什么需要微前端?

我们通过3W(what,why,how)的方式来讲解微前端

What?什么是微前端?

微前端就是将不同的功能按照不同的维度拆分成多个子应用。通过主应用来加载这些子应用。

微前端的核心在于, 拆完后在!

Why?为什么去使用他?

  • 不同团队间开发同一个应用技术栈不同怎么破?
  • 希望每个团队都可以独立开发,独立部署怎么破?
  • 项目中还需要老的应用代码怎么破?

我们是不是可以将一个应用划分成若干个子应用,将子应用打包成一个个的lib。当路径切换时加载不同的子应用。这样每个子应用都是独立的,技术栈也不用做限制了!从而解决了前端协同开发问题

How?怎样落地微前端?

2018年 Single-SPA诞生了, single-spa是一个用于前端微服务化的JavaScript前端解决方案 (本身没有处理样式隔离,js执行隔离) 实现了路由劫持和应用加载

2019年 qiankun基于Single-SPA, 提供了更加开箱即用的 API (single-spa + sandbox + import-html-entry) 做到了,技术栈无关、并且接入简单(像iframe一样简单)

总结:子应用可以独立构建,运行时动态加载,主子应用完全解耦,技术栈无关,靠的是协议接入(子应用必须导出 bootstrap、mount、unmount方法)

这里先回答大家肯定会问的问题:

这不是iframe吗?

  • 如果使用iframeiframe中的子应用切换路由时用户刷新页面就尴尬了。
  • 浏览器路径不同步。浏览器刷新之后,iframe链接状态丢失。浏览器前进后退按钮在iframe中也是无法使用的。
  • DOM 结构不共享。想象一下屏幕右下角 的 iframe 需要一个居中的弹框,我们可以通过iframe通信的方式实现,但是会给我们增加不必要的复杂度。
  • iframe间cookie管理成本较高,我们需要在iframe中共享同一个cookie。
  • 慢。每次子应用进入都需要重建浏览器上下文、资源也会重新加载。

应用通信:

  • 基于URL来进行数据传递,但是传递消息能力弱
  • 基于CustomEvent实现通信
  • 基于props主子应用间通信
  • 使用全局变量、Redux进行通信

公共依赖:

  • CDN - externals
  • webpack联邦模块

实现微前端技术方案

  • 采用何种方案进行应用拆分?
  • 采用何种方式进行应用通信?
  • 应用之间如何进行隔离?

微前端方案种类

目前国内微前端方案大概分为:

  • 基座模式:通过搭建基座、配置中心来管理子应用。如基于SIngle Spa的偏通用的qiankun方案,也有基于本身团队业务量身定制的方案。
  • 自组织模式: 通过约定进行互调,但会遇到处理第三方依赖等问题。
  • 去中心模式: 脱离基座模式,每个应用之间都可以彼此分享资源。如基于Webpack 5 Module Federation实现的EMP微前端方案,可以实现多个应用彼此共享资源分享。

将在后面的文章中一一带大家搞懂各种微前端的解决方案。

iframe

微前端的最简单方案,通过iframe加载子应用。 通信可以通过postMessage进行通信。 完美的沙箱机制自带应用隔离。

缺点:用户体验差 (弹框只能在iframe中、在内部切换刷新就会丢失状态)

Web Components

将前端应用程序分解为自定义 HTML 元素。 基于CustomEvent实现通信
Shadow DOM天生的作用域隔离

缺点:浏览器支持问题、学习成本、调试困难、修改样式困难等问题。

single-spa

single-spa 通过路由劫持实现应用的加载(采用SystemJS),提供应用间公共组件加载及 公共业务逻辑处理。子应用需要暴露固定的钩子 bootstrap、mount、 unmount)接入协议。

基于props主子应用间通信 无沙箱机制,需要实现自己实现JS沙箱以及CSS沙箱

缺点:学习成本、无沙箱机制、需要对原有的应用进行改造、子应用间相同资源重复加载问题。

Module federation

通过模块联邦将组件进行打包导出使用 共享模块的方式进行通信 无CSS沙箱和JS沙箱

缺点:需要webpack5,模块需要独立拆分和部署。

总结一下:微前端就是将不同的功能按照不同的维度拆分成多个子应用。通过主应用来加载这些子应用,至于使用什么方式来加载我们的子应用,且听下一章《微前端从零到剖析qiankun源码 -- Web Components的玩法!》