面向体验的重构优化

面向体验的重构优化

前端重构程序员是一个关注代码同时还要留意体验的异类。代码的优化虽然难,但是有比较多的性能测试工具去证明优化的成果。然而体验这种东西,我们又要如何去证明它的好与坏呢?

一、视觉体验优化

  1. 页面加载
  2. 数据请求
  3. 图片渲染

二、数据证明体验效果

今天我着重会基于「webnovel」PC站点从以上两点给大家介绍,如何从体验的角度去做重构的优化,并如何用数据去证明你的优化是有效果的。

一、视觉体验优化

我们要做体验的优化,首先要我们要知道什么才是好的体验。

不知道哪里听过这么一句话,「 好的体验,就是感觉不到在体验 」。这句话听起来很矛盾,但是却和业界公认的体验小红书「 Don’t make me think 」的理念一样。你想用户来「 webnovel 」是来看小说的,不是来称赞我们网页体验做得多么优秀的。当用户开始关注到我们网站体验的时候,那正是说明我们的体验不好的时候。

那用户在什么地方容易感受到我们网站的体验呢?

页面加载

第一个地方就是页面加载的时候。这里我们明显可以看到「 webnovel 」的 Logo 和三个小图标在页面刷新的时候,会有一瞬间从无到有的过程。

我们「 webnovel 」站点是面向全球海外用户的,跳出了国内兼容 IE 浏览器的怪圈,于是在小图标这块我们选择了浏览器兼容性要求高,但是呈现效果却更好的SVG图标「 SVG 属于矢量图标,在能保证体积更小的情况下,还能在放大缩小的时候不失真 」。我们将 Iconfont 「来自阿里的在线图标管理工具 」自动帮我们生成的 JS 代码引用到页面中,结果就出现了上面的呈现效果。

这个原理其实很简单,我们 SVG 图标的 DOM 结构是在 JS 执行之后动态添加到我们的标签内部的。所以就会出现先呈现页面,再呈现图标的效果。于是我们很自然的想到,直接将 JS 生成的 DOM 结构放到我们的内部,来解决这个问题。

但是很傻很天真,在拷贝 DOM 结构的时候我们发现,这个 SVG 代码量也太多了,直接放到页面内部会大大增加我们 HTML 的代码量,影响整个页面呈现的速度,这个感觉是捡了芝麻丢西瓜。

最后我们采用的解决方案是,把 SVG 图标做了拆分,首屏的显示的图标我们采用直接添加 DOM 的方式,其它剩余的图标还是选择 JS 动态加载老方法。这样首屏之外的图标即使有闪动用户也很难看到。于是我们解决了首屏图标闪动的问题,也避免了 SVG 图标代码量的问题。用户感知不到图标的闪动,也就不会花时间去思考我们页面加载是快是慢的体验问题了。

提前加载首屏数据,能一定程度上增强我们用户刷新和跳转页面时候的体验。

数据请求

第二个地方的就是我们数据请求的时候。当我们切换TAB的时候,能明显看到一个 Loading 的效果。用户的动作触发数据请求,在等待的过程我们用 Loading 来告知用户这一状态,以减弱用户等待的焦虑。这其实是一个对于数据加载,增强体验常规的做法。

可是不管我们的数据请求多么的快,用户都还是能明显能看到这个 Loading 的效果。这并不是我们想要的。

我们这边处理的办法是,在用户鼠标放到这个按钮的时候,我们认为用户是有了点击的意愿,于是我们就提前发起了数据请求的操作。当用户按下这个按钮的时候,我们的数据请求的整个过程可能已经结束,而这也就意味着我们的 Loading 状态已经消失。此时用户就能直接看到我们加载好的数据了。也就是说很有可能,在整个过程中用户是看到不到我们的 Loading 状态的。这不就是我们想要的体验上的优化吗?

利用用户操作的空闲时间,提前做一些预处理,不失为一个增强数据请求体验的好办法。

图片渲染

我们都知道,图片和图标都是属于展示性的元素,特别是像我们 「 webnovel 」网站设计师很用心制作的书封,我们自然会愿意选择体积更大但是质量更高的高清图。为了避免影响正文的展示,我们又不得不选择了类似图片 Lazyload 的机制,让这个图片延迟加载。

但是可以明显看到这和之前的数据加载的 Loading 逻辑一样,需要一个表示 Loading 态的占位图。等图片加载完成,占位图会一瞬间被我们的高清书封替换,于是此时就出现了我们不期望的闪动。

当用户一看到闪动,他们就会去思考你这个加载是快还是慢。但是我们要的是 「Don’t make me think 」。我们不希望让用户去思考除开我们产品之外的东西。所以我们得想个办法弱化甚至去除这种闪动。

讲到这里呢就不得不科普以下我们浏览器本身就有的图片缓存机制了。在一定时间段内你浏览器访问过的图片,会被浏览器缓存。当你再一次看到这个图片的时候,这个图片就直接读取浏览器缓存的内容一瞬就打开,不会有闪动问题。

于是我们就想是不是可以利用这个机制,解决之前闪动的问题。但是现在难点是,我们详情页的书封是比首页的书封大的。因为尺寸不一样所以是不同的图片,于是就没有缓存这个概念。

如果我们让详情页也用首页的书封,详情页小图被拉伸就会看起来很模糊。如果首页用详情页的大书封,首页的图片数据加载开销又太大。

我们这边采用的解决方案是,三层叠加法。我们把占位图,小书封,大书封,按照上图的层级完美的叠在了同一个位置。当用户从首页进入到我们详情页的时候,我们占位图和小书封都是直接使用浏览器缓存瞬间呈现的,因为小书封是叠在占位图之上的,所以用户是看不到占位图的。而此时大书封正在加载,当大书封加载好了之后,就会盖在小书封之上。等用户仔细看这个书封的时候,这个大书封其实很有可能已经加载完成。

从上图的GIF可以看出,整个过程就从之前的占位图到大书封的闪现,变成了现在的小书封到大书封的渐变。其实这是很难被用户发现的。

看到这里可能有同学会问说,既然这里都看不到占位图,为什么还需要加载这个图呢?其实原因很简单,因为不是每个人都是从首页进入到详情页的。有可能用户是直接打开的这个链接。那么此时占位图就回到了最初的逻辑。先看到占位图然后再看到书封。当然我也得承认对于这样的用户,我们其实是多加载了一个小书封的资源的。但是对于体验上的优化来说,这一点资源的消耗我个人认为还是可以接受的。

还有一个好玩儿的点是,在这个地方因为同时加载了,占位图,小书封,大书封,它们作为图片也都会被浏览器缓存,当用户跳转到其它页面的时候,如果有相同的图片,那又是瞬开的。这样我们就充分的利用了浏览器缓存,让用户在我们网站上的体验得到了进一步的提升。

图片缓存,让网站体验比好更好。

二、数据证明体验效果

视觉层的体验优化是所见即所得的,你可以很快的看到优化的成果。但是有很多因为浏览器差异,或者用户差异引起的体验问题,我们没法直观和快速的去证明体验优化的效果。我们就得靠数据去证明了。

要用数据说话,首先我们得有数据,而这个数据的收集工具我们海外 PC 站用的则交给了来自 Google 的 Analytics。这边给大家讲关于这个的一个有趣故事。

有一天我在用 webpagetest 「 一个全球知名的测试网站加载速度的工具 」测试我们 「 webnovel 」页面的时候我看到了这样一个结果。

大家注意看那个最长的绿色,看到了吧,一个 DNS 加载怎么比后面的 SSL + CSS 加载 + CSS渲染还要长?CSS 可是强制阻塞我们页面渲染的重要元素,它要是慢了,你网站做再多优化都没有用。这个你让人怎么忍?

怎么办呢?我们选择了一个暴力但是有效的办法,直接把 CSS 合并到我们的 HTML 文件中 「 CSS 内联到 HTML 内部 」。CSS 文件都没有了,看你还怎么 DNS、SSL … 哇!好棒,我拿着这个去找老大邀功。老大啪啪给我提了两个点就把我打懵了。

第一, 你这个明显是首次加载页面时候的效果,对于大多数这个 CSS 文件已经有缓存的用户,你如何证明,这个优化对他们是又用的?

第二,「 webnovel 」是面向全球的网站,你又如何证明,这个优化对所有地区的用户的优化力度 ?

是啊我要怎么证明?「 webnovel 」全球这么多的用户,我就用一份 「 webpagetest 」 的测试报告去涵盖所有的终端和用户群体,显示是不具有公信力的。并且我又要如何证明这个优化的力度是多少?

此时中国好同事出现了,我的前端逻辑小伙伴帮我在框架机内部做了一个随机预处理的AB样本输出。道理很简单,就是让 50% 的用户是用原始的方式加载我们的 CSS ,另外 50% 的用户使用我们 CSS 内联到 HTML 内部的方式。这样我只需要加个标识符区别一下这两个样本,上报到 GA 「 Google Analytics 」 ,然后 GA 会自动帮我们统计和处理这些样本,最后我只需要将这两个样本的平均值做一个 10 以内的减法,就知道了我们的优化力度具体是多少了。

然而另一个问题出现了,我们应该把什么作为数据上报给 GA 呢?显然用整个网页的加载时间去证明 CSS 的加载是不对的。那我用 CSS 加载完成之后的那个时间去证明?可是我又怎么能证明 CSS 加载完成之后页面就已经渲染好了呢?我们不是在做体验的优化吗?又怎么能仅凭借 CSS 文件的加载来证明用户体验变好了呢?

此时我是凌乱的。不行,整个场面我要HOLD住,不能慌。

体验,体验,CSS都没有加载,用户连页面都没有看到又怎么能叫体验?于是用户刚看到页面的时间,被我认定是一定程度上可以证明体验优劣的。

怎么去获取这个时间呢?其实利用 performance API,就可以获取到上图所示的浏览器各个阶段的时间。

Chrome浏览器 可以用 window.chrome.loadTimes().firstPaintTime; IE8+ 浏览器可以用 window.performance.timing.msFirstPaint;

来获取页面开始渲染的时间。最后大家一致的意见是,将这个 「 firstPaintTime - navigationStart 」的时间近似理解为用户从访问页面到看到页面的时间。

于是,我很开心的把这个这个时间上报到 GA,然后版本上线,等待数据收集。最后得出如下的统计结果:

看到以上的数据结果,这个优化的时间和总时间比起来比预想的差太多了。感觉不应该啊?

当我们仔细分析这个数据,发现在这整个的时间段内,服务端的时间占了 1.1s 。我在这拼命的优化体验,可是最后发现体验的瓶颈并不在我们前端这边。这充分的说明,有的东西还是得靠数据说话,而不是你以为你以为的就是你以为的。当然除开这个瓶颈时间我们可以得出如下的结论。

至此我们有理有据的证明了优化体验的成果,虽然结果出乎了我们的预料,但是却证明,数据上报是能够证明我们体验成果的一个有理证据。

当然我们也把这个瓶颈问题,反馈给力服务端的同学。然后得到的答复是,「 webnovel 」还属于我们海外站的新项目,很多海外服务器有待跟进。相信在后续设备之后,会解决这个痛点。

数据上报,让你的体验优化有理有据。

总结

篇幅有限,这边我只是零散的列举了,我个人认为可以从用户体验角度去做的几点重构优化,以及如何利用数据去证明你优化的力度。希望对于大家有一定的启发和帮助,有什么问题,也请给我留言,我们可以深入的交流。


本文作者:ziven 郑成忠

原创声明:本文为阅文前端团队 YFE 成员出品,请尊重原创,转载请联系公众号 ( id: yuewen_YFE ) 获取授权,并注明作者、出处和链接。

编辑于 2018-09-10