第三期|前端早早聊大会

1,952 阅读9分钟

会议情况

首先谈一谈对于本期前端早早聊整场下来的一些看法:

  • 核心内容主要有,搭建系统,低代码开发,五代码开发和数据管理
  • 讲师阵营分别来自政采云,淘宝和阿里妈妈
  • 产品范例分别为鲁班,飞冰,MPM,ImgCook,方舟,天马和淘积木

我喜欢的内容笔记

墨冥-如何设计实现营销搭建系统 - 终端秒开

我比较感兴趣的技术点是终端秒开。

技术架构

一 离线链路:面向内部用户的链路

  • 核心依赖:依托于阿里强大的技术生态,营销搭建系统底层有两个强依赖服务
  • 搭建服务:提供了基础的模块,页面,管理实体的 SDK,负责各种搭建实体的增删改查以及协议规范
  • 投放服务:提供了资源位,排期,数据源,投放规则的 SDK,负责各种投放实体的增删改查以及协议规范
  • 方舟:对应产品架构中的产品能力,调用底层搭建服务、投放服务,封装业务层的实体管理,接受来自用户的交互输入,最终向在线链路输出
  • 页面和模块代码
  • 页面配置:搭建体系里核心的模块组成页面的协议描述,比如页面基本信息,包含哪些模块,模块的对应的资源位等
  • 模块的资源位数据配置 二 在线链路:面向外部消费者用户的链路
  • 服务端:
  • 渲染服务:基于从离线链路获取的页面和模块代码、页面配置组装出页面的模板
  • 数据服务:基于从离线链路获取的模块资源位数据配置,进行数据处理,并合并生成页面需要的数据
  • 用户端:阿里系 App 内以及浏览器内,获取页面模板,调用页面数据,渲染出消费者访问的页面

营销搭建的终端秒开

网页从url输入到主要资源加载完成经历流程如下图:

  • 从这张经典的图里,我们可以大致看到一个网页从url输入到主要资源加载完成的主要过程:获取 url -> 重定向 -> 服务端缓存 -> DNS查询 -> 建链 -> 文档传输 -> 文档资源解析和处理 -> 主要资源加载完成。
  • 传统的前端秒开性能优化基本上是通过优化以上各个节点的时间来完成的。

终端秒开最佳实践

上图展示了传统的性能优化最佳实践(如之前常提的雅虎军规),从加载优化、图片优化、CSS 优化、JS 优化,总结下来:

数据预请求,页面级(预)缓存,模块级(预)缓存。当搭建系统发生了局部内容的变更后,会通过客户端(预)缓存管理服务更新客户端内的缓存。

搭建场景下加载优化的核心时序

从整个加载和渲染过程中我们可以看到,理论最佳情况,我们实现了

  • 直接从客户端预缓存中读取 Page Code 和 Module Code
  • 预请求首屏数据后直接开始渲染

沐童-如何设计实现 H5 页面搭建系统 - 数据模型

数据层面临的痛点

1.请求散乱无章
第一种场景:页面请求茫茫多,有时候想定位页面中某个请求来自哪个组件,可能得定位半天。

  • MPM 负责搭建的是卖场,卖场往往是流量入口,承载了各线业务,因此接口场景特别复杂。如果我们简单地将请求完全交给组件自身,各自发起和处理,其结果就是页面请求散乱无章,维护困难不止,甚至可能互相影响。

2.多余的重复请求 第二种场景:某个页面中,有多个组件都配置了同一个预约 ID,导致页面发出了 N 个一模一样的预约态查询请求。

  • 在自搭建场景,这种请求重复的问题再常见不过,假如我们没有对数据请求进行统一管理的话,那么很有可能这些无效的重复请求将严重拖垮你的页面性能。

3.接口压力大
第三种场景:商品接口支持批量请求,但由于页面的各个商品组件是独立请求的,导致多个商品请求并没有聚合,走批量调用。

  • 一些常用的业务接口往往会支持批量调用,目的就是为了减轻服务调用压力。但是由于我们没有对请求进行统管,无法聚合,使得页面多次请求同个业务接口,给服务造成了不少压力。

4.数据模型多变
第四种场景:商品组件下的各个模板,除请求商品之外,有些模板会拉取新人价,有些模板会拉取补贴价。

  • 这是页面搭建经常面临的问题 —— 数据模型多变。每个组件都对应了多个模板,每个模板又可能对应了不同的数据模型,那么如何进行数据模型的组合,这么多数据模型又该如何有效维护和管理,也是一个大问题。

5.三端同构诉求
第五种场景:以 Vue 为例,我们习惯在组件创建时,也就是 created 钩子函数中请求数据,这在客户端渲染时表现很完美,但在直出场景下却完全行不通。

  • 归根结底,这其实是因为 Vue 虽然支持了 SSR,但对异步数据获取的同构支持却很不完善。为了适配 MPM 的三端同构,数据层设计必须考虑这个问题。
请求模型设计

1.数据源
我们认为,请求模型的复杂性在于请求组合的复杂性,请求可以串联、并联及串并联混合,请求还有主次之分。 要应对请求模型复杂灵活的组合,首先我们需要对请求进行量化,也就是说,我们需要一个最小单元来描述请求,请求模型则基于这些基本单元进行自由组合,这个最小单元就是数据源。

数据源是请求模型的基本组成单位,描述了一类请求动作,它包括以下几个基本属性:

  • 接口地址:数据源和接口是一一对应的
  • 请求前置处理:发起请求前的参数组装处理
  • 请求后置处理:请求响应后的一些通用的数据处理
  • 入参校验:发起请求前引擎会先对入参进行合法校验,非法入参将不会发起请求
  • 聚合分发策略:描述了如何对该接口的多个同类请求进行请求聚合和响应分发
  • 监控统计配置:接口监控、统计相关的配置

我们用一个类来实现数据源,一旦想要请求这个接口,调用层只需要以配置参数为入参进行实例化,就可以得到一个请求对象,引擎可以理解请求对象,并发起一个真正的请求。

数据源有很多个,每个数据源都有自己的名称标识,在调用层,我们只需要通过数据中心提供的 fetch 方法,指定数据源标识并传入配置数据,就可以建立起和数据源的绑定关系,来选择调用某个数据源。

基于这样的设计,我们可以很方便地实现请求模型的自由组合。

首先我们要求数据源应该是纯粹且专一的,它应该只做一件简单的事,比如跟这个接口密切相关的一些通用处理逻辑,而像一些跟特定部分组件/模板业务逻辑相关的处理,则不应该出现在这里,这是自由组合的前提。

其次,我们允许由数据源以各种形式自由组合成更高级、更复杂的请求模型,或者叫高级数据源。对于调用层来说,既可以直接调用数据源,也可以调用封装好的高级数据模型。

数据源如何组合成高级请求模型呢?这里我们采用了最简单灵活的函数调用,而不再是以类的形式来组织。函数天然拥有的作用域机制,对实现灵活多变的请求模型十分有利。上图就是这样一个例子,我们在函数内串联调用了商品、优惠券两个数据源,简单地实现了一个“带券商品”的请求模型。

高级请求模型是个函数,同样也就拥有唯一的名称标识。所以向上,我们将调用方式对齐,因此对于调用层来说,究竟是直接调用数据源,还是调用高级请求模型,其实没什么区别。


另一方面,依靠数据源,我们也有效地实现了统一管理。上图是数据源请求的整体工作流程,其中有两个核心模块 —— 数据中心和请求中心:

  • 数据中心:是页面请求的代理层,页面所有请求都将经过数据中心,请求聚合分发在这里进行;
  • 请求中心:解析来自数据中心的请求对象,发起请求并返回响应,请求的去重在这里进行。 借助这两个核心模块,整个页面请求的流程大致是这样的:
  • ①.页面或楼层向数据中心申请一次数据请求,申请内容携带了数据源标识 source 和配置数据;
  • ②.数据中心根据数据源标识 source,选取相应数据源,并实例化一个请求对象,发给请求中心;
  • ③.请求中心解析请求对象,发起请求,并处理响应,返回处理结果到数据中心;
  • ④.数据中心再透传给调用层,触发响应渲染。

关于大会:前端早早聊大会目标成为用得上,听得懂,抄得走的前端大会,计划 2020 年办 12 期,由前端早早聊与掘金联合举办,未来前端早早聊大会行程动态、资料下载请扫码下方公众号跟进: