缓存方案

什么是Web缓存

Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,若是是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,仍是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,若是网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。至于浏览器和网站服务器是如何标识网站页面是否更新的机制,将在后面介绍。javascript

 

Web缓存的做用

使用Web缓存的做用实际上是很是显而易见的:php

减小网络带宽消耗

不管对于网站运营者或者用户,带宽都表明着金钱,过多的带宽消耗,只会便宜了网络运营商。当Web缓存副本被使用时,只会产生极小的网络流量,能够有效的下降运营成本。css

下降服务器压力

给网络资源设定有效期以后,用户能够重复使用本地的缓存,减小对源服务器的请求,间接下降服务器的压力。同时,搜索引擎的爬虫机器人也能根据过时机制下降爬取的频率,也能有效下降服务器的压力。html

减小网络延迟,加快页面打开速度

带宽对于我的网站运营者来讲是十分重要,而对于大型的互联网公司来讲,可能有时由于钱多而真的不在意。那Web缓存还有做用吗?答案是确定的,对于最终用户,缓存的使用可以明显加快页面打开速度,达到更好的体验。前端

 

Web缓存的类型

在Web应用领域,Web缓存大体能够分为如下几种类型:html5

数据库数据缓存

Web应用,特别是SNS类型的应用,每每关系比较复杂,数据库表繁多,若是频繁进行数据库查询,很容易致使数据库不堪重荷。为了提供查询的性能,会将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提供响应效率。好比经常使用的缓存方案有memcached等。  java

服务器端缓存

 代理服务器缓存mysql

代理服务器是浏览器和源服务器之间的中间服务器,浏览器先向这个中间服务器发起Web请求,通过处理后(好比权限验证,缓存匹配等),再将请求转发到源服务器。代理服务器缓存的运做原理跟浏览器的运做原理差很少,只是规模更大。能够把它理解为一个共享缓存,不仅为一个用户服务,通常为大量用户提供服务,所以在减小相应时间和带宽使用方面颇有效,同一个副本会被重用屡次。常见代理服务器缓存解决方案有Squid等,这里再也不详述。ios

 CDN缓存c++

CDN(Content delivery networks)缓存,也叫网关缓存、反向代理缓存。CDN缓存通常是由网站管理员本身部署,为了让他们的网站更容易扩展并得到更好的性能。浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。虽然这种架构负载均衡源服务器之间的缓存无法共享,但却拥有更好的处扩展性。从浏览器角度来看,整个CDN就是一个源服务器,从这个层面来讲,本文讨论浏览器和服务器之间的缓存机制,在这种架构下一样适用。

 

浏览器端缓存

浏览器缓存根据一套与服务器约定的规则进行工做,在同一个会话过程当中会检查一次并肯定缓存的副本足够新。若是你浏览过程当中,好比前进或后退,访问到同一个图片,这些图片能够从浏览器缓存中调出而即时显现。

 

Web应用层缓存

应用层缓存指的是从代码层面上,经过代码逻辑和缓存策略,实现对数据,页面,图片等资源的缓存,能够根据实际状况选择将数据存在文件系统或者内存中,减小数据库查询或者读写瓶颈,提升响应效率。

 

 

 

 

Web浏览器的缓存机制 

 

Web缓存的工做原理

 

全部的缓存都是基于一套规则来帮助他们决定何时使用缓存中的副本提供服务(假设有副本可用的状况下,未被销毁回收或者未被删除修改)。这些规则有的在协议中有定义(如HTTP协议1.0和1.1),有的则是由缓存的管理员设置(如DBA、浏览器的用户、代理服务器管理员或者应用开发者)。

浏览器端的缓存规则

对于浏览器端的缓存来说,这些规则是在HTTP协议头和HTML页面的Meta标签中定义的。他们分别从新鲜度校验值两个维度来规定浏览器是否能够直接使用缓存中的副本,仍是须要去源服务器获取更新的版本。

新鲜度(过时机制):也就是缓存副本有效期。一个缓存副本必须知足如下条件,浏览器会认为它是有效的,足够新的:

  1. 含有完整的过时时间控制头信息(HTTP协议报头),而且仍在有效期内;
  2. 浏览器已经使用过这个缓存副本,而且在一个会话中已经检查过新鲜度;

知足以上两个状况的一种,浏览器会直接从缓存中获取副本并渲染。

校验值(验证机制):服务器返回资源的时候有时在控制头信息带上这个资源的实体标签Etag(Entity Tag),它能够用来做为浏览器再次请求过程的校验标识。如过发现校验标识不匹配,说明资源已经被修改或过时,浏览器需求从新获取资源内容。

浏览器缓存的控制

使用HTML Meta 标签

Web开发者能够在HTML页面的<head>节点中加入<meta>标签,代码以下:

1

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

上述代码的做用是告诉浏览器当前页面不被缓存,每次访问都须要去服务器拉取。使用上很简单,但只有部分浏览器能够支持,并且全部缓存代理服务器都不支持,由于代理不解析HTML内容自己。

能够经过这个页面测试你的浏览器是否支持:Pragma No-Cache Test 。

使用缓存有关的HTTP消息报头

一个URI的完整HTTP协议交互过程是由HTTP请求和HTTP响应组成的。有关HTTP详细内容可参考《Hypertext Transfer Protocol — HTTP/1.1》、《HTTP协议详解》等。

在HTTP请求和响应的消息报头中,常见的与缓存有关的消息报头有:

HTTP缓存相关报头

 

Cache-Control与Expires

Cache-Control与Expires的做用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据仍是从新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,若是同时设置的话,其优先级高于Expires

Last-Modified/ETag与Cache-Control/Expires

配置Last-Modified/ETag的状况下,浏览器再次访问统一URI的资源,仍是会发送请求到服务器询问文件是否已经修改,若是没有,服务器会只发送一个304回给浏览器,告诉浏览器直接从本身本地的缓存取数据;若是修改过那就整个数据从新发给浏览器;

Cache-Control/Expires则不一样,若是检测到本地的缓存仍是有效的时间范围内,浏览器直接使用本地副本,不会发送任何请求。二者一块儿使用时,Cache-Control/Expires的优先级要高于Last-Modified/ETag。即当本地副本根据Cache-Control/Expires发现还在有效期内时,则不会再次发送请求去服务器询问修改时间(Last-Modified)或实体标识(Etag)了。

通常状况下,使用Cache-Control/Expires会配合Last-Modified/ETag一块儿使用,由于即便服务器设置缓存时间, 当用户点击“刷新”按钮时,浏览器会忽略缓存继续向服务器发送请求,这时Last-Modified/ETag将可以很好利用304,从而减小响应开销。

Last-Modified与ETag

你可能会以为使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为何还须要Etag(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  1. Last-Modified标注的最后修改只能精确到秒级,若是某些文件在1秒钟之内,被修改屡次的话,它将不能准确标注文件的新鲜度
  2. 若是某些文件会被按期生成,当有时内容并无任何变化,但Last-Modified却改变了,致使文件无法使用缓存
  3. 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的惟一标识符,可以更加准确的控制缓存。Last-Modified与ETag是能够一块儿使用的,服务器会优先验证ETag,一致的状况下,才会继续比对Last-Modified,最后才决定是否返回304。Etag的服务器生成规则和强弱Etag的相关内容能够参考,《互动百科-Etag》和《HTTP Header definition》,这里再也不深刻。

用户操做行为与缓存

用户在使用浏览器的时候,会有各类操做,好比输入地址后回车,按F5刷新等,这些行为会对缓存有什么影响呢?

用户操做与缓存

经过上表咱们能够看到,当用户在按F5进行刷新的时候,会忽略Expires/Cache-Control的设置,会再次发送请求去服务器请求,而Last-Modified/Etag仍是有效的,服务器会根据状况判断返回304仍是200;而当用户使用Ctrl+F5进行强制刷新的时候,只是全部的缓存机制都将失效,从新从服务器拉去资源。

相关有趣的分享:

浏览器缓存机制》:不一样浏览器对用户操做行为处理比较

HTTP 304客户端缓存优化的神奇做用和用法》:强行在代码层面比对文件的Last-Modified时间,保证用户使用Ctrl+F5进行刷新的时候也能正常返回304

 

哪些请求不能被缓存?

没法被浏览器缓存的请求:

  1. HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0等告诉浏览器不用缓存的请求
  2. 须要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的
  3. 通过HTTPS安全加密的请求(有人也通过测试发现,ie其实在头部加入Cache-Control:max-age信息,firefox在头部加入Cache-Control:Public以后,可以对HTTPS的资源进行缓存,参考《HTTPS的七个误解》)
  4. POST请求没法被缓存
  5. HTTP响应头中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的请求没法被缓存

 

 

 

如何构建可缓存站点

 

前面了解了Web缓存的运行机制极其重要性以后,咱们能够从如下这些方面去努力改善咱们的站点,保证缓存被最有效的利用,达到最佳的性能。

同一个资源保证URL的稳定性

URL是浏览器缓存机制的基础,因此若是一个资源须要在多个地方被引用,尽可能保证URL是固定的。同时,比较推荐使用公共类库,好比Google Ajax Library等,有利于最大限度使用缓存

给Css、js、图片等资源增长HTTP缓存头,并强制入口Html不被缓存

对于不常常修改的静态资源,好比Css,js,图片等,能够设置一个较长的过时的时间,或者至少加上Last-Modified/Etag,而对于html页面这种入口文件,不建议设置缓存。这样既能保证在静态资源不变了状况下,能够不重发请求或直接经过304避免重复下载,又能保证在资源有更新的,只要经过给资源增长时间戳或者更换路径,就能让用户访问最新的资源

减小对Cookie的依赖

过多的使用Cookie会大大增长HTTP请求的负担,每次GET或POST请求,都会把Cookie都带上,增长网络传输流量,致使增加交互时间;同时Cache是很难被缓存的,应该尽可能少使用,或者这在动态页面上使用。

减小对HTTPS加密协议的使用

经过HTTPS请求的资源,默认是不会被缓存的,必须经过特殊的配置,才能让资源获得缓存。建议只对涉及敏感信息的请求使用HTTPS传输,其余相似Css,Js,图片这些静态资源,尽可能避免使用。

多用Get方式请求动态Cgi

虽然POST的请求方式比Get更安全,能够避免相似密码这种敏感信息在网络传输,被代理或其余人截获,可是Get请求方式更快,效率更高,并且能被缓存,建议对于那些不涉及敏感信息提交的请求尽可能使用Get方式请求

动态CGI也是能够被缓存

若是动态脚本或CGI输入的内容在必定的时间范围内是固定的,或者根据GET参数相同,输入的内容相同,咱们也认为请求是能够被缓存的,有如下几种方式,能够达到这个效果:

  1. 让动态脚本按期将内容改变时导出成静态文件,Web直接访问带有Last-Modified/Etag的静态文件
  2. 开发者能够经过代码给动态脚本的响应头中添加Cache-Control: max-age,告诉浏览器在过时前能够直接使用副本
  3. 经过代码给动态脚本的响应头添加Last-Modified/Etag信息,浏览器再次请求的时候,能够经过解析If-Modified-Since/If-None-Match得知浏览器是否存在缓存,由代码逻辑控制是否返回304

 

如何给站点增长缓存机制

HTTP请求/响应头中缓存报头对有效利用站点缓存,做为一个Web前端开发者,我要作什么呢?答案是:啥都不用作。不过要去推进Web运营人员、Web后端开发人员分别给服务器和动态脚本CGI增长合适的缓存报头。

服务器配置

Apache相关配置参考:mod_headersmod_headers

编写可缓存的动态脚本

服务器配置的方法比较简单通用,可是若是遇到没有权限修改服务器配置或者须要添加更细致的Expires/Cache-Control/Etag等信息时,不妨能够试试从代码层面去添加这些信息。不一样语言写法实现略有不一样,但思路都是一致的。能够在单独开辟一个独立模块,调用语言库提供的添加报头的接口,根据须要设置报头信息。当某个请求的动态脚本须要被缓存时,能够采用相似include,require等模块引用方式调用公共模块,实现缓存机制。

Php实现代码实例以下:

Cache.php

<?php
Header(“Cache-Control: must-revalidate”);

$offset = 60 * 60 * 24 * 3;
$ExpStr = “Expires: ” . gmdate(“D, d M Y H:i:s”, time() + $offset) . ” GMT”;
Header($ExpStr);
?>

<?php

Require(Cache.php)

// business code here

// todo

?>

 

 

 

HTML5时代的Web缓存机制

 

随着现代浏览器的推进,Flash放弃对移动端的支持,HTML5无疑成为当前Web前端煊赫一时的话题。各大游戏开发商、App开发商纷纷投入人力进行研究和技术储备。相信不久的未来,HTML5会迎来一个快速发展和普及的春天。那么,HTML5这个新一代的标准,又给咱们带来哪些缓存机制呢?

 

 

 HTML5 之离线应用Manifest

咱们知道,使用传统的技术,就算是对站点的资源都实施了比较好的缓存策略,可是在断网的状况下,是没法访问的,由于入口的HTML页面咱们通常运维的考虑,不会对其进行缓存。HTML5的Cache Manifest离线应用特性就可以帮助咱们构建离线也能使用的站点,全部的资源都使用浏览器本地缓存,固然前提是要求在联网的情形下使用过一次站点。

如何实现离线访问特性

实现的步骤很是简单,主要3个步骤:

1)在服务器上添加MIME TYPE支,让服务器可以识别manifest后缀的文件

AddType text/cache-manifest manifest

2)建立一个后缀名为.manifest的文件,把须要缓存的文件按格式写在里面,并用注释行标注版本

CACHE MANIFEST

# 直接缓存的文件

CACHE:

Path/to/cache.js

# version:2012-03-20

3)给 <html> 标签加 manifest 属性,并引用manifest文件

具体能够参考:HTML5 缓存: cache manifest

<html manifest=”path/to/name-of.manifest”>

离线应用访问及更新流程

  1. 第一次访问离线应用的入口页HTML(引用了manifest文件),正常发送请求,获取manifest文件并在本地缓存,陆续拉取manifest中的须要缓存的文件
  2. 再次访问时,没法在线离线与否,都会直接从缓存中获取入口页HTML和其余缓存的文件进行展现。若是此时在线,浏览器会发送请求到服务器请求manifest文件,并与第一次访问的副本进行比对,若是发现版本不一致,会陆续发送请求从新拉取入口文件HTML和须要缓存的文件并更新本地缓存副本
  3. 以后的访问重复第2步的行为

离线机制的缓存用途

从Manifest的机制来看,即便咱们不是为了建立离线应用,也一样可使用这种机制用于缓存文件,能够说是给Web缓存提供多一种能够选择的途径。

存在的问题:缓存文件更新控制不灵活

就目前HTML5提供的manifest机制来说,一个页面只能引用一个manifest页面,并且一旦发现这个manifest改变了,就会把里面全部定义的缓存文件所有从新拉取一遍,无论实际上有没有更新,控制比较不灵活。针对这个问题,也有的同窗提出了一些建议,好比把须要缓存的文件分模块切分到不一样manifest中,并分开用HTML引用,再使用强大的iframe嵌入到入口页面,这样就当某一个模式须要有更新,不会致使其余模块的文件也从新拉取一遍。

 

HTML5 之本地存储localstorage

HTML5给咱们提供本地存储localstorage特性,严格来说,其实已经不算传统Web缓存的范畴。由于它存储的地方是跟Web缓存分开的,是浏览器从新开辟的一个地方。

localstorage的做用

本地存储localstorage的做用主要使Web页面可以经过浏览器提供的set/get接口,存储一些自定义的信息到本地硬盘,而且在单次访问或之后的访问过程当中随时获取或修改。

Localstorage的使用

Localstorage提供了几个很是易用的Api,setItem/getItem/removeItem/clear,具体的能够参考:Html5 Step by Step(二) 本地存储

Localstorage的缓存用途

Localstorage设计的本意多是用来存储一些用户操做的个性化设置的文本类型的信息和数据,当咱们其实也可能拿来当Web缓存区使用,好比咱们能够将Base64格式编码的图片信息,存在localstorage中,再次访问时,直接本地获取后,使用Css3的Data:image的方式直接展示出来。

存在的问题:大小限制

按照目前标准,目前浏览器只给每一个独立的域名提供5m的存储空间,当存储超过5m,浏览器就会弹出警告框。

 

能够说,HTML5的Manifest和localstorage是给咱们在考虑Web缓存的时候提供了多一种思路,当你开发的应用只面对现代浏览器的时候,不妨能够考虑一下。

 

 

Web App时代的缓存机制新思路

 

Web App的概念逐渐被业界承认,各大互联网公司也纷纷推出Web App开发大赛,积极引入到他们的开放平台,比较著名相似facebook农场,qzone偷菜之类的。Web开发逐渐从Web Page的进入到Web App的时代,想详细了解的话,能够看下超叔在D2上分享的分享《开放时代:从Web Page到Web APP》视频Slide

Web App常见架构

以WebQQ例,WebQQ这个站点的全部内容都是一个页面里面呈现的,咱们看到的相似windows操做系统的框架,是它的顶级容器和框架,由AlloyOS的内核负责统筹和管理,而后其余模块,好比壁纸设置,消息中心,App Store都是以模块的形式,并用iframe的方式嵌入到顶级容器中。具观察,如今愈来愈多的Web应用都倾向于使用这个的架构,这样作好处是很明显的,好比顶级框架能够维持一个不变的javascript上下文便于管理;关闭模块的iframe后,内存能够更好的释放;利用iframe的安全机制最大限度的保证内核的安全和稳定等等。

这种Web的架构,其实也给咱们Web前端提供了从代码逻辑层面上给Web应用实现缓存提供了可能。

 

缓存Ajax请求

因为顶级框架页面是不会因为调整刷新而致使javascript上下文丢失,因此底层或各个模块所须要的Ajax请求,都是能够经过顶级框架统一请求后,并以信息服务的形式对外提供Api调用。对于一些实时性要求不是很强的请求来讲,能够由顶级框架作统一缓存,按期更新。这种作法能够不影响用户体验的前提下,明显减小请求数,下降网络流量,并间接减轻了服务器的压力。

经过Javascript实现内存缓存

跟缓存Ajax请求的结果相似,程序运行过程当中的其余数据,其实也能够采用相似的方式在顶级容器的Javascript上下文中缓存。

 

Web App发展新方向:Web-Client模式

随着Web App的进一步发展,貌似浏览器已经没法阻挡Web应用探索更前端,更本地化Native App的用户体验。好比目前的Qplus豆瓣荚等应用,都采用Client、Web相结合的开发模式。这样作便可以利用Web开发迭代更新快、UI开发成本低等特色,有能够利用客户端的能力为Web实现不少没法实现的功能。以Qplus为例,Qplus不但内嵌了Webkit内核,还未Webkit上定制了不少便利的接口,好比跨Web-Client的拖曳、多线程下载等。在这种发展新模式下,Web缓存又能有什么考虑的发张方向呢?

客户端提供缓存读写能力

咱们知道,HTML5的localstorage仅仅只能支持5m的存储。咱们能够按localstorage的设计思路,让客户端为Web定制更大,更灵活的本地存储功能。到时,Web缓存能作的事情就会更多。

 

以上就当前Web App的发展趋势,讨论了对于Web缓存领域,有哪些能够作,能够考虑的方向。固然,这些作法,合不合理,合不合适都仍是值得讨论和商榷的,若是你有想法,均可以随时联系并一块儿讨论。

 

全文总结

本文尝试概述目前Web缓存方向的现状,以及HTML5和Web App时代下,Web缓存能够考虑的新方向。因为时间仓促和表达归纳能力有限,有可能有表达不妥的地方,欢迎指正讨论。

 

 

 

进击的Hybrid App,量身定作缓存机制

 

 

前言

 

前面的文章分别简述了Web缓存、相关机制、以及 html5 和 Web App 时代咱们能够选择的缓存思路。转眼过了很长时间,这期间移动互联网成为你们讨论和学习的焦点,部门也有不少同窗陆续接触 Mobile Native App 和 Mobile Web App 的开发。同时,还有部分同窗专一 QQ 内嵌 Webkit + Client 这种Hybrid App模式的开发,继续推进 QQ 客户端 Web 化的进程。

引用张图,简单粗俗的解释下 Native App、Web App 和 Hybrid App

hybrid-app

Navtie App: 使用平台系统提供的原生语言来编写的 App,若是Android用java,ios用objective-c,windows c++等

Web App:主要使用 Web 技术js/html/css进行编写,运行在各平台系统浏览器或浏览器组件中

Hybrid App:混合使用前面两种技术,部分代码以 Web 技术编写,部分代码由某些 Native Container 承担(如 Phongap 插件,PC/手机 QQ客户端等)

 

现有的缓存机制及问题

移动互联网网速慢、QQ 客户端对 Web 模块可用性要求高,使得咱们无论作 Mobile Web App 开发、仍是 PC Web App 开发,都必须对 Web 缓存有更深刻的理解和利用。PC QQ 和 手机 QQ 都有基本 Webkit 的 Webview,除了传统常规提到的缓存外,参阅《Web浏览器的缓存机制 》,咱们最早想到的优化方案就是前面文章提到的 Html5 App Cache,Web Storage,详细请参阅《HTML5时代的Web缓存机制》 和《Web App时代的缓存机制新思路》。

但,使用的过程当中,咱们发现了一些关于 html5 app cache 的问题:

一、第一次必须联网,在移动网络下首次打开效果很是不理想

二、http 头设置会致使 manifest 没法正常更新,见 http://www.alloyteam.com/2012/01/html5-offline-app-update-problem/

三、Manifest 中缓存文件一旦下载出错,后续的文件将再也不下载,抛出错误事件,见:http://stackoverflow.com/questions/6666513/html5-manifest-caching-error

四、Android 系统版本众多,较低版本的浏览器对 manifest 支持不完善

五、引用 manifest 的 html 页面自己也会被缓存

六、《慎用manifest》一文提到的如:页面的参数传递、manifest 的发布、回滚、下线等问题

从上面能够看出,html5 虽然提供基于 manifest 这种离线缓存的机制,但在实际运用过程当中仍是会遇到很是多的问题,因而,咱们开始思考,既然是 hybrid app,与其花大量时间踩坑,有资源有条件,不如更激进一点,尝试利用客户端能力来量身定作一套本身适用的缓存机制。因而 Alloykit 诞生了。

 

关于 Alloykit

Alloykit 是 PC/手机 QQ 上基于 Webview 开发的一个方便易用的开发组件,可以使基于 Webkit 开发的模块,快速拥有 Web 资源本地化、Common Api、自动种入登陆态和续期、诊断上报、DNS管理、开发者工具支持、关键性能数据上报等特性。

Alloykit 各模块及主要功能:

本地化模块:把静态资源下载到本地,而后经过访问本地资源代替去服务器请求

Common Api模块:对经常使用共性的 Client 接口进行封装,Web能够内嵌 Commonapi.js 进行方便调用

登陆态管理模块:web 登陆态自动续期,登陆态拉取失败走 Pt 跳转

诊断上报模块:诊断修复用户问题(清缓存,DNS,从新加载页面),截屏并收集用户本机网络信息,上报到后台进行分析。

DNS管理模块:域名预加载,域名 ip 验证等

开发模式:开发模式开关,开发者调试工具支持

数据上报:通用控件在不一样业务中的关键上报点

下面主要介绍一下本地化缓存模块的设计思路,后面有机会再单独介绍其它的模块。

 

本地化模块

用一张图大体示意以下:

cache2

由上图能够看出,本地化模块主要由下面两个子模块组成:

一、拦截器:采用的一种相似 Fiddler AutoResponse 的本地替换思路,经过拦截全部 web 请求,进行本地化资源匹配,命中则用本地资源直接替换,不然,正常发起请求。

二、更新器:根据更新策略进行新版本资源检测,负责下载和维护本地缓存目录中的资源,并将更新过程关键点经过事件通知到 Web 页面备用。

原理很简单,使用也很简单,主要分为如下几个步骤:

一、客户端开发阶段:新建窗口的时候,只须要经过配置文件,将窗口类型声明为 AlloykitWindow

二、前端开发阶段:开发过程透明,不须要任何特殊处理

三、前端发布阶段:打包静态资源 zip 包

把业务涉及到而且但愿离线的域名和资源打包,假设你的页面用到了web.qq.com、cdn.qq.com、test.statics.qq.com等域名,以下图所示,为每一个域名建一个目录(若只有一个域名,则只创建一个目录),而后按照资源的url创建各级子目录并把资源放到相应的子目录下。

好比你有这样一个html页面:http://web.qq.com/module1/helloworld.html

把须要离线的页面文件和图片资源放到目录web.qq.com/module1下便可,如图:

pack-zip

使用 zip 压缩软件,将全部资源打包为一个 zip 包。

四、运维发布阶段:

  • 正常发布线上资源
  • 登陆资源包管理平台,提交对应 zip 包
  • 须要打包到客户端安装包的资源,单独提交给客户端开发负责打包

 

Alloykit 本地化 和 H5 manifest 对比

一、Alloykit 能够选择将关键页面直接打包到客户端或App安装包,首次打开不须要依赖网络条件

二、对于没有打包到安装包的页面,也能够经过配置,让客户端启动后提早加载资源包

三、Alloykit 开发过程体验更简单,基本透明

四、Alloykit 把全部资源打包为一个 zip 包进行下载,更高效

五、Alloykit 经过客户端提供的基于 tcp 的下载通道进行下载,并有重试机制,更加稳定可靠

六、Alloykit 能够经过自身封装,支持多平台,避免开发者兼容多平台带来的麻烦

七、Alloykit 能够经过协议的设计,轻松实现刷新缓存、封版、下线离线特性等功能

这个本地化机制目前已有模块开始试用,在享受量身定制的缓存机制带来的性能提高和开发便利的同时,咱们开始遇到并思考本地化以后的一些问题。

 

本地化以后

一、本地化文件的安全问题

缓存目录中本地文件,第三方是有办法找到并进行强制修改,可能存在不安全的因素。有同窗可能会说这个担忧其实画蛇添足,好比 Chrome Cache 文件写入磁盘的算法是开源的,若是第三方(相似 ChromeCacheView)软件实现了这个算法,就能对缓存文件进行修改,也存在相似安全问题。话虽如此,但是仍是要作最坏的打算,说不定哪天数字搞你一下。要设计一种机制作保障。这种提供两种思路:

1)设计一种相似 Chrome Cache 闭源算法,把获取的资源包以这种算法读写入本地磁盘上。

2)使用非对称加密算法

客户端开发的时候,内嵌私钥

资源包 zip 中加入一个包含全部文件 md5 信息的json文件,并使用对应的公钥进行加密

客户端获取 zip 包后,使用私钥对 json 文件解密,获取 md5 信息,逐个进行校验

 

二、Web 项目运营思路转变

Web 项目一旦使用了本地化特性,无论是 H5 的 manifest 仍是 Alloykit ,都会存在滞后一次更新,因此始终都会存在旧版本的长尾问题。因此这类型的项目给运营提出了更高的要求:

1)后台 CGI 接口,尽可能考虑向前兼容,保证协议结构不变,若是确实须要改动,建议启用新路径

2)前端资源文件,建议采用增量的形式发布,好比 main.js ,发布的时候建议编译成 main-****.js(通常使用时间戳或md5后8位)

这样作的好处很明显,能够最大限度避免发布引发的波动,同时也能够支持 web 项目多版本并存,避免多版本相互影响。使用 grunt 或 modjs 能够轻松完成这个自动化构建编译工做。

3)Web 版本的铺量速度有所降低,因此对版本质量的要求更高,不建议太频繁、未经严格测试的版本发布

可见是否使用本地化,也须要作慎重的考虑,在性能和各个方面作权衡。

 

三、本地化以后的可用性问题

Alloykit 本地化以后,理论上在断网的状况下,页面也是打开的。可是要保证页面可用,其实还有很长的路要走。

针对那种单机的 h5 游戏或者简单页面,其实无需任何处理就能保证离线的访问效果。但,目前彻底单机的 Web App 基本是不存在,大量的动态的数据和社会化的交互。若是本地化以后不作任何处理,那么在离线的状况下,基本也是只有页面框架,大量的页面空白和 ajax 请求超时,基本也至关于不可用。那么,花了这么大力气定制的本地化机制就仅仅保证打开的时候可看不可用吗?有什么办法能够改善吗?

答案是有的,这时 Web Storage 和 Web Database 就能够派上用场了,详细使用能够 Google 或者参考索引中的第四、5篇文章。

一些典型的离线场景及处理方案:

1)离线写操做:将 Ajax 请求以及相关参数保存到 localStorage 队列中,网络上线后,触发执行队列中的操做

2)离线读操做:页面上有须要经过 Ajax 获取动态的数据或远程图片进行渲染的块,能够经过前端 hardcode 一些默认数据,而且将最近一次 ajax 结果存储到 localStorage 中,图片能够转为 base64 字符串才用一样的方式处理

localStorage 有同源限制,大小也有限制,而且只能存储字符串,须要存储图片须要进行转化,比较繁琐耗性能。能否跟激进一些,由客户端提供模拟 localStorage,自行开辟存储空间,提供接口进行存取和校验?彻底是可行的,而且如今在一些 Mobile 的项目中进行了相关尝试,接口整合到 CommonApi 模块中。

 

总结

独立于标准以外重复制造轮子,自己不是太推荐的作法。在目前标准和平台支持未完善,以及在特定场景下有欠缺的情形下,资源容许,咱们选择了尝试新方法,针对Hybrid App 这种特殊的运用场景定制了一种本地化缓存和存储的实现方案。时间仓促,方案自己仍处于测试阶段,某些方面考虑不免会有欠考虑,很是欢迎同窗们留言指出、改进。

相关文章
相关标签/搜索