微信扫一扫
分享到朋友圈

百度Web前端开发实战案例解析

作者:InfoQ 来源:InfoQ 公众号
分享到:

11-10

从 Web 诞生到如今,Web 前端技术已经逐步成长为一个丰富且有活力的技术世界。随着互联网行业发展格局的频繁演进以及产品策略的不断调整,不同阶段的业务在技术选型、前端性能优化、用户交互体验上不断产生新的需求,不断地对 Web 前端技术提出新的要求。

10 月 27 日,82 期百度技术沙龙,邀请了数位百度前端技术部 Web 前端资深研发工程师,从 Web 前端技术出发,通过五个主题,立足现在面向未来,由内到外地分享百度在搜索组件化的探索、搜索体验增强、开放 Web 速度优化及开放 Web 未来发展发面的技术沉淀和积累。

1 搜索组件化探索与实践

首先进行分享的是百度前端技术部资深研发工程师陈骁带来的《搜索组件化的探索与实践》。

为什么搜索要做组件化?

据陈骁介绍,最开始的百度搜索移动端的前端架构是从 PC 时代迁移过来,服务器端使用 Smarty 来渲染模版,实现前后端分离。前端使用 Zepto 来完成交互逻辑,但是它的扩展性比较有限,难以实现对 HTML、CSS 代码的组件化管理,随着移动端的交互形式越来越复杂,原本的方案出现了局限性。

于是,组件化应运而生。组件化是把一些可复用的单元提取出来,通过对几个组件的管理,实现对整个搜索结果页样式的控制,提高开发的效率和横向团队整体升级的效率。

目前百度已经有了非常多的组件化解决方案,包括 Lavas 和 Reac t。可以具体到组件语法、基础框架以及同构区块。

如下图所示,组件语法包括四部分:

  • Template:组件代理结构

  • 浏览器端:组件前端逻辑

  • Style:前端样式

  • Config:同构逻辑

前三部分基本能够覆盖组件的常用语法,而同构在服务器端和浏览器端都能执行,主要有 props、data、components、computed 等。

那么这个组件代码怎么在线上跑起来呢?

首先会在线下通过编译器,把它编译成 PHP、JavaScript 两份原码。PHP 的编译产物完全使用 PHP 的语法,可以在后端形成一个 Server Runtime,在这个过程中,也能够把 PHP 的编译产物渲染成字符串,通过网络传输到浏览器端。而在浏览器端运行时可以用编码产物 Javascript 的组件,渲染成可操作的 HTML 代理结构,包括它的事件和交互。

其中的难点在于怎么把一个组件代码编译成在 PHP、在 JS 都能跑的组件代码。百度会做对于模板和一些表达设计的处理。例如,模板代码有一个文本节点,有一个自定义组件,在编译的过程中,会利用编译器把它转化成抽象语法树,形成树的结构,每个节点都有一些属性和信息,利用语法树的结构和属性信息,就可以通过代码生成器分别生成 PHP 和 JS 的代码。

这里还有一个问题,为什么需要一个同构区块呢?这是因为同构区块可以很好控制服务器端能执行的代码,方便语法解析。另外,百度对同构代码块进行语法限制,以保证服务器端的稳定性,也可以更加方便解析成想要的 PHP 代码。

通过改造,组件化渲染框架不仅可以使得效率提升,保证了体验一致性,而且进行了横向升级降低成本。

性能优化

针对服务器端的渲染性能,百度做了非常细致的优化:

  • 在框架层,对渲染流程进行了简化,添加了缓存;

  • 在基础组件层,对控制的简单组件进行编译优化;

  • 在业务层,提供先验工具、准入规范,线上监控和报警,并提供 a-nossr 指令。

那么组件是如何在服务器端渲染成想要的 HTML 字符串呢?

如下图所示,会经过以下步骤:首先,加载组件的配置,创建组件的实例。在实例的创建过程中,对这个组件所有的数据进行初始化,包括一些特征和计算属性,得到初始化状态以后,再渲染出虚拟 DOM 树,把整个组件节点数渲染成一个实例的形式,用虚拟 DOM 树渲染成 HTML 字符串。

与此同时,百度搜索对整个渲染的过程进行了简化。在框架层,通过创建虚拟 DOM,减少了一次递归,也减少了在线上运行时的逻辑。在基础组件层,百度对横向团队能够完全控制的一些简单组件进行了优化。利用 HTML 编译器编译成语法树,语法树对它每一个 AST 节点进行优化,通过将 Tag 直接定义为普通的 DOM 节点的方法,生成最后想要的函数代码。

框架层:渲染流程简化

简单组件编译优化

目前进展

目前,百度提供搜索组件化的工具。比如搜索 Web 无障碍规划、搜索性能准入规范、搜索设计规范;服务方面包括性能监控、前后端异常监控等;运行方面提供 VSL 语音交互框架帮助开发者开发一些语音交互逻辑;工程方面提供搜索敏捷平台,帮助开发者直接完成联调、提测、上线;在应用方面,有卡片、图片搜索、咨询搜索、移动端的首页,还有一些独立的站,包括百度体育和百度招聘。

搜索组件化技术全景图

2 移动体验标准化建设

第二个 Session 是由百度前端技术部资深前端工程师刘浪宇带来的《移动体验标准化建设》。

极致的用户体验是 Web 产品所追求的,那么什么是好的用户体验,如何去量化用户体验做到好的体验呢?首先需要有一套清晰的体验指导标准,然后再去落地。

移动体验指南

移动体验指南是基于移动 Web 生态提出一套通用的体验指导规范,目的是更好地服务于用户及产品的系统,为广大用户提供优质的体验。从用户的体验层次、交互和移动 Web 现状,百度归纳出六个纬度:

第一,快速的信息呈现。速度快慢直接影响用户对站点的体验评级,所以让主体内容快速呈现给用户才是优质的体验必需的。

第二,设计交互层面强调一致性。一致的设计交互可以利用用户的学习经验,降低学习和使用的成本。

第三,好产品需要做到让用户低成本、高效地完成所有交互操作,整体操作要清晰无阻,带给用户最流畅的体验。

第四,内容强调优质阅读观感。站点的内容可读性、内容本身质量是否能够达到,都是优质的体验所必需的。

第五,情感层面有两点,首先是愉悦的情感认知,其次是让用户对站点信任,页面是否安全、是否及时告知流量信息等等。

第六,关于强健的场景适配,优秀的站点应当适合于不同的人群和宿主环境。

移动体验检测平台

有了体验指南,如何快速知道站点存在哪些问题?这就需要体验检测平台 Radar。

Radar 的最底层是 Headless  Chrome,百度通过协议接口可以非常快捷地操作这个浏览器。中间的运行是基于谷歌开源的一个网页工具 Lighthouse 。它主要有两个内容,第一是网页数据收集,通过数据分析获得数据,按照规则的需要,对于这些数据进行分析后输出想要的结果。第二,Radar 的核心是非常多的规则,主要分两类,一类是普通的,一类是交互的。

刘浪宇以交互的规则为例,详细阐述了一个规则是如何实现的。如下图,交互的规则主要分为两部分,第一是场景识别,第二是交互分析。举一个比较简单的例子,当用户在页面看到一个输入框时,觉得点击可以直接输入是一个良好的体验。那么如何量化这个规则呢?首先是场景识别,找到在这个页面中看起来像评论输入框的元素。然后找一些特征,从海量数据里面标注、提取一些通用特征之后为这个场景建立特征库。之后再基于场景所需要的特征,进行网页结构化数据提取。

Radar 规则架构(交互类规则为例)

接下来这些场景元素就要进行交互分析,首先进行深度筛选然后进行交互操作。以模拟屏幕的点击举例,点击之前用户会看页面的变动,比如说 DOM 的变动、跳转的变动,然后对变动进行分析,看是否符合预期。

3 基于 Custom  Elements 标准组件化构建 Web 应用

第三个主讲人是百度前端技术部资深前端工程师邹淼江,他现场分享了如何高效快速的构建一个体验良好的 Web 应用、基于 Custom Elements 标准的组件化设计、如何提升用户端体验和开发效率。

首先看自定义标签,自定义标签在功能上逻辑上与 JavaBean 类似,都封装 Java 代码,是可重用的组件代码,并且允许开发人员为复杂的操作提供逻辑名称。另外,自定义标签具有⽀持⽆障碍、提高开发效率、评估性能、对 SEO 良好的特点。

其中,如何使用自定义标签进行性能评估呢?百度提供了一套搜索引擎的验证工具。比如,符合某一种规则的 Custom  Elements,给它标高分,为符合高性能标签。但如果使用 DIV 的方式,搜索引擎没办法知道布局是不是高性能,也没办法知道所对应的 JS 如何实现,如果有了 Custom  Elements 的标准,就能清晰地知道这个页面想干什么。

基于此,我们可以设想:如果完全使用这些 Custom  Elements 语义化标签构建 Web 站点可行吗?

这就需要引入组件化设计。其实目前存在的组件化设计都千篇一律,把一个页面的功能模块以组件树状的形式自由组合,堆积成一个功能的页面或者是模块,这就是组件的结构。具体要求:

  • 每⼀个 Custom Element 是⼀个组件

  • 组件内部实现相应的交互、功能和数据处理逻辑

  • 组件之间逻辑和样式是独⽴隔离的

  • 组件是可以通信的

  • 组件是可复⽤的

Web Components 标准

Web Components 是指通过一种标准化的非侵入的方式封装的一个组件。主要标准包括 Custom Elements,Shadow DOM,HTML Templates,HTML Imports 等多个维度的规范与实现。

  • Custom Elements 是提供一种方式让开发者可以自定义 HTML 元素,包括特定的组成,样式和行为。支持 Web Components 标准的浏览器会提供一系列 API 给开发者用于创建自定义的元素,或者扩展现有元素。

  • Shadow DOM 旨在提供一种更好地组织页面元素的方式,来为日趋复杂的页面应用提供强大支持,避免代码间的相互影响。开发者可利用 Shadow DOM 封装自己的 HTML 标签、CSS 样式和 JavaScript 代码。

  • HTML Imports 是一种在 HTML 中引用以及复用其他的 HTML 文档的方式,可以简单理解为常见的模板中的 include 之类的作用。我们可以通过 HTML  Import 的形式,直接将做的 Custom  Elements 的标签放进 HTML 中进行渲染渲染。

Web Components 兼容性

4 搜索落地页体验技术及应用

第四个主题由百度前端技术部前端工程师李兆明讲述。如何更快、更好的将各类搜索结果页面传递到用户端一直以来是百度搜索前端的核心关注点。基于此,李兆明分别从如何让落地页加载更快,如何让搜索结果页和落地页之间切换更加顺滑以及未来的新标准,介绍百度搜索落地页体验技术的探索。

如何让落地页加载更快

思路一:提前加载。通过 Resource Hint 提示浏览器预解析域名、建立预连接,甚至进行预渲染。若是不支持的浏览器,则可以通过 JavaScript 模拟一部分。

思路二:抓取数据。通过开放平台提交数据,由百度来渲染。

思路三:MIP / AMP。MIP 提供多重措施,让使用 MIP 技术的页面加载速度更上一层楼。例如,CDN 加速服务;使用 MIP 设计的网站没有任何可以阻塞渲染的脚本,所有脚本都在页面主体加载完成后才执行。此外,MIP 要求所有页面都是静态的,如果有需要实时更新的数据需要异步获取,这样设计节省了后端的渲染时间。

如何把两个页面融合在一起?

其实,无论有多少优化加载速度的手段,归根结底离不开页面跳转。但是,浏览器跳转相对来说不够平滑,用户体验不够好,能不能把前后两个页面融合到一起呢?

答案当然是肯定的。李兆明在保证体验、保障安全及保持开放的基础上,讲解了百度前端搜索的解决方案:

  • 保证体验:通过 Iframe 加载页面;通过 PostMessage 等方法实现交互动效。

  • 保障安全:不允许使用外部脚本,需要封装组件审核;通过校验确保 HTML 符合规范。

  • 保持开放:通过 GitHub 追踪开发。

展望新技术

在未来,百度搜素将基于域名、Iframe 渲染问题,为开发者带来 Navigation Transition、Promotable Iframe、Portals 及 Web Packaging 新标准,带来最流畅的体验。

Navigation Transition:页面切换的交互方式。解决了跨域问题,没有 Iframe 渲染的历史包袱。不过前一个页面依然不能控制后一个页面的加载、渲染。iframe 可以提前加载,但是 Navigation Transitions 一定要在用户切换的时候加载。

Promotable Iframe:与 Iframe 相关,核心代码是 Promotable 的 API,只要调用 Promotable,就会调动页面的一小块,而后调动整个页面及内容。但是这种方法涉及一些生命周期的管理和 JS 的回收问题,是不够安全的实现,而且这样没有解决 CDN 的问题,依然需要改域名。

Portals:传送门,将一个页面传送另一个页面。这个标准是 Promotable Iframe 的增强,引入了一个新的 HTML 标签 portal,这个标签用来替代 Iframe 显示一块网页,写法和 Iframe 类似。但是它比 Iframe 多一个功能,就是可以通过 “active” 方法激活它。与此同时, portal 的子文档会收到一个 portal zactive 事件,事件中可以拿到它的上级元素,这样又可以把上级元素当成一个 portal 插入回自己的文档流,使得页面切换回去成为可能。

Web  Packaging:解决了 CDN 跨越问题。这个标准包括三方面:签名、打包、加载。如下图,左边内容提供者是站长,缓存的 CDN 类比 MIP 的 CDN ,右边是访问用户,用户浏览我们百度搜索结果页的时候,通过 MIP 的 Cache CDN 提前把数据取过来,用户真正点击的时候,直接从刚才取回来的页面去加载它。由于内容本身是内容提供者提供的,所以他可以对于自己 URL 进行签名。有了这个签名且签名有效的时候,浏览器可以自己显示原始的网址,同时原始的网址可以和原来的服务器进行交互,像通过原网址打开的一样,解决了 CDN 跨域问题。

5 如何通过 Lavas 快速构建 PWA 站点

最后一个主题的讲师是百度前端技术部资深研发工程师王轶盛为大家介绍如何通过 Lavas 快速构建 PWA 站点。

PWA

PWA(Progress Web App)是 WEB 未来的发展方向。从体验上来说,PWA 接近原生 APP,通过 Manifest 技术允许用户快速打开站点并获得沉浸式的体验,通过 Service Worker 能够做到资源预加载和离线可用等从而提升性能和可用性;同时 PWA 又拥有 Web 站点的共同优势:免安装和自动更新。

但与 Web 站点不同的是,PWA 又具有可靠、快速、黏性等特点:

第一是可靠。在断网的情况下,PWA 可做到比较友好的离线提示,这个是 PWA 断网的最高级,叫断网可用。

第二是快速。53% 的用户会放弃加载时间超过 3 秒的网站,越快的加载速度就有越少的用户流失。PWA 提供 Service  Worker,确定哪些访问缓存、哪些访问网页,缩短加载时间。

第三是黏性。黏性是指用户访问过一次,下一次访问是否麻烦。PWA 会用一个半秒的启动动画来保证浏览器首页启动的顺滑。另外,启动之后没有的地址栏、菜单栏,保证用户的沉浸式体验。

从技术层面讲,PWA 有分为四部分:

第一是 Service  Worker 。定义预缓存、网络拦截和缓存策略。它本身是一个 Worker,有专门的语法,需要 CACHES API,需要注册及更新。

第二是 Manifest 。这是一个 Json 文件,定义快速入口,启动动画。

第三是 Web Push and Notification 。是服务器推送给客户端的主动通知。

第四是 APP Shell 。这并不是新技术,但它是常用的 PWA 架构。简单来说,就是把一个 APP 分成了外壳和内容,用 Service  Worker 把外壳缓存起来,将里面的页面进行跳转。

通过 Lavas 搭建 PWA 站点

Lavas 包括工具、文档以及对应的解决方案和建站模板,是一个开源的解决方案。Lavas 本身有两部分,Lavas cli 和 Lavas core,内部用 Vue + Vue Router + Vuex 搭建站点,内置两套模板 (basic & app-shell),支持传统模式 SPA 和 SSR 快速渲染,可以快速拥有 PWA 特性,灵活性强,配置简单,而且文档及时更新,内容完整。通过 Lavas 搭建 PWA 站点主要有八个步骤:

  • 准备环境 & 初始化项目。安装 Lavas cli,初始化项目,选择模板,安装依赖。

  • 创建新页面。

  • 添加链接。使用 <router-link>,注意和 Vue 保持一致,to 属性指明目标页面,支持字符串格式的地址,支持对象。然后启动调试服务器。

  • 和服务端通讯。安装 axios,引入 axios,向后端发送请求。

  • 使用 Vues 管理数据。

    • 创建 STORE,需要定义一些内容。把请求数据移动到 action 里面,获取成功后调用 commit 触发 mutation 去更改 state。

    • 在组件中,通过 store.dispatch 触发 action 获取数据,然后通过 mapState 把 state 和计算属性关联,最后通过计算属性在页面上使用。

  • 配置 Manifest 。Manifestt.json 定义了启动 URL,定义各种尺寸的 icon,定义动画配色和启动模式。

  • 配置 Service Worker。配置,指定模板位置、构建位置


  • 构建和上线。执行构建命令 > lavas build;启动生产环境 > cd dist,> lavas start。

Lavas 技术原理

Lavas 的技术原理主要有自动生成路由规则、Skeleton、App Shell。

Vue  Router 需要四个步骤做整件事情:第一步定义和引用组件,第二步把组件和路由联系起来,第三步是把刚刚联系起来的数据放到 Router 函数创建实例,第四是把 Router 放到 VUE 创建实例,结束 Vue 实例挂载就。

经过改进, Router 不用自己定义页面级组件,可以认定只要在 Pages 目录中,那组件都是页面级的,从而可以实现自动化 Import,不需要每次写一大堆的代码。另外,绝大多数情况路由规则和组件名称是有对应关系的。自动生成路由规则映射,省去了列出映射关系的麻烦,也避免后期组件改名带来的维护成本。

Skeleton 叫骨架屏,就是实际内容展现之前,有个大概内容给用户看,这样用户提前看到一些东西。这是 Loading 升级版,因为每个组件可以自定义样式、切换时机、列表等。

Lavas 的 Skeleton 都可以用,实现思路是 Vue 的挂载点一般是个空的 DIV,在构建时将 Skeleton 的内容添加到挂载点中,Vue 挂载前清空 DIV 内的占位内容,挂载后渲染为实际内容,使用 SW 预缓存 HTML,访问时直接从缓存中获取 HTML,这样可以让用户看到占位的东西。

App Shell,就是把一个 APP 分两部分,有外壳和内容,把外壳缓存起来,每打开页面先把外壳拿出来,然后再是内容渲染。App  Shell 实现有两个步骤,第一是划分,告诉程序哪部分是外壳、哪部分是内容;第二是程序把外壳缓存起来。这需要实现两方面,第一是 SPA,首次请求服务器返回 Index.HTML,所有页面的渲染均由 JS 完成,只在挂载点内重新渲染,单页 Index.html 就是 Shell,使用 SW 预缓存 Index.html 即可。第二是 SSR,首次请求服务器返回给全部内容,后续页面的渲染由 JS 完成。

Web 生态的发展就是互联网的发展,新技术的不断涌现和新场景的不断实现也让这个开放的生态得以持续繁荣。王轶盛表示,百度希望国内的开发者与站长能够多多参与到 PWA 项目中,共同建设和改善国内的 Web App 生态。

阅读8327
开发 案例 
举报0
关注InfoQ微信号:infoqchina

用微信扫描二维码即可关注
声明

1、头条易读遵循行业规范,任何转载的稿件都会明确标注作者和来源;
2、本文内容来自“InfoQ”微信公众号,文章版权归InfoQ公众号所有。

评论
更多

文章来自于公众号:

InfoQ

微信号:infoqchina

邮箱qunxueyuan#163.com(将#换成@)
微信编辑器
免责声明
www.weixinyidu.com   免责声明
版权声明:本站收录微信公众号和微信文章内容全部来自于网络,仅供个人学习、研究或者欣赏使用。版权归原作者所有。禁止一切商业用途。其中内容并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现头条易读网站上有侵犯您的知识产权的内容,请与我们联系,我们会及时修改或删除。
本站声明:本站与腾讯微信、微信公众平台无任何关联,非腾讯微信官方网站。