需求背景
七猫中文网首页重新改版,并且实现前后端分离,之前的首页是php渲染的静态页面,前后端分离后是nuxt框架实现的服务端渲染。
新版本的七猫中文网首页设计稿如图所示,可以看出改版后的首页包含模块是比较多的,因此在实现方案上要考虑内容过多导致首屏加载过慢的问题。
组件规划
首页的内容比较多,因此在开发之前首先定义好页面的组件,然后对组件进行拼装展示;
1、公共组件类:
qm-main:主要用来控制页面内容区域的宽度
qm-row:楼层组件,首页的内容可以看为是多个qm-row堆叠起来,并且每层的间距都是一样的
qm-col:对于纵向的模块划分,例如排行榜模块可以认为是4个qm-col组成的模块
qm-mod:标题+内容,统一管理首页标题的样式,以及标题和内容区域的间距;
qm-book-cover:书籍封面组件,包含功能:封面的懒加载、hover动画、加载错误处理,通过参数配置支持多种尺寸的书籍封面;
qm-card:卡片组件,统一管理卡片的圆角以及背景色;
2、业务组件
根据具体的模块内容,定义相应的业务组件;
数据加载
由于内容过多,我们首先考虑的方案是将首页内容拆分为4个大的模块,通过多个接口下发数据,然后只有第一个模块的内容在服务器上渲染,其他模块在浏览器端加载,这样既保证了加载速度,又保证了用户看到的首屏内容是直接输出的。
但是这个方案很快就被否定了,因为产品希望用户在浏览首页内容时,刷新页面后保持滚动条的位置不变,依然定位在上次浏览的位置。这就要求我们的首页的内容区域高度在每次刷新的时候都保持不变,要实现这个效果,有两种实现方案,第一个是一次性加载所有的内容,第二个是固定每个模块的高度;
第二个方案显然不行的,因为每个模块的高度都是随着数据变化的;所以我们就考虑采用第一种方案:在服务器上直接渲染所有的模块;
但是这种方案有个问题,就是生成的静态页面体积较大,会影响首屏的加载速度,因此我们在第一个方案的基础上又做了一些性能优化。
性能优化
1、减少加载不必要的元素节点。
例如首页的排行榜模块,除了第一行,每行只展示排名以及书籍名称,只有在鼠标悬浮上去的时候才会展示书籍的详细信息,因此在服务器上不会渲染首屏不展示的元素,以此来减少静态页面的体积。
类似的除了排行榜模块,还有人气作家、获奖作品这类的轮播模块,轮播模块也是同理,在服务器上只渲染首屏会展示的元素节点。
2、图片懒加载
首页的图片数量也是很多的,因此需要对图片进行懒加载:滚动到可视范围再加载;但同时为了用户体验友好,首屏可见的图片没有做懒加载,是直接渲染的。
此处还有一个体验上的优化,就是一开始的懒加载我们是针对图片元素进行处理的:图片滚动到可视范围内之后加载图片资源;我们忽视了轮播模块,因为轮播模块还存在横向的滚动;
就拿人气作家模块为例,当该模块滚动到页面可视范围内之后,当前可见的作者头像开始加载,但是当用户点击轮播箭头,查看下一页作者信息时,首先看到的是一张默认头像图,体验不友好;
因此针对这个问题,我们对于懒加载做了优化,除了可以作用于图片本身,也可以作用于图片所在的容器,当容器到达可视范围,就加载容器内的全部图片;
其他优化
最开始我们确定的4个接口下发数据的方式,在不分模块加载的情况下,依然保留了。在请求数据接口时,四个接口并发请求,这样处理的好处是接口响应出错的时候,会隐藏掉对应的展示模块,页面正常展示其他内容