会议内容

  1. 围绕微前端开展,评审winstore微前端框架方案
  2. 组件库建设的规划
  3. 前端手册

    微前端

    从项目出发

    image.png

项目迭代就像搭积木 (组件或者物料堆)

某一个积木拼错了 (功能出现bug)

增加一个新功能 (最小的成本 增加功能 ) (高内聚,低耦合)

其他人也想要使用这个部件 (可测试性) (如a 物料 使用到 b 物料里)

其他人的部件怎么添加到我的这个积木里面

要搬家了,这个大家伙怎么带过去 (增量迭代,渐进式开发)

高内聚,低耦合

在设计各个子应用及主应用的过程中,需要遵循高内聚、低耦合的原则。

高内聚,即模块内的关系,一个软件模块只由相关性很强的代码组成。
设计的过程就是识别、度量模块内的联系,再将相关的行为聚集在一起,把不相关的行为放在别处。如果想要修改模块中某一部分的行为,只需要修改一处代码即可,而不需要修改多处。在实践的过程中,主要基于单一职责和关注点分离两个原则来实现。
低耦合,即模块间的关系。对于微架构系统来说,在服务之间、应用之间如果实现了松耦合,那么修改一个服务和应用就不需要修改另一个服务和应用。除了基座应用,每个应用都不应该关心协作应用的相关信息。
这两个词说起来很简单,但是真正在实现的过程中却相当麻烦。应用之间往往存在一定的依赖关系,要解耦这些依赖,就需要将数据独立出来,并使用通信的方式来传递状态。


在实际项目上遇到两个实际的场景

场景一:

如果我们的项目需要开发某个新的功能,而这个功能另一个项目已经开发好,我们想直接复用时。PS:我们需要的只是别人项目的这个功能页面的内容部分,不需要别人项目的顶部导航和菜单。

往往都会想到是 一个比较笨的办法就是直接把别人项目这个页面的代码拷贝过来,但是万一别人不是 vue开发的,或者说 vue版本、 UI
库等不同,以及别人的页面加载之前操作(路由拦截,鉴权等)我们都需要拷贝过来,更重要的问题是,别人代码有更新,我们如何做到同步更新。

长远来看,代码拷贝不太可行,问题的根本就是,我们需要做到让他们的代码运行在他们自己的环境之上,而我们对他们的页面仅仅是“引用”。这个环境包括各种插件( vuevuexvue-router等),也包括加载前的逻辑(读 cookie,鉴权,路由拦截等)。私有 npm
可以共享组件,但是依然存在技术栈不同/UI库不同等问题。

场景二:

2、巨无霸项目的自由拆分组合

  • 代码越来越多,打包越来越慢,部署升级麻烦,一些插件的升级和公共组件的修改需要考虑的更多,很容易牵一发而动全身
  • 项目太大,参与人员越多,代码规范比较难管理,代码冲突也频繁。
  • 产品功能齐全,但是客户往往只需要其中的部分功能。剥离不需要的代码后,需要独立制定版本,独立维护,增加人力成本。

举个栗子,你们的产品有几百个页面,功能齐全且强大,客户只需要其中的部分页面,而且需要你们提供源码,这时候把所有代码都给出去肯定是不可能的,只能挑出来客户需要,这部分代码需要另外制定版本维护,就很浪费。

什么是【微前端】

背景:

  • 前端应用越来越复杂

导致:

  1. 人力成本压力

线上出现问题,怎么快速定位问题

  1. 维护成本高
  2. 迭代成本高
  3. 需求变更影响范围大
  4. 持续化投入产出比不足

所以:

  • 面对这种情况 【后端】是如何处理的? (后端微服务)

解决:

  • 重新洗牌 (先拆后合)-> 重构

优点:

  1. 隔离(服务、IDC) IDC:机房
  2. 弹性/扩展性 (如:扩容)
  3. 增强稳定性
  4. 降低成本 (人力、上线、回归、需求)

主要事项:

  1. 测试
  2. 部署
  3. 服务拆分标准
  4. 过于 分散/密集

解读微前端

那什么是微前端?微前端主要是借鉴后端微服务的概念。简单地说,就是将一个巨无霸(Monolith)的前端工程拆分成一个一个的小工程。别小看这些小工程,它们也是“麻雀虽小,五脏俱全”,完全具备独立的开发、运行能力。整个系统就将由这些小工程协同合作,实现所有页面的展示与交互。

2021/01/21 前端规划 - 图2

可以跟微服务这么对比着去理解:

微服务 微前端
一个微服务就是由一组接口构成,接口地址一般是 URL。当微服务收到一个接口的请求时,会进行路由找到相应的逻辑,输出响应内容。 一个微前端则是由一组页面构成,页面地址也是 URL。当微前端收到一个页面 URL 的请求时,会进行路由找到相应的组件,渲染页面内容。
后端微服务会有一个网关,作为单一入口接收所有的客户端接口请求,根据接口 URL 与服务的匹配关系,路由到对应的服务。 微前端则会有一个加载器,作为单一入口接收所有页面 URL 的访问,根据页面 URL 与微前端的匹配关系,选择加载对应的微前端,由该微前端进行进行路由响应 URL。

这里要注意跟 iframe 实现页面嵌入机制的区别。微前端没有用到 iframe,它很纯粹地利用 JavaScript、MVVM 等技术来实现页面加载。后面我们将介绍相关的技术实现。

微前端本质是是一种项目架构方案,是为了解决前端项目太过庞大,导致项目管理维护难、团队协作乱、升级迭代困难、技术栈不统一等等问题

微前端特点

1、应用自治

微前端架构,是多个应用组件的统一应用,这些应用可以交由多个团队来开发。要遵循统一的接口规范或者框架,以便于系统集成到一起,因此相互之间是不存在依赖关 系的。我们可以在适当的时候,替换其中任意一个前端应用,而整体不受影响。这也意味着,我们可以使用各式各样的前端框架,而不会互相影响。

2、单一职责

与微服务类似的是,微前端架构理应满足单一职责的原则。然而,微前端架构要实现单一职责,并非那么容易。前端面向最终用户,前端需要保证用户体验的连续性。一旦在业务上关联密切,如B页面依赖A页面,A页面又在一定的程度上依赖B页面,拆分开来就没有那么容易。但是如果业务关联少,如一些关于“我们的联系方式”等的页面,使用不多,没有多少难度。因此,一旦面临用户体验的挑战,就要考虑选择其他方式。

3、技术栈无关

在后端微服务的架构中,技术栈无关是一个相当重要的特性。后端可以选用合适的语言和框架来开发最合适的服务,服务之间使用API进行通信即可。但是对于微前端架构来说,虽然拥有一系列的JavaScript语言,但是前端框架是有限的,即使在某个微前端架构里实现了框架无关,也并不是那么重要。框架之间的差距并不大,一个框架能做的事情,另一个框架也能做,这一点便不如后端。使用Java解决不了的人工智能部分,可以交给Python;如果觉得Java烦琐,可以使用Scala,如图所示
image.png
对大部分公司和团队来说,技术无关只是一个无关痛痒的话术。如果一家公司的几个创始人使用了Java,那么极有可能在未来的选型上继续使用Java。对于前端框架来说也是相似的,如果我们选定Vue,除非出现新的框架来解决vue框架的问题,否则大概率继续使用原有的框架——毕竟已经拥有大量成熟的基础设施。

举个例子:七某云平台
2021/01/21 前端规划 - 图4
本质上应该就是一个微前端应用,左侧的菜单就是各个子应用的入口,切换菜单的同时就是在切换子应用,而整个主容器就是一个portal门户(可能包含用户登录机制 、菜单权限获取 、 全局异常处理等)

iframe

iframe 作为一个非常 “古老” 的,人人都觉得普通的技术,却一直很管用。它能有效地将另一个网页/单页面应用嵌入到当前页面中,两个页面间的 CSS 和 JavaScript 是相互隔离的——除去 iframe 父子通信部分的代码,它们之间的代码是完全不相互干扰的。iframe 便相当于是创建了一个全新的独立的宿主环境,类似于沙箱隔离,它意味着前端应用之间可以相互独立运行。
iframe 确实挺好用的,但是也存在一些缺点:

  • 子项目需要改造,需要提供一组不带导航的功能
  • iframe 嵌入的显示区大小不容易控制,存在一定局限性
  • URL 的记录完全无效,页面刷新不能够被记忆,刷新会返回首页
  • iframe 功能之间的跳转是无效的
  • iframe 的样式显示、兼容性等都具有局限性
  • iframe 方式的应用之间通信和调试比较麻烦,存在不可控性风险
  • iframe 的优点是简单易用,缺点是用户体验差,应用之间通信困难。我们在微前端架构方案中,首选方案并不是 iframe。但是在接入第三方应用时,iframe 依旧是首选方案。

微前端场景分析

iframe single-spa.js 其他
缺点
1. 结构冗余 (嵌套处理)
1. 事件通讯繁琐
1. 只能处理视图相关服务
1. 操作反馈复杂
1. 其他更多的缺点

1. 只有app级别的隔离
1. 没有统一的服务规范
1. 使用了system.js
1. 对业务侵入性太强
目标:
吸收single-spa的优点
改正single-spa的缺点

为什么需要微前端?

思考

结合别人实际场景

在介绍具体的改造方式之前,我想跟大家先说明下我们当时面临的问题,以及改造后的对比,以便大家以此为对照,评判或决定使用。主要包括打包速度、页面加载速度、多人多地协作、SaaS 产品定制化、产品拆分这几个角度。

首先是打包速度。在 6 个月前,我们的 B 端工程那会儿还是一个 Monolith。当时已经有 20 多个依赖、60 多个公共组件、200 多个页面,对接 700 多个接口。我们使用了 Webpack 2,并启用 DLL Plugin、HappyPack 4。在我的个人主机上使用 4 线程编译,大概要 5 分钟。而如果不拆分,算下来现在我们已经有近 400 个页面,对接1000 多个接口。 这个时间意味着什么?它不仅会耽误我们开发人员的时间,还会影响整个团队的效率。上线时,在 Docker、CI 等环境下,耗时还会被延长。如果部署后出几个 Bug,要线上立即修复,那就不知道要熬到几点了。 在使用微前端改造后,目前我们已经有 26 个微前端工程,平均打包时间在 30-45 秒之间(注意,这里还没有应用 DLL + HappyPack)。 页面加载速度其实影响到并不是很大,因为经过 CDN、gzip 后,资源的大小还能接受。这里只是给大家看一些直观的数据变化。6 个月前,打包生成的 app.js 有 5MB(gzip 后 1MB),vendor.js 有 2MB(gzip 后 700KB),app.css 有 1.5MB(gzip 后 250KB)。这样首屏大概要传输 2MB 的内容。拆分后,目前首屏只需要传输 800KB 左右。(优化)

在协作上,我们在全国有三个地方的前端团队,这么多人在同一个工程里开发,遭遇代码冲突的概率会很频繁,而且冲突的影响面比较大。如果代码中出现问题,导致 CI 失败,所有其他人的代码提交与更新也都会被阻塞。使用微前端后,这样的风险就平摊到各个工程上去了。(协作)

再者就是定制化了。我们做的额是一款 toB 的产品,做成 SaaS 标准版产品大概是所有从业者的愿望。但整体市场环境与产品功能所限,经常要面临一些客户要求做本地化与定制化的要求。本地化就会有代码安全方面的考量,最好是不给客户源代码,最差则是只给客户购买功能的源代码。而定制化从易到难则可以分为独立新模块、改造现有模块、替换现有模块。(拆、合)

通过微前端技术,我们可以很容易达到本地化代码安全的下限——只给客户他所购买的模块的前端源码。定制化里最简单的独立新模块也变得简单:交付团队增加一个新的微前端工程即可,不需要揉进现有研发工程中,不占用研发团队资源。而定制化中的改造现有模块也可以比较好地实现:比如说某个标准版的页面中需要增加一个面板,则可以通过一个新的微前端工程,同样响应该页面的 URL(当然要控制好顺序),在页面的恰当位置插入一个新的 DOM 节点即可。

最后就是产品拆分方面的考量了。我们的产品比较大,有几块功能比较独立、有特色。如果说将来需要独立成一个子产品,有微前端拆分作为铺垫,腾挪组合也会变得更加容易些。

微前端的前提,还是得有主体应用,然后才有微组件或微应用,解决的是可控体系下的前端协同开发问题(含 空间分离带来的协作 和 时间延续带来的升级维护)

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

What?什么是微前端?

2021/01/21 前端规划 - 图5
微前端就是将不同的功能按照不同的维度拆分成多个子应用。通过主应用来加载这些子应用。
微前端的核心在于, 拆完后在!

Why?为什么去使用他?

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

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

How?怎样落地微前端?

2021/01/21 前端规划 - 图6
2018年 Single-SPA诞生了, single-spa是一个用于前端微服务化的JavaScript前端解决方案 (本身没有处理样式隔离,js执行隔离) 实现了路由劫持和应用加载
2019年 qiankun基于Single-SPA, 提供了更加开箱即用的 APIsingle-spa + sandbox + import-html-entry) 做到了,技术栈无关、并且接入简单(像iframe一样简单)

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

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

这不是iframe吗?

  • 如果使用iframeiframe中的子应用切换路由时用户刷新页面就尴尬了。

应用通信:

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

公共依赖:

  • CDN - externals
  • webpack联邦模块

实施微前端的六种方式

自己在主导新技术落地,需要考虑:
无论是对于从头开发的微前端应用,还是正在迁移的微前端应用,这种架构的演进都需要一个实施时间。出于以下目的,我们需要快速“发布”MRV版本(最小可发布版本)的微前端架构应用:
◎ 架构在项目中的可行性验证。
◎ 向领导和团队证明架构的可能性。
◎ 增强团队对于新技术的信心。

将那个最小的、成本最低的应用迁移到微前端架构中。

《前端架构从入门到微前端》一书中,将微前端的实施分为六种:

1、路由分发

路由分发式微前端,即通过路由将不同的业务分发到不同的、独立前端应用上。其通常可以通过 HTTP 服务器的反向代理来实现,又或者是应用框架自带的路由来解决。如图:
2021/01/21 前端规划 - 图7

2、前端微服务化

前端微服务化,是微服务架构在前端的实施,每个前端应用都是完全独立(技术栈、开发、部署、构建独立)、自主运行的,最后通过模块化的方式组合出完成的应用。
采用这种方式意味着,一个页面上可以同时存在两个以上的前端应用在运行。如图:
2021/01/21 前端规划 - 图8
目前主流的框架有 Single-SPAqiankunMooa,后两者都是基于 Single-SPA 的封装。

用基座化的方式来加载其他应用。基座化方式可以支持加载不同的前端框架,以及在基座工程上绑定业务逻辑。

3、微应用

微应用化是指在开发时应用都是以单一、微小应用的形式存在的,而在运行时,则是通过构建系统合并这些应用,并组合成一个新的应用。
微应用化大都是以软件工程的方式来完成前端应用的聚合,因此又可以称之为组合式集成
微应用化只能使用唯一的一种前端框架。
如图:
2021/01/21 前端规划 - 图9

4、组件化微前端:微件化

微件化(Widget)是一段可以直接嵌入应用上运行的代码,它由开发人员预先编译好,在加载时不需要再做任何修改或编译。微前端下的微件化是指,每个业务团第编写自己的业务代码,并将编译好的代码部署到指定的服务器上,运行时只需要加载指定的代码即可。
如图:
2021/01/21 前端规划 - 图10

5、iframe

iFrame 作为一个非常古老的,人人都觉得普通的技术,却一直很管用。

HTML 内联框架元素 <iframe> 表示嵌套的正在浏览的上下文,能有效地将另一个 HTML 页面嵌入到当前页面中。

iframe 可以创建一个全新的独立的宿主环境,这意味着我们的前端应用之间可以相互独立运行。采用 iframe 有几个重要的前提:

  • 网站不需要 SEO 支持
  • 拥有相应的应用管理机制。

在很多业务场景下,难免会遇到一些难以解决的问题,那么可以引入 iframe 来解决。

6、Web Components

Web Components 是一套不同的技术,允许开发者创建可重用的定制元素(它们的功能封装在代码之外)并且在您 Web 应用中使用它们。
在真正的项目上使用 Web Components 技术,离现在还有一些距离,结合 Web Components 来构建前端应用,是一种面向未来演进的架构。或者说在未来可以采用这种方式来构建应用。
如图:
2021/01/21 前端规划 - 图11
在真实的业务场景中,往往是上面提到六种方式中的几种的结合使用,或者是某种方式的变种。下面看我遇到的真实场景。

看原型 ->

微前端的业务划分方式

与微服务类似,要划分不同的前端边界不是一件容易的事。就当前而言,以下几种方式是常见的划分微前端的方式:

◎ 按照业务拆分。
◎ 按照权限拆分。
◎ 按照变更的频率拆分。
◎ 按照组织结构拆分。
◎ 跟随后端微服务划分。

who use qiankun

蚂蚁金服 https://tech.antfin.com/
ZStack——国内领先的私有云计算公司 https://www.zstack.io/product/zstack_cmp/
百应 https://www.byai.com/

微前端的核心为app,微前端的场景主要是:将应用拆分为多个app加载,或将多个不同的应用当成app组合在一起加载。

将应用拆分为多个app加载,或将多个不同的应用当成app组合在一起加载 ,

第一种:可以按功能模块拆分,每个功能是个应用,不限你选择的技术框架
第二种:多个不同项目整合成一个项目,类似 企业的信息门户

image.png

微前端的 8 个问题

  1. 我们如何实现在一个页面里渲染多种技术栈?
  2. 不同技术栈的独立模块之间如何通讯?
  3. 如何通过路由渲染到正确的模块?
  4. 在不同技术栈之间的路由该如何正确触发?
  5. 项目代码别切割之后,通过何种方式合并到一起?
  6. 我们的每一个模块项目如何打包?
  7. 前端微服务化后我们该如何编写我们的代码?
  8. 独立团队之间该如何协作?

组件库建设的规划

项目保留两套框架,vue.js 和 angular.js
vue.js ui组件库ant-design-vue
angular.js ui组件库boostrap

设想一:基于 WinDesign 组件设计规范,先将组件库代码完善起来。

设想二:建立ui标准化,完善前端代码规范。

设想三:搭建个部门前端脚手架

很多小伙伴一直纠结什么是脚手架?其实核心功能就是创建项目初始文件,那问题又来了,市面上的脚手架不够用?为什么还要自己写?
只要提到脚手架你就会想到,vue-clicreate-react-appdva-cli … 但是在公司中你会发现有以下一系列的问题!

  • 业务类型多
  • 多次造轮子,项目升级等问题
  • 公司代码规范,无法统一

很多时候我们开发时需要新建项目,把已有的项目代码复制一遍,保留基础能力。(但是这个过程非常琐碎而又耗时)。那我们可以自己定制化模板,自己实现一个属于自己的脚手架。来解决这些问题。

前端手册

为什么需要手册,手册意义在于,让新加入进来小伙伴可以快速了解项目,项目规范,团队及上手项目,节省熟悉项目时间和项目交接。。。