从Wep page到Application
需要做一个选择,是Web app还是Native app,当然,还有第三种,Hybrid app。
现在手机用户越来越多,电脑终端浏览器也在不断的更新换代,推陈出新,网页已经不仅仅是用来分享信息这么简单,可以用来做更多的事情。
本地存储升级
在以前,浏览器几乎不具备太多的存储能力。HTML5在存储方面做了重大的改进,提供了localStorage和sessionStorage对象用于小型数据的存储,更提供了WebDatabase以存储大量数据。
cookie与cookie的局限
Http本身是一种无状态无链接的协议,用户在浏览器上请求一个动作时,服务器不会知道用户上一个动作做了什么,因此,如果要存储诸如登录与否、已登录文本等状态信息是非常麻烦的。cookie的发明则满足了大部分的状态存储的需求。从根本上讲,cookie就是一段存储在客户端(浏览器)的文本,我们既可以在服务器响应返回时设置cookie,也可以在前端通过javascript进行修改。cookie有域限制,不同域的cookie相互不影响,也不能互相访问。
可以在谷歌浏览器的控制台输入document.cookie来查看当前网页所有可用的cookie,也可以通过这样的方式document.cookie="uid=123"来设置cookie,这条语句不会覆盖之前的cookie,只是自动添加到原先cookie的后面,不同的键值对用";"分隔。除了域的限制以外,还有一个大小和数量的限制对于我们数据存储来说,影响很大。不同的浏览器采用了不同的限制策略,但都不会很多。
来自HTML5的Web Storage
相比较于cookie而言,HTML5规范中的WebStorage更适合用作本地数据存储。Web Storage的使用非常方便,速度更快也更安全,只会存储在浏览器中而不会随HTTP请求发送到服务器端。它可以轻松存储大量数据而丝毫不会影响你网站的性能。
Web Storage使用
浏览器内置了两个已经实例化好了的对象,一个是sessionStorage,另一个是localStorage。
其中sessionStorage中存储的数据只是在单页面会话期间有效,sessionStorage更类似于一个页面上的全局变量。而localStorage的数据则会被持久化到客户端,而且永远不会过期(cookie可以设置过期时间),并且其容量也不会像cookie那样受限。
无论是sessionStorage还是localStorage,都可以使用下述这些方法或属性:
setItem(key,value) getItem(key) removeItem(key) length key(n) clear()
这两者的区别是存储数据的生命周期不一样,只要一直在这个域内连续访问,存储在sessionStorage的数据会一直存在,一旦关闭页面或浏览器,所有sessionStorage存储的数据都会消失(也就是说,sessionStorage不会将数据存入磁盘)。
storage事件
对Storage对象进行的所有修改都会触发文档上的storage事件。其中事件对象会有以下属性:
domain key oldValue newValue
例如:
document.addEventListener("storage", function(e) {console.log("Storage changed. Name '" + e.Key +"'"); });
由于这个事件有兼容性问题,一般不建议使用。
当然,并不是说localStorage大小可以无限使用,对于不同的浏览器,有不一样的设定,但大体上会给每个域设有5MB的存储空间,这对于大多数应用来说,已经足够了。
缓存和应用缓存
HTML5提供了一种独特的缓存机制:Application Cache(应用缓存)
顾名思义,这是为应用程序而生的缓存机制。主要是可以将服务器端的资源文件缓存至本地,至少有以下三个有点:
加速应用启动速度---省却了下载文件的时间
离线访问--利用离线缓存下来的页面和文件资源继续未完成的工作
节省服务器资源--更少的请求,意味着更小的服务器压力。
应用缓存的基本使用
一般而言,针对单页应用启用。
manifest
在文档中开启应用缓存非常简单,只需要在HTML标签中添加一个manifest属性,并指定manifest文件即可。
<!DOCTYPE html>
<html manifest="/appcache.manifest">
//这个html文件本身一定会被缓存
</html>
而appcache.manifest其实就是一个文本文件,里面指定了需要浏览器缓存的资源,比如像下面这个样子:
CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js
浏览器首次加载页面时会读取该文件,并下载和缓存它指定的资源,上面例子中缓存了四个文件,由于缓存是一次性的,因此如果四个文件有任何一个文件不可用,整个缓存行为将失败。除了文件中指定的四个需要缓存的文件以外,指定manifest文件的html文档也会被缓存下来。
要注意服务器在返回此文件时必须设置MIME类型为text/cache-manifest,不同服务器指定MIME类型的方式不同,基于NodeJS的Web服务器Express中设置MIME的方式如下:
res.type('text/cache-manifest')
res.sendfile(appcache.manifest文件路径)
manifest文件还可以指定一些特别的缓存行为,下面是一个完整格式的示例
CACHE MNIFEST
#指定会被缓存的资源
/favicon.ico
images/logo.png
stylesheetes/style.css
javascripts/app.js
#必须在有网络时访问的资源
NETWORK:
/api
#降级访问
FALLBACK:
#根目录如果不可用,则读取offline.html文件
/ /offline.html
#所有images/目录下的文件不可用时被请求,则读取images/offline.jpg
images/ images/offline.png
任何一个manifest文件都可以包含CACHE NETWORK 和FALLBACK三个不同的部分,它们分别表示如下:
CACHE:一定会被缓存的资源,浏览器首次加载页面时便下载其后的所有文件。
NETWORK:这些文件属于白名单资源,无论是否处于离线状态,这些资源的访问都会绕过缓存,资源的URL可以使用通配符。
FALLBACK:对于不可访问资源使用后备资源进行访问,两种资源以空格隔开,第一部分表示资源可用时的路径,第二部分表示后备资源缓存路径。资源的URL可以使用通配符。
以上三个部分可以按照任意顺序和数量进行组合。
缓存更新
著名程序员Phil Karlton曾说过:"在计算机科学领域,有两大难题,如何让缓存失效(cache invalidation)和如何给各种东西命名"
有三种方式进行缓存失效:
修改manifest文件:修改被缓存的文件本身并不会自动更新缓存,但是更改manifest文件本身则会重新下载整个缓存列表。
通过API接口以编程方式进行缓存控制。
用户主动在浏览器中清除缓存数据—对于开发者来说意义不大,最多是在调试的时候根据需要清除缓存来测试程序
由于manifest文件支持注释,而注释的更改也可以使manifest文件变化从而导致更新缓存,我们可以利用这一特点来实现自动更新缓存。使用程序生成一串随机值创建一行注释写入到manifest文件中,这个随机值可以是版本号、文本哈希值和时间戳等。
下面给出的是一个基于NodeJS的简单的版本生成器:
var fs = require('fs'),
mfPath = './public/appcache.manifest',
mfOutputPath = './public/output.manifest'
function gernerateVersionHash() {
//使用当前时间生成一段随机版本号
return (+new Date()).toString(32)
}
fs.readFile(mfPath, function(err, data) {
if(err) throw err;
var output = '# version=' + generateVersionHash() + '\n' + data;
fs.writeFile(mfOutputPath, output, function(err) {
if(err) throw err;
console.log('生成文件成功!路径:' + mfOutputPath)
}); })
配置好路径后,每次在更新了应用程序时,只需要运行这个脚本即可更新缓存。当然也可以监视你要保存的资源文件是否被修改来自动生成新版本的manifest文件以实现更新缓存。
编程接口
更新缓存更好的方式是通过javascript访问离线缓存接口。window.applicationCache对象定义了应用缓存的编程接口。比如我们要更新缓存,可以调用applicationCache.update()方法时,浏览器将先重新获取manifest文件,如果manifest文件有变化,那么就尝试更新用户的缓存。不过此时只是将需要缓存的文件下载下来,当下载完毕,调用applicationCache.swapCache()即可,applicationCache.status属性查询缓存的当前状态。
Application cache的使用不算困难,但是在使用时一定要注意下面这两个问题:
访问页面时,查询参数将会不起作用。如访问index.html?page=1这个url,第一次加载时后端服务器可以取到page=1这个参数,可是当index.html被缓存后,无论如何调正查询参数都是不会向服务器发起请求的,需要注意这一点,如果需要在url中传递参数,可以使用hash,并用javascript处理hash内容。
manifest本身也有可能被缓存,设置过期header是个解决办法。
以上内容来自《HTML5 移动Web开发实战详解》 林珑编著。