微前端和Qiankun

微前端架构是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。

采用不同 JavaScript 技术框架的多个团队中协同构建一个现代化前端 Web 应用所需要的技术、策略和方法。

qiankun: https://qiankun.umijs.org/zh/guide

2020.12 星期二 :


2021.7.17 星期六 23:33




总结:还是要回到业务本身。包括微前端框架的使用方式 和 实现上。
一千个读者一千个哈姆雷特。

# 概念

微前端这个术语最初来自 2016 年的 ThoughtWorks 技术雷达[ https://www.thoughtworks.com/radar/techniques/micro-frontends ],它将微服务的概念扩展到了前端领域。目前的趋势是构建一个功能丰富且强大的前端应用,即单页面应用(SPA),其本身一般都是建立在一个微服务架构之上。前端层通常由一个单独的团队开发,随着时间的推移,会变得越来越庞大而难以维护。这就是传说中的前端巨无霸Frontend Monolith

微前端背后的理念是将一个网站或者 Web App 当成特性的组合体,每个特性都由一个独立的团队负责。每个团队都有擅长的特定业务领域或是它关心的任务。这里,一个团队是跨职能的,它可以端到端,从数据库到用户界面完整的开发它所负责的功能。

然而,这个概念并不新鲜,过去它叫针对垂直系统的前端一体化或独立系统。不过微前端显然是一个更加友好并且不那么笨重的术语。

一体化的前端 VS 垂直化组织方式
DOM 就是 API; 页面组合;基本原型;如何创建一个自定义元素
浏览器支持;框架兼容性;子父元素或兄弟元素通信 / DOM 事件
服务端渲染 / 通用渲染;自定义元素 + 服务端包含(Includes).

# qiankun
qiankun: https://qiankun.umijs.org/zh/guide
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。

## 什么是微前端
> Techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently. – Micro Frontends
> 微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。


微前端架构具备以下几个核心价值:
技术栈无关
主框架不限制接入应用的技术栈,微应用具备完全自主权

独立开发、独立部署
微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新

增量升级
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略

独立运行时
每个微应用之间状态隔离,运行时状态不共享

## 为什么不是 iframe

## qiankun 技术图
### 特性

基于 single-spa 封装,提供了更加开箱即用的 API 技术栈无关,任意技术栈的应用均可 使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。
HTML Entry 接入方式。接入微应用像使用 iframe 一样简单 样式隔离,确保微应用之间样式互相不干扰。
JS 沙箱,确保微应用之间 全局变量/事件 不冲突。 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
umi 插件,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。

### 使用场景
项目很多,规模很大,都是每个项目独立使用git此类仓库维护的、技术栈为vue/react/angular的这类应用
需要整合到统一平台上,你正在寻找可能比iframe更合适的替代方案
项目A有功能A1、A2、A3,项目B有功能B1、B2、B3,产品经理要你把A2、B1、B3组合成一个包含这些功能的新项目




## 常见问题
### 在主应用的某个路由页面加载微应用
### 微应用加载的资源会 404
原因是 webpack 加载资源时未使用正确的 publicPath。
a. 使用 webpack 运行时 publicPath 配置
b. 使用 webpack 静态 publicPath 配置
### 微应用打包之后 css 中的字体文件和图片加载 404
五种解决方式。
1. cdn。
2. url-loader:base64.
3. 借助 webpack 的 file-loader ,在打包时给其注入完整路径(适用于字体文件和图片体积比较大的项目)
4. 将两种方案结合起来,小文件转 base64 ,大文件注入路径前缀
5. vue-cli3 项目可以将 css 打包到 js里面,不单独生成文件(不推荐,仅适用于 css 较少的项目)
1
2
3
4
5
module.exports = {
css: {
extract: false,
},
};



### 静态资源一定要支持跨域
由于 qiankun 是通过 fetch 去获取微应用的引入的静态资源的,所以必须要求这些静态资源支持跨域。
### 主应用跟微应用之间的样式隔离

qiankun 将会自动隔离微应用之间的样式(开启沙箱的情况下),你可以通过手动的方式确保主应用与微应用之间的样式隔离。
### 独立运行微应用
有些时候我们希望直接启动微应用从而更方便的开发调试.可以使用这个全局变量来区分当前是否运行在 qiankun 的主应用的上下文中 window.__POWERED_BY_QIANKUN__
### 取出公共的依赖库
> 不要共享运行时,即便所有的团队都是用同一个框架。


### 微应用之间如何跳转


# Ⅰ可能是你见过最完善的微前端解决方案

## 行业现状
传统的云控制台应用,几乎都会面临业务快速发展之后,单体应用进化成巨石应用的问题。为了解决产品研发之间各种耦合的问题,大部分企业也都会有自己的解决方案。笔者于17年底,针对国内外几个著名的云产品控制台,做过这样一个技术调研:

MPA 方案的优点在于 部署简单、各应用之间硬隔离,天生具备技术栈无关、独立开发、独立部署的特性。缺点则也很明显,应用之间切换会造成浏览器重刷,由于产品域名之间相互跳转,流程体验上会存在断点。
SPA 则天生具备体验上的优势,应用直接无刷新切换,能极大的保证多产品之间流程操作串联时的流程性。缺点则在于各应用技术栈之间是强耦合的。
那我们有没有可能将 MPA 和SPA 两者的优势结合起来,构建出一个相对完善的微前端架构方案呢?
jsconf china 2016 大会上,ucloud 的同学分享了他们的基于 angularjs 的方案(单页应用“联邦制”实践),里面提到的 “联邦制” 概念很贴切,可以认为是早期的基于耦合技术栈的微前端架构实践。

## 微前端架构实践中的问题
### 路由系统及 FutureStat
### App Entry
解决了路由问题后,主框架与子应用集成的方式,也会成为一个需要重点关注的技术决策。
1. 构建时组合 VS 运行时组合
2. JS Entry vs HTMLEntry
3. 模块导入
### 应用隔离
1. 样式隔离
Shadow DOM?
CSS Module? BEM?
Dynamic Stylesheet !
2. JS 隔离
即在应用的 bootstrap 及 mount 两个生命周期开始之前分别给全局状态打下快照

## 蚂蚁金服微前端落地实践
在内部得到充分的技术验证和线上考验之后,我们决定将这套解决方案开源出来!

qiankun - 一套完整的微前端解决方案
https://github.com/umijs/qiankun
取名 qiankun,意为统一。我们希望通过 qiankun 这种技术手段,让你能很方便的将一个巨石应用改造成一个基于微前端架构的系统,并且不再需要去关注各种过程中的技术细节,做到真正的开箱即用和生产可用。


先是qiankun 掌握其根本,然后是mooa 了解其历程。
第三个是meituan的两个方案。第四是基于singleSpa,qiankun 讨论微前端实现方式。
倒数第二总结一下微前端,做了哪些工作,来获得收益;或者弊端。
最后再回顾一下实现微前端的六种方式。

排名不分先后
# Ⅱ 微前端的那些事儿

实施微前端的六种方式
基础铺垫:应用分发路由 -> 路由分发应用
后端:函数调用 -> 远程调用
前端:组件调用 -> 应用调用
路由分发式微前端
使用 iFrame 创建容器
自制框架兼容应用
组合式集成:将应用微件化
纯 Web Components 技术构建
结合 Web Components 构建
在 Web Components 中集成现有框架
集成在现有框架中的 Web Components
复合型

为什么微前端开始在流行——Web 应用的聚合
前端遗留系统迁移
后端解耦,前端聚合
兼容遗留系统
如何解构单体前端应用——前端应用的微服务式拆分
前端微服化
独立开发
独立部署
我们真的需要技术无关吗?
不影响用户体验
微前端的设计理念
设计理念一:中心化路由
设计理念二:标识化应用
设计理念三:生命周期
设计理念四:独立部署与配置自动化
实战微前端架构设计
独立部署与配置自动化
应用间路由——事件


大型 Angular 应用微前端的四种拆分策略
前端微服务化:路由懒加载及其变体
微服务化方案:子应用模式
方案对比
标准 LazyLoad
LazyLoad 变体 1:构建时集成
LazyLoad 变体 2:构建后集成
前端微服务化
总对比


前端微服务化:使用微前端框架 Mooa 开发微前端应用
Mooa 概念
微前端主工程创建
Mooa 子应用创建
导航到特定的子应用

前端微服务化:使用特制的 iframe 微服务化 Angular 应用
iframe 微服务架构设计
微前端框架 Mooa 的特制 iframe 模式
微前端框架 Mooa iframe 通讯机制
发布主应用事件
监听子应用事件
示例


# Ⅲ 微前端在美团外卖的实践

## 背景
外卖商家广告端的业务形态。目前,我们开发和维护的系统主要包括三端:
PC系统:单门店投放系统PC端
H5系统:单门店投放系统H5端
KA系统:多门店投放系统PC端
如上图所示,原始解决方案的三端由各自独立开发和维护,各自包含所有的业务线,而我们的业务开发情况是:

PC端和H5端相同业务线的基本业务逻辑一致,UI差异大。
PC端和KA端相同业务线的部分业务逻辑一致,UI差异小。

就有两个问题摆在我们面前:

如何进行物理层面的复用(不同端的代码在不同地址的Git仓库)。
如何进行逻辑层面的复用(不同端的相同逻辑如何使用一份代码进行抽象)。

## 方案选择
经过以上的需求分析,我们调研了业界及公司周边的微前端方案,并总结了以下几种方案以及它们各自主要的特点:

NPM式:子工程以NPM包的形式发布源码;打包构建发布还是由基座工程管理,打包时集成。
iframe式:子工程可以使用不同技术栈;子工程之间完全独立,无任何依赖;基座工程和子工程需要建立通信机制;无单页应用体验;路由地址管理困难。
通用中心路由基座式:子工程可以使用不同技术栈;子工程之间完全独立,无任何依赖;统一由基座工程进行管理,按照DOM节点的注册、挂载、卸载来完成。
特定中心路由基座式:子业务线之间使用相同技术栈;基座工程和子工程可以单独开发单独部署;子工程有能力复用基座工程的公共基建。
## 微前端实践概览
## 微前端架构下的业务变化
## 基于React技术栈的中心路由基座式微前端
### 动态化方案
动态路由
动态Store
动态CSS

### 路由配置信息方案
### 子工程接口方案
### 复用方案
### 流程方案
开发流程
热更新
Mock数据


### 部署方案
### 回滚方案
### 监控方案


# Ⅲ 用微前端的方式搭建类单页应用

## 前言
微前端由ThoughtWorks 2016年提出,将后端微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。
我们把这种由多个微前端聚合出来的单页应用叫做“类单页应用”,美团HR系统就是基于这种设计实现的。美团HR系统是由30多个微前端应用聚合而成,包含1000多个页面,300多个导航菜单项。对用户来说,HR系统是一个单页应用,整个交互过程非常顺畅;对开发者同学来说,各个应用均可独立开发、独立测试、独立发布,大大提高了开发效率。

接下来,本文将为大家介绍“微前端构建类单页应用”在美团HR系统中的一些实践。同时也分享一些我们的思考和经验,希望能够对大家有所启发。
## HR系统的微前端设计
一般而言,“类单页应用”的实现方式主要有两种:

iframe嵌入
微前端合并类单页应用
### 一个前端对应多个后端
“Portal项目”是比较特殊的,在开发阶段是一个容器,不包含任何业务,除了提供“子项目”注册、合并功能外,还可以提供一些系统级公共支持,例如:

转发规则上限制数据请求格式必须是 系统名+Api做前缀 这样保障了各个系统之间的请求可以完全隔离。其中,Nginx的配置示例如下:
### 应用注册机制
#### 路由注册
#### 项目作用域控制
window.app主要功能:
define 定义项目的公共库,主要用来解决JS公共库的管理问题
require 引用自己的定义的基础库,配合define来使用
routes 用于存放全局的路由,子项目路由添加到window.app.routes,用于完成路由的注册
init 注册入口,为子项目添加上namesapce标识,注册上子项目管理数据流的reducers

#### CSS作用域方面
使用webpack在构建阶段为业务的所有CSS都加上自己的作用域
#### JS公共库版本统一

### 构建后集成和独立部署
在HR系统的整合过程中,开发阶段对“子项目”是“零侵入”,而在发布阶段,我们也希望如此。

# Ⅳ 你必须要会的微前端


  1. 一.为什么需要微前端?
    1. 1.What?什么是微前端?
    2. 2.Why?为什么去使用他?
    3. 3.How?怎样落地微前端?
  2. 二 .SingleSpa实战
    1. 1.构建子应用
    2. 2.配置库打包
    3. 3.主应用搭建
    4. 4.动态设置子应用publicPath
  3. 三.qiankun实战
    1. 1.主应用编写
    2. 2.注册子应用
    3. 3.子Vue应用
    4. 4.子React应用
  4. 四.CSS隔离方案
  5. 五.JS沙箱机制
    1. 1.快照沙箱
    2. 2.Proxy 代理沙箱


## 一.为什么需要微前端?
1.What?什么是微前端?
2.Why?为什么去使用他?
3.How?怎样落地微前端?
### 应用间如何通信?
基于URL来进行数据传递,但是这种传递消息的方式能力较弱;
基于CustomEvent实现通信;
基于props主子应用间通信;
使用全局变量、Redux进行通信。

### 如何处理公共依赖?
CDN - externals
webpack联邦模块
## 二 .SingleSpa实战
## 三.qiankun实战
四.CSS隔离方案
子应用之间样式隔离:
Dynamic Stylesheet动态样式表,当应用切换时移除掉老应用样式,再添加新应用样式,保证在一个时间点内只有一个应用的样式表生效

主应用和子应用之间的样式隔离:
BEM(Block Element Modifier) 约定项目前缀
CSS-Modules 打包时生成不冲突的选择器名
Shadow DOM 真正意义上的隔离
css-in-js
## 五.JS沙箱机制
运行子应用时应该跑在内部沙箱环境中

快照沙箱,当应用沙箱挂载或卸载时记录快照,在切换时依据快照恢复环境 (无法支持多实例)
> 快照沙箱只能针对单实例应用场景,如果是多个实例同时挂载的情况则无法解决,这时只能通过Proxy代理沙箱来实现
Proxy 代理沙箱,不影响全局环境
> 每个应用都创建一个proxy来代理window对象,好处是每个应用都是相对独立的,不需要直接更改全局的window属性。



# Ⅸ 微前端到底是什么

本文首发于 ayqy.net ,原文链接:http://www.ayqy.net/blog/micro-frontends/

## 一.简介
## 二.特点
将庞大的整体拆成可控的小块,并明确它们之间的依赖关系。关键优势在于:
代码库更小,更内聚、可维护性更高
松耦合、自治的团队可扩展性更好 渐进地升级、更新甚至重写部分前端功能成为了可能

简单、松耦合的代码库
增量升级
独立部署
团队自治

## 三.实现方案
实现上,关键问题在于:

多个 Bundle 如何集成?
集成方式分为 3 类:
服务端集成:如 SSR 拼装模板
构建时集成:如 Code Splitting
运行时集成:如通过 iframe、JS、Web Components 等方式

子应用之间怎样隔离影响?
样式隔离:开发规范(如BEM)、CSS 预处理(如SASS)、模块定义(如CSS Module)、用 JS 来写(CSS-in-JS)、以及shadow DOM特性
作用域隔离:各种模块定义(如ES Module、AMD、Common Module、UMD)


公共资源如何复用?
资源复用对于 UI 一致性和代码复用有重要意义,但并非所有的可复用资源(如组件)都必须在一
另一方面,资源分为以下 3 类:
基础资源:完全不含逻辑功能的图标、标签、按钮等
UI 组件:含有一定 UI 逻辑的搜索框(如自动完成)、表格(如排序、筛选、分页)等
业务组件:含有业务逻辑

其中,不建议跨子应用复用业务组件,因为会造成高度耦合,增加变更成本
对于公共资源的归属和管理,一般有两种模式:
公共资源归属于所有人,即没有明确归属
公共资源归集中管理,由专人负责

子应用间怎样通信?


如何测试?
每个子应用都应该有自己的全套测试方案,特殊之处在于,除单元测试、功能测试外,还要有集成测试:
## 四.示例
在线 Demo:https://demo.microfrontends.com/
源码地址:micro-frontends-demo/container
详细介绍:The example in detail


## 五.缺点
导致依赖项冗余,增加用户的流量负担
团队自治程度的增加,可能会破坏协作

## 六.总结


# Ⅹ 实施微前端的六种方式

结合我最近半年在微前端方面的实践和研究来看,微前端架构一般可以由以下几种方式进行:
使用 HTTP 服务器的路由来重定向多个应用 在不同的框架之上设计通讯、加载机制,诸如 Mooa 和 Single-SPA
通过组合多个独立应用、组件来构建一个单体应用 iFrame。使用 iFrame 及自定义消息传递机制
使用纯 Web Components 构建应用 结合 Web Components 构建

## 基础铺垫:应用分发路由 -> 路由分发应用
后端:函数调用 -> 远程调用
### 前端:组件调用 -> 应用调用
## 路由分发式微前端
在这个示例里,不同的页面的请求被分发到不同的服务器上。
随后,我们在别的项目上也使用了类似的方式,其主要原因是:跨团队的协作。
因此在这种情况下,它适用于以下场景
## 使用 iFrame 创建容器
网站不需要 SEO 支持
拥有相应的应用管理机制。
设计管理应用机制
设计应用通讯机制
## 自制框架兼容应用
尽管 Single-SPA 已经拥有了大部分框架(如 React、Angular、Vue 等框架)的启动和卸载处理,但是它仍然不是适合于生产用途。当我基于 Single-SPA 为 Angular 框架设计一个微前端架构的应用时,我最后选择重写一个自己的框架,即 Mooa。
## 组合式集成:将应用微件化
## 纯 Web Components 技术构建
在添加了一些基本的 Web 前端框架的功能之后,我发现这项技术特别适合于作为微前端的基石

Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的 Web 应用中使用它们。
它主要由四项技术组件:

1)Custom elements,允许开发者创建自定义的元素,诸如 <today-news></today-news>
2)Shadow DOM,即影子 DOM,通常是将 Shadow DOM 附加到主文档 DOM 中,并可以控制其关联的功能。而这个 Shadow DOM 则是不能直接用其它主文档 DOM 来控制的。
3)HTML templates,即<template><slot> 元素,用于编写不在页面中显示的标记模板。
4)HTML Imports,用于引入自定义组件。



# 万字长文+图文并茂+全面解析微前端框架 qiankun 源码 - qiankun 篇

初始化全局配置 - start(opts)
注册子应用 - registerMicroApps(apps, lifeCycles?)
获取子应用资源 - import-html-entry
主应用挂载子应用 HTML 模板
沙箱运行环境 - genSandbox
LegacySandbox
多实例沙箱 - ProxySandbox
SnapshotSandbox
挂载沙箱 - mountSandbox
计时器劫持 - patchTimer
动态添加样式表和脚本文件劫持 - patchDynamicAppend
卸载沙箱 - unmountSandbox
注册内部生命周期函数
触发 beforeLoad 生命周期钩子函数
进入到 mount 挂载流程
进入到 unmount 卸载流程

最后一件事
这篇文章我花了大约半个月的时间来进行排版、梳理、画图,坚持下来一路写完确实很不容易。



# 微前端的核心价值

> 如果是 widget 级别,那么微前端跟业务组件的区别在哪里?微前端到底是因何而生?
我的观点:有没有区别在于你的实现是不是技术栈无关。

我认为微前端的核心价值在于 “技术栈无关”,这才是它诞生的理由,或者说这才是能说服我采用微前端方案的理由。

## 为什么”技术栈无关”这么重要?
## 为什么我认为”技术栈无关”才是微前端的初衷?
> 微前端的初衷应该还是来解决工程问题的,带来的产品价值在不同的领域可大可小。 比如在阿里云这种典型的云产品控制台的场景下,它带来的产品价值就会很可观。

> 今天看各 BU 的业务问题,微前端的前提,还是得有主体应用,然后才有微组件或微应用,解决的是可控体系下的前端协同开发问题(含空间分离带来的协作和时间延续带来的升级维护)
## 微前端方案正确的架构姿势
「技术栈无关」是架构上的准绳,具体到实现时,对应的就是:应用之间不应该有任何直接或间接的技术栈、依赖、以及实现上的耦合。


qiankun 正是以此为准则设计的。
如果说阿里的企业使命是:「让天下没有难做的生意」。
那么微前端的使命我认为是:「让天下没有短命的控制台」。

> 事实上如果所有的 web 技术栈能做到统一,所有 library 的升级都能做到向下兼容,我们确实就不需要微前端了。 —— 鲁迅

## 评论
> 最终解决方案还要看web component
> 技术栈无关这个优点说实话是非常。。emmm。怎么说呢,非常的自我安慰。
> 很多同学纠结于 web components。微前端的最大的优势,是技术无关性。web components 是一种具体的技术,而三大框架也是具体的技术。后者明显比裸写 web components 要香的多了。

> 结合 Web Components 构建是一种面向未来演进的架构。或者说在未来的时候,我们可以开始采用这种方式来构建我们的应用。目前没有采用的原因是遗留系统下IE的兼容性问题。(至少目前选择类似乾坤的方式是有这方面的原因
三大框架中除了react之外,都已经算是拥抱 Web Components 了。ng 用起来更是不像外部组件。
> 类似于 Stencil 的形式,将组件直接构建成 Web Components 形式的组件,随后在对应的诸如, React 或者 Angular 中直接引用。其实也是很好的解决方式。

> 最后还想提问一句, 微前端带来的spa体验对比与 MPA 路由组合带来的体验提升了多少? 对于用户真的有感知吗? 如何衡量这里的价值?









knowledge is no pay,reward is kindness
0%