浏览器端的 9 种缓存机制-阿里云开发者社区

开发者社区> 美人迟暮> 正文

浏览器端的 9 种缓存机制

简介:
+关注继续查看

浏览器端的 9 种缓存机制





浏览器缓存Browser Caching是浏览器端保存数据用于快速读取或避免重复资源请求的优化机制,有效的缓存使用可以避免重复的网络请求和浏览器快速地读取本地数据,整体上加速网页展示给用户。浏览器端缓存的机制种类较多,总体归纳为九种,这里详细分析下这九种缓存机制的原理和使用场景。打开浏览器的调试模式->resources左侧就有浏览器的8种缓存机制。

一、http缓存

http缓存是基于HTTP协议的浏览器文件级缓存机制。即针对文件的重复请求情况下,浏览器可以根据协议头判断从服务器端请求文件还是从本地读取文件,chrome控制台下的Frames即展示的是浏览器的http文件级缓存。以下是浏览器缓存的整个机制流程。主要是针对重复的http请求,在有缓存的情况下判断过程主要分3步:

  • 判断expires,如果未过期,直接读取http缓存文件,不发http请求,否则进入下一步
  • 判断是否含有etag,有则带上if-none-match发送请求,未修改返回304,修改返回200,否则进入下一步
  • 判断是否含有last-modified,有则带上if-modified-since发送请求,无效返回200,有效返回304,否则直接向服务器请求

如果通过etag和last-modified判断,即使返回304有至少有一次http请求,只不过返回的是304的返回内容,而不是文件内容。所以合理设计实现expires参数可以减少较多的浏览器请求。

二、websql

websql这种方式只有较新的chrome浏览器支持,并以一个独立规范形式出现,主要有以下特点

  • Web Sql 数据库API 实际上不是HTML5规范的组成部分;
  • 在HTML5之前就已经存在了,是单独的规范;
  • 它是将数据以数据库的形式存储在客户端,根据需求去读取;
  • 跟Storage的区别是: Storage和Cookie都是以键值对的形式存在的;
  • Web Sql 更方便于检索,允许sql语句查询;
  • 让浏览器实现小型数据库存储功能;
  • 这个数据库是集成在浏览器里面的,目前主流浏览器基本都已支持;

websql API主要包含三个核心方法:

  • openDatabase : 这个方法使用现有数据库或创建新数据库创建数据库对象。
  • transaction : 这个方法允许我们根据情况控制事务提交或回滚。
  • executeSql : 这个方法用于执行真实的SQL查询。 

openDatabase方法可以打开已经存在的数据库,不存在则创建:


  1. var db = openDatabase('mydatabase', '2.0', my db',2*1024);

openDatabasek中五个参数分别为:数据库名、版本号、描述、数据库大小、创建回调。创建回调没有也可以创建数据库。

database.transaction() 函数用来查询,executeSql()用于执行sql语句。

例如在mydatabase数据库中创建表t1:


  1. var db = openDatabase(' mydatabase ', '1.0', 'Test DB', 2 * 1024 * 1024);
  2. db.transaction(function(tx){
  3. tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');
  4. });

插入操作


  1. var db = openDatabase('mydatabase', '2.0', my db', 2 * 1024);
  2. db.transaction(function (tx) {
  3. tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');
  4. tx.executeSql('INSERT INTO t1 (id, log) VALUES (1, "foobar")');
  5. tx.executeSql('INSERT INTO t1 (id, log) VALUES (2, "logmsg")');
  6. });

在插入新记录时,我们还可以传递动态值,如:


  1. var db = openDatabase(' mydatabase ', '2.0', 'my db', 2 * 1024);
  2. db.transaction(function(tx){
  3. tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');
  4. tx.executeSql('INSERT INTO t1 (id,log) VALUES (?, ?'), [e_id, e_log]; //e_id和e_log是外部变量
  5. });

读操作,如果要读取已经存在的记录,我们使用一个回调捕获结果:


  1. var db = openDatabase(mydatabase, '2.0', 'my db', 2*1024);
  2. db.transaction(function (tx) {
  3. tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');
  4. tx.executeSql('INSERT INTO t1 (id, log) VALUES (1, "foobar")');
  5. tx.executeSql('INSERT INTO t1 (id, log) VALUES (2, "logmsg")');
  6. });
  7. db.transaction(function (tx) {
  8. tx.executeSql('SELECT * FROM t1, [], function (tx, results) {
  9. var len = results.rows.length, i;
  10. msg = "<p>Found rows: " + len + "</p>";
  11. document.querySelector('#status').innerHTML += msg;
  12. for (i = 0; i < len; i++){
    alert(results.rows.item(i).log );
  13. }
  14. }, null);
  15. });

三、indexDB

IndexedDB 是一个为了能够在客户端存储可观数量的结构化数据,并且在这些数据上使用索引进行高性能检索的 API。虽然 DOM 存储 对于存储少量数据是非常有用的,但是它对大量结构化数据的存储就显得力不从心了。IndexedDB 则提供了这样的一个解决方案。

IndexedDB 分别为同步和异步访问提供了单独的 API 。同步 API 本来是要用于仅供 Web Workers 内部使用,但是还没有被任何浏览器所实现。异步 API 在 Web Workers 内部和外部都可以使用,另外浏览器可能对indexDB有50M大小的限制,一般用户保存大量用户数据并要求数据之间有搜索需要的场景。

异步API

异步 API 方法调用完后会立即返回,而不会阻塞调用线程。要异步访问数据库,要调用 window 对象 indexedDB 属性的 open() 方法。该方法返回一个 IDBRequest 对象 (IDBOpenDBRequest);异步操作通过在 IDBRequest 对象上触发事件来和调用程序进行通信。

  • IDBFactory 提供了对数据库的访问。这是由全局对象 indexedDB 实现的接口,因而也是该 API 的入口。
  • IDBCursor 遍历对象存储空间和索引。
  • IDBCursorWithValue 遍历对象存储空间和索引并返回游标的当前值。
  • IDBDatabase 表示到数据库的连接。只能通过这个连接来拿到一个数据库事务。
  • IDBEnvironment 提供了到客户端数据库的访问。它由 window 对象实现。
  • IDBIndex 提供了到索引元数据的访问。
  • IDBKeyRange 定义键的范围。
  • IDBObjectStore 表示一个对象存储空间。
  • IDBOpenDBRequest 表示一个打开数据库的请求。
  • IDBRequest 提供了到数据库异步请求结果和数据库的访问。这也是在你调用一个异步方法时所得到的。
  • IDBTransaction 表示一个事务。你在数据库上创建一个事务,指定它的范围(例如你希望访问哪一个对象存储空间),并确定你希望的访问类型(只读或写入)。
  • IDBVersionChangeEvent 表明数据库的版本号已经改变。

同步API

规范里面还定义了 API 的同步版本。同步 API 还没有在任何浏览器中得以实现。它原本是要和webWork 一起使用的。

四、cookie

Cookie(或者Cookies),指一般网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。cookie一般通过http请求中在头部一起发送到服务器端。一条cookie记录主要由键、值、域、过期时间、大小组成,一般用户保存用户的认证信息。cookie最大长度和域名个数由不同浏览器决定,具体如下:

浏览器 支持域名个数 最大长度
IE7以上 50个 4095B
Firefox 50个 4097B
Opera 30个 4096B
Safari/WebKit 无限制 4097B

不同域名之间的cookie信息是独立的,如果需要设置共享可以在服务器端设置cookie的path和domain来实现共享。浏览器端也可以通过document.cookie来获取cookie,并通过js浏览器端也可以方便地读取/设置cookie的值。

https://github.com/component/cookie/blob/master/index.js

五、localstorage

localStorage是html5的一种新的本地缓存方案,目前用的比较多,一般用来存储ajax返回的数据,加快下次页面打开时的渲染速度。

浏览器 最大长度
IE9以上 5M
Firefox 8以上 5.24M
Opera 2M
Safari/WebKit 2.6M

  1. //localStorage核心API:
  2. localStorage.setItem(key, value) //设置记录
  3. localStorage.getItem(key) //获取记录
  4. localStorage.removeItem(key) //删除该域名下单条记录
  5. localStorage.clear() //删除该域名下所有记录

值得注意的是,localstorage大小有限制,不适合存放过多的数据,如果数据存放超过最大限制会报错,并移除最先保存的数据。

https://github.com/machao/localStorage

六、sessionstorage

sessionStorage和localstorage类似,但是浏览器关闭则会全部删除,api和localstorage相同,实际项目中使用较少。

七、application cache

application cahce是将大部分图片资源、js、css等静态资源放在manifest文件配置中。当页面打开时通过manifest文件来读取本地文件或是请求服务器文件。
离线访问对基于网络的应用而言越来越重要。虽然所有浏览器都有缓存机制,但它们并不可靠,也不一定总能起到预期的作用。HTML5 使用ApplicationCache 接口可以解决由离线带来的部分难题。前提是你需要访问的web页面至少被在线访问过一次。
使用缓存接口可为您的应用带来以下三个优势:

  • 离线浏览 – 用户可在离线时浏览您的完整网站
  • 速度 – 缓存资源为本地资源,因此加载速度较快。
  • 服务器负载更少 – 浏览器只会从发生了更改的服务器下载资源。

一个简单的离线页面主要包含以下几个部分:

index.html


  1. <htmlmanifest="clock.manifest">
  2. <head>
  3. <title>AppCache Test</title>
  4. <linkrel="stylesheet"href="clock.css">
  5. <script src="clock.js"></script>
  6. </head>
  7. <body>
  8. <p><outputid="clock"></output></p>
  9. <divid="log"></div>
  10. </body>
  11. </html>

clock.manifest


  1. CACHE MANIFEST
  2. #VERSION 1.0
  3. CACHE:
  4. clock.css
  5. clock.js

clock.js和clock.css为独立的另外文件。

另外需要注意的是更新缓存。在程序中,你可以通过window.applicationCache 对象来访问浏览器的app cache。你可以查看 status 属性来获取cache的当前状态:


  1. var appCache = window.applicationCache;
  2. switch (appCache.status) {
  3. case appCache.UNCACHED: // UNCACHED == 0
  4. return 'UNCACHED';
  5. break;
  6. case appCache.IDLE: // IDLE == 1
  7. return 'IDLE';
  8. break;
  9. case appCache.CHECKING: // CHECKING == 2
  10. return 'CHECKING';
  11. break;
  12. case appCache.DOWNLOADING: // DOWNLOADING == 3
  13. return 'DOWNLOADING';
  14. break;
  15. case appCache.UPDATEREADY: // UPDATEREADY == 4
  16. return 'UPDATEREADY';
  17. break;
  18. case appCache.OBSOLETE: // OBSOLETE == 5
  19. return 'OBSOLETE';
  20. break;
  21. default:
  22. return 'UKNOWN CACHE STATUS';
  23. break;
  24. };

为了通过编程更新cache,首先调用 applicationCache.update()。这将会试图更新用户的 cache(要求manifest文件已经改变)。最后,当 applicationCache.status 处于 UPDATEREADY 状态时, 调用applicationCache.swapCache(),旧的cache就会被置换成新的。


  1. var appCache = window.applicationCache;
  2. appCache.update(); // Attempt to update the user’s cache.
  3. if (appCache.status == window.applicationCache.UPDATEREADY) {
  4. appCache.swapCache(); // The fetch was successful, swap in the new cache.
  5. }

这里是通过更新menifest文件来控制其它文件更新的。

八、cacheStorage

CacheStorage是在ServiceWorker的规范中定义的。CacheStorage 可以保存每个serverWorker申明的cache对象,cacheStorage有open、match、has、delete、keys五个核心方法,可以对cache对象的不同匹配进行不同的响应。

cacheStorage.has()

如果包含cache对象,则返回一个promise对象。

cacheStorage.open()

打开一个cache对象,则返回一个promise对象。

cacheStorage.delete()

删除cache对象,成功则返回一个promise对象,否则返回false。

cacheStorage.keys()

含有keys中字符串的任意一个,则返回一个promise对象。

cacheStorage.delete()

匹配key中含有该字符串的cache对象,返回一个promise对象。


  1. caches.has('v1').then(function(){
  2. caches.open('v1').then(fu
  3. ssets);
  4. });
  5. }).catch(function(){
  6. someCacheSetupfunction();
  7. });;

  1. var response;
  2. var cachedResponse = caches.match(event.request).catch(function(){
  3. return fetch(event.request);
  4. }).then(function(r){
  5. response = r;
  6. caches.open('v1').then(function(cache){
  7. cache.put(event.request, response);
  8. });
  9. return response.clone();
  10. }).catch(function(){
  11. return caches.match('/sw-test/gallery/myLittleVader.jpg');
  12. });

  1. then.addEventListener('activate', function(event){
  2. var cacheWhitelist = ['v2'];
  3. event.waitUntil(
  4. caches.keys().then(function(keyList){
  5. return Promise.all(keyList.map(function(key){
  6. if (cacheWhitelist.indexOf(key) === -1) {
  7. return caches.delete(keyList[i]);
  8. }
  9. });
  10. })
  11. );
  12. });

https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage

九、flash缓存

这种方式基本不用,这一方法主要基于flash有读写浏览器端本地目录的功能,同时也可以向js提供调用的api,则页面可以通过js调用flash去读写特定的磁盘目录,达到本地数据缓存的目的。

注释PS

  • Web Storage / Web SQL Database / Indexed Database 的数据都存储在浏览器对应的用户配置文件目录(user profile directory)下,以 Windows 7 为例,Chrome 的数据存储在”C:\Users\your-account-name\AppData\Local\Google\Chrome\User Data\Default\”下,而 Firefox 的数据存储在”C:\Users\your-account-name\AppData\Local\Mozilla\Firefox\Profiles\”目录下。
  • cookie文件存储于documents and settings\userName\cookie\文件夹下。通常的命名格式为:userName@domain.txt

  • 较多的缓存机制目前主流浏览器并不兼容,不过可以使用polyfill的方法来处理

浏览器涉及的缓存方式主要包含这些,具体结合自己的业务场景进行选择使用



本文来自云栖社区合作伙伴“Linux中国”

原文发布时间为:2013-04-02.

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
4009 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
3956 0
设置google浏览器不缓存JS
惯例: 我是温浩然: Google浏览器中,F12,控制台,选择右上的设置(settings)。 左侧找General,然后取消选中,Disabled JavaScript OK
1822 0
缓存键重复、冲突带来的数据读取错误
    第二次了,栽在这个问题上, 依然是出自缓存。     需要注意两个问题:     1.根据分类读的数据列表,缓存键需要带上分类ID/分类名称。     2.由于子模块比较多,缓存键命名的时候,整体搜一下是否已存在当前缓存键,否则容易出现多个模块公用一个缓存的现象,导致必有一处数据不对。
659 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
5674 0
fbh
Chrome浏览器强制刷新页面(不使用缓存)
在Chrome浏览器中按下F5或 Ctrl+F5 都没用,Chrome总是会强制使用页面缓存进行刷新,如何不使用页面缓存进行刷新? Chrome官方推荐使用如下快捷键,就可以不使用页面缓存进行刷新 Windows和Linu...
3581 0
hibernate注解方式的二级缓存
hibernate默认情况下是支持一级缓存,也就是session级的缓存的,而默认情况下是不支持二级缓存,即sessionFactory级的缓存的,二级缓存        一般比较少去考虑它,除非对效率要求非常高的时候, 这时侯如果我们的某一个实体要在多个session里面使用需要用到s...
745 0
Confluence 6 升级自定义的站点和空间关闭缓存
Velocity 被配置在内存中使用缓存模板。当你在 Confluence 中编辑了页面的模板文件,Confluence 知道文件进行了编辑,将会重新从磁盘中载入模板文件。
851 0
+关注
美人迟暮
Nothing for nothing.
1020
文章
212
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载