HTML5 本地存储和内容按需加载的思路和方法

2019-10-24

HTML5自打出生就注定要开始它不平凡的一生,各大科技公司都对其寄予厚望,并纷纷进行尝试。苹果、谷歌、微软陆续推出HTML5展示页面,各大视频网站也相继宣布支持HTML5视频技术,HTML5地理定位技术更如雨后春笋,在国外社交网站得到应用。

另一方面,在移动设备平台,iPhone的出货量已经超过1亿部,而iPad的销量也超过了1500万台,iPad2也在首周销量了近100万台,销售额达到95亿,占整个平板市场份额的90%。我们知道,这俩不支持Flash,这个普及程度提醒我们,提高多平台的兼容性势在必行。

同时,在关注网站性能优化的同时,我们应该注意到减少用户加载页面时的加载量也是一个极其重要的方面。可以想象,一个日浏览量1000w次的网站,节省10K的下载量会有多好的效果,这对用户的访问速度和服务器的负载都有极大的好处。

 

> 官网优化情况

 

为了配合LOL不删档测试,并改善用户浏览时的体验,官网在今年1月份开始了改版。官网尝试采用全新的内容布局思路,对用户做更好的引导。本次改版,官网主要有以下四个方面的调整:大量去除上一版影响浏览的Flash动画,只保留首页下载按钮的Flash效果,加快了页面的加载速度;引导页对用户进行分流,获取游戏资讯的用户进入官网,了解游戏玩法攻略的进入战争学院;首页增强了游戏活动和赛事的展示,采用了不同以往的大型轮播广告和占据页面近三分之一空间的列表;增加了免费英雄展示和游戏荣誉墙的部分。

另外针对现状,官网通过采用HTML5本地存储,内容按需加载,延迟加载,文件压缩,CSS Sprites等技术,使页面性能得到了大幅度提升。另外采用HTML5视频技术,使官网在苹果移动平台上有很好的表现。

本文将着重介绍HTML5本地存储和内容按需加载的思路和方法,以及HTML5视频技术的效果。LOL官网采用的减少加载量的方法,在首页上为用户节省了至少600K的下载量,同时大大减轻了服务器的负载。

首页GTmetrix得分

整体健康度(其中首页1秒健康度70%以上,2秒健康度80%以上,3秒健康度90%以上)

 

> 减少页面加载量

 

减少页面加载量最主要的目的是减少资源消耗,加快页面的呈现速度。虽然延迟加载可以在一定程度上优化页面的性能,但不是所有的内容都需要第一时间加载给用户看或者重复加载的。比如用户在浏览页面第一屏的内容,那么页面在打开时就加载第一屏以下的一些内容就不是很有必要。再或者,官网页面中一些相同的部分,如导航、脚部声明等部分,这些修改率极低的内容每次都从服务器请求,在一定程度上增加了页面加载的负荷。

减少页面加载量的方法有很多,这次LOL官网改版主要用到了以下方法:

采用HTML5本地存储技术,在用户电脑里存储页面的一些内容,如导航,合作媒体,脚部声明等。这样用户在加载页面时,浏览器直接从本地获取这些内容,在一定程度上减少了资源的消耗。

图片随滚动条滚动加载,使用户在浏览页面时,动态按需加载图片。比如,用户在浏览第一屏内容时,第一屏以后的图片是没有加载的,当用户滚动页面时,呈现在浏览器中的部分会动态加载图片。

优化轮播广告的加载方式,页面打开时只加载第一张图片,在轮播到第二张图片时,才请求加载第二张图片,以此类推。

按需加载页卡的内容,官网首页右上角的新闻板块,加载时只请求第一个页卡的内容,当用户点击其他页卡时,再加载页卡的内容。

 

> HTML5本地存储

简单的说,本地存储就是为网页通过客户端网页浏览器在本地存储键值对的一个方法。就像Cookie,就算你离开了网站,关闭了浏览器标签,退出浏览器等等,数据也会一直存在。与Cookie不同的是,数据绝不会向遥远的网络服务器传送(除非你使用其他方法来手动传输)。不同于提供长期本地存储的上述所有尝试,它在网页浏览器内以原生的方式执行,因此在第三方浏览器插件失效的情况下它也能有效执行。

我们对于支持HTML5的浏览器(Firefox、Chrome、Safari、Opera等),使用HTML5的localStorage提供的方法;对于IE浏览器,使用IE提供的userData方法;对于其他浏览器使用常规方法加载内容。

IE的本地存储数据

userData是IE提供的一个本地存储方法,他将需要存储的内容放置在本地的一个XML文件中,并在页面的一个元素中设置一个调用的锚点。具体使用方法为:使用getElementById获取页面内的一个元素,使用addBehavior(“#default#userData”)对其添加本地存储的行为;使用setAttribute将需要存储的内容对其进行赋值,并用save(“XXX”)方法将内容存储在名为XXX的XML文件中;使用load(“XXX”)方法加载本地的XXX.xml文件,并用getAttribute获取已经存储的内容。

Chrome的本地存储数据

关于HTML5本地存储localStorage的详细方法,请参见HTML5 Web存储。我的一个翻译文档《网络应用程序本地存储的前世今生》也会稍后在博客放出。

 

对于具体实现上,我的做法是:先判断本地是否存在已存储的内容,如果没有数据或者版本已过期(版本其实是我设置的一个变量,当修改这个变量时即为版本过期),加载相应的JS数据,通过一个函数将数据处理为需要的格式,然后存储在本地;如果有且版本没过期,直接从本地获取数据。接着将数据通过函数进行进一步的处理,插入相对应的结构中。

官网中,导航、合作媒体、健康游戏公告、脚部声明、免费英雄均采用本地存储,将数据存储在用户的电脑中。

其中导航、荣誉墙、合作媒体、健康游戏公告、脚部声明这5个静态板块的本地存储应用一共节省了10多K(IE的本地存储文件实际有30K,是因为IE对内容中的字符进行了转义,以符合XML的规则)的下载量。

免费英雄板块属于动态板块,里面的数据是通过游戏提供的一个json文件来获取的(包含游戏里所有英雄的数据,每周的免费英雄都会不同),将其本地存储后,节省了500K的下载量。只是在每周一免费英雄修改时,会重新下载一次。

 

> 图片随页面滚动加载

其实这是很多大型网站都使用了的方法,比如淘宝、拍拍等等。这次在游戏官网里做一个尝试,效果不错,初期为首页节省了几十K的下载量,因为不同显示器分辨率不同,所以第一屏高度不一样,这个数据有所浮动。

滚动时,当前屏正在加载的图片

首先,将图片的路径存储在img标签的一个非src属性中,LOL首页是存储在rel属性中的,此举是避免页面直接加载图片。然后使用JS的监听方法(IE是attachEvent,其他浏览器是addEventListener),监听页面的scroll事件。一旦页面滚动,就会执行一个编写的函数,来判断图片是否处于浏览器的当前一屏内,如果是,将rel属性内的地址赋值给src属性,如果不是,继续监听。当板块内的所有图片都被加载后,取消监听。LOL官网首页的活动板块和媒体合作板块均使用了这种技术,大大减少了页面的加载量。

> 轮播广告按需加载

以往轮播广告的加载模式是一次性全部加载,虽然采用延迟加载,但用户可能不会浏览到所有的轮播广告。当用户在首页只停留5秒时(LOL官网首页轮播广告设置的是5秒切换一次),第二张广告图片以后的图片加载就没有必要了。

LOL官网首页采用的方式是,第一次加载第一张广告图片,当5秒后,判断第二张图片是否加载过,如果没有,加载第二张图片,以此类推。这样,如果用户在首页停留时长只有14秒,那么就节省了第4、5张广告图片的下载量,大约有100K左右。

 

> 页卡内容按需加载

对于新闻页卡,以往的方式是使用include载入,并将看不到的页卡隐藏掉。但如果用户并没有切换到其他页卡,那么直接加载这些页卡的内容就是不必要的。

触发加载页卡内容

LOL官网首页页卡采用的方式是,只加载第一个可见页卡的内容。当用户点击切换页卡时,再加载对应页卡的内容。包括导航和荣誉墙这两个部分,虽然是从本地加载数据,但也是用户触发后才插入到相应结构的。这样不仅减少了一定的下载量,也减少了一部分浏览器的渲染工作。

 

> 多平台兼容

 

平台兼容问题其实说到底,还是浏览器的兼容问题。在PC平台,我们要兼容N多浏览器,在移动平台同样如此。更恐怖的是,移动平台的浏览器种类和复杂度远远大于PC平台。
所以LOL官网的多平台兼容也只针对移动平台中的现代浏览器。

 

> 苹果平台

iPad下的引导页

对于iPad和iPhone,主要问题是其不支持Flash。LOL官网有两处,一是引导页的视频,二是首页的下载按钮。实现起来很简单,使用JS判断浏览器信息(navigator.userAgent),如果是iPad和iPhone,使用HTML5视频技术替换引导页的Flash播放器,屏蔽首页的Flash下载按钮的插入,保持其为一个a标签的链接。具体方法请参见我在御龙在天官网改版时的文档《御龙在天的iPad之路》。

 

> 谷歌平台

对于Android系统的手机和平板电脑,并不需要做任何多余的事情,只要你的页面符合标准,因为Android手机本身就支持Flash,经过我的测试,LOL官网在HTC Desire下的浏览完全正常。

 

> 一些小技巧

 

> 更快的数据解析方式

我们通常使用json或者XML的方式来存储大量数据。《高性能Javascript》一书中介绍了一种自定义格式,并测试出自定义格式是解析最快的。其方法是使用符号来间隔数据,比如var test=”1,2,3,4”,然后使用split(“,”)来方法来获取各个数据。LOL官网就是用这种方式在本地存储的数据。

 

> CSS Sprites

为了减少请求,LOL官网将每个页面的小图片都整合到其各自的一张大图片中,首页更是BT,整合图片有90K。

首页的整合图片

 

> MP4文件大小控制

针对苹果移动平台设备输出的MP4文件需要控制大小,文件太大会造成浏览时很卡的感觉。毕竟移动平台设备的CPU还是不能和PC相比的。LOL引导页的MP4文件就从最开始的10M压缩到了6M。

 

> 函数执行

LOL官网使用了大量的JS,尤其是首页。如果一次性执行大量函数,会造成CPU暂用率很高,页面很卡的情况。因此,LOL官网使用了一个函数来间隔执行这些函数。在页面加载完成时,先一次性执行必须马上使用的几个函数,然后以100毫秒为间隔,根据重要程度挨个执行剩下的函数,以减轻CPU的负载。经过对比,采用这种方式后,LOL官网首页虽然JS使用比DNF官网首页多很多,但加载时的CPU占用率比DNF还低5%左右。

 

> CSS选择符

我们在编写CSS时,会有很多的选择符,但不同的写法,页面在渲染时的效率是不一样的。根据匹配规则,浏览器会从右至左匹配对应的元素。比如.header li a{},在渲染时,浏览器会先遍历页面内所有的a标签,再遍历这些a标签谁在li标签内,然后再去找他们谁在.header下,这样效率其实很低,而且开销很大。其实我们可以对这些a标签直接写个类名.header_lnk{},这样浏览器渲染时一下子就可以找到,避免再去翻箱倒柜。另外.header .header_lnk{}也是没有必要的,直接写.header_lnk{}效率更高,我们为什么还要浏览器多过滤一次呢?

 

> 结束语

 

当然,减少HTTP请求,使用延迟加载等等这些方法也是必不可少的,具体请参见《DNF官网整容手册》。官网的优化永无止尽,其实这次改版后的页面还有很多地方可以优化。比如减少页面的初期渲染量,优化JS以进一步减小CPU占用率,兼容更多的移动平台等等。希望此文档能在今后各个产品的官网改版上帮助到各位同学。

《HTML5 本地存储和内容按需加载的思路和方法.doc》

下载本文的Word格式文档,以方便收藏与打印。