热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HTML5离线应用无法更新的定位与解决

最近在制作一个Web应用,其中用到了HTML5的离线应用功能(offlineapplication),离线应用的概念就不再阐述,可以查看这两篇
一、些许前提

最近在制作一个Web应用, 其中用到了HTML5的离线应用功能(offline application), 离线应用的概念就不再阐述, 可以查看这两篇文章:

http://www.ibm.com/developerworks/cn/web/1011_guozb_html5off/

http://www.mhtml5.com/2011/02/583.html

这里主要讨论它的更新问题. 首先浏览器是有两部分cache的, browser cache 和app cache, browser cache就是常说的浏览器缓存, app cache是离线应用的缓存. 他们各自的更新机制如下:

 

Browser cache

App cache

其中browser cache的机制大家都很清楚了, 其中离线应用的更新是: 除了第一次访问是直接拉取server的, 然后后台更新app cache之外, 其余的情况都是直接访问app cache. 因此, 要如果离线应用的代码更新了, 只有下次打开或者刷新才会生效.

二、找出凶手

OK, 铺垫完毕. 我的应用主要在webkit内核的浏览器使用的, 为了方便起见, 下面的文字都是在chrome的环境下产生的.

在测试机测试离线功能时, 我们发现, 如果更改了js文件且更新了manifest, 刷新两次(嗯, 你没看错,是两次, 第一次于后台更新app cache, 第二次应用新cache)就会应用上新的代码. 但是, 发布到正式环境之后, 就不能更新了, 把F5按烂了, 也没什么变化. 当然这是删除掉app cache是没问题的, 但是我们没办法要求用户这样做.

通过抓包发现, 无论哪个环境, manifest更新了, 浏览器端都能抓取新的, 在chrome的控制台也能看到更新app cache的log, 因此不是manifest本身被缓存了的原因. 但是在正式环境里面, 拉取了新的manifest之后, 就没有任何更新的请求出去, 太诡异了.

继续对比http的响应头, 发现了不同之处, 如下:

测试环境 正式环境

HTTP/1.1 200 OK

Date: Thu, 05 Jan 2012 05:56:38 GMT

Server: NWS_HY_P91

Last-Modified: Thu, 05 Jan 2012 04:29:52 GMT

Expires: Thu, 05 Jan 2012 05:56:38 GMT

Connection: close

Content-Type: application/Javascript

Vary: Accept-Encoding

HTTP/1.1 200 OK

Date: Thu, 05 Jan 2012 05:56:38 GMT

Server: nginx

Last-Modified: Thu, 05 Jan 2012 04:29:52 GMT

Expires: Thu, 05 Jan 2012 05:56:38 GMT

Connection: keep-alive

Content-Type: application/Javascript

Cache-Control: max-age=10368000

可以看到, 两个环境里面有3个不同, connection, vary, cache-control. 第一眼望去, 感觉就可能是cache-control的问题. 于是用fildder把响应卡住, 把max-age改成0, 结果呢, 它正常更新了! 因此猜测app cache的更新应该是先去browser cache找, 找到了该文件, 并且没过期, 就不再访问server了, 因此抓包也看不到任何请求. 它的流程应该是这样的:

App cache 2

于是我本地搭了一个apache验证, 把js的max-age设置为30秒, 果然在30秒内, 无论怎么修改manifest和js, 都不会有对js的新请求, 它一直在向browser cache拉取, 而30秒之后, 就能去server拉去新的js了.

三、谁是真凶?

理论上这件事就应该到此为止了, 只要把正式环境的cdn都去掉cache-control就大功告成啦. 但是,去掉cache-control将大大浪费公司的带宽! 而且deewii童鞋发现, 有一台放置vm(应用用到的一个接口层, 是一个页面)的机器, 也设置了cache-control, 但是却能正常更新, 这下又变得扑朔迷离了.

刚才我们对比响应头发现了三个不同, 继续看connection这东西, keep-alive是用来保持长连接的, 莫非是它的影响? 但是抓了几个包, 却发现vm所在机器返回的响应头里面是Connection: keep-alive, 因此排除了这个影响.

最后只能把希望放在Vary: Accept-Encoding 里面了, 还是刚刚搭apache, 加上max-age=10368000, 加上keep-alive, 加上Vary: Accept-Encoding, 修改manifest, 刷新… 天, 竟然发起更新请求了! 原来你(Accept-Encoding)才是真正的凶手! 有没有可能是本地才会这样呢, 继续用fiddler卡住正式环境的响应, 加上Vary: Accept-Encoding, 果然刷新之后也能正常更新了.

虽然找到原因, 但是本人对这个Accept-Encoding不是很了解, 查了些资料(参考这里: http://www.falconhan.com/webanalytics/vary-accept-encoding-header.htm ), 猜测Accept-Encoding是用来告诉浏览器只缓存它自己声明的类型(在发起的http请求头里面指定, 例如: Accept-Encoding: gzip,deflate,sdch)的文件, 而存在于browser cache里面的内容则是浏览器解压后的, 因此app cache去browser cache更新的时候发现格式不对, 就抛弃掉, 继续去server请求. 不知道想的对不对, 欢迎拍砖指正.

四、写在后面

花了一个晚上+一个上午, 总算把这个无法更新的问题解决了. 虽然最后得到的结论很简单, 只要在服务器配个返回头就行了, 但是找问题的时候相当痛苦. 归根到底还是对http协议不够了解, 学艺不精还得继续努力.

PS: 在用firefox测试的时候, 发现它只有第一次打开(或者删掉离线数据之后)的时候会去请求manifest和其他离线资源, 之后它竟然完全不访问manifest, 导致没办法更新, 网上也没找到什么好资料(网上也有遇到相同状况的童鞋: http://hi.baidu.com/erik168/blog/item/aadff9547720d8013b293559.html ), 不知道有没有童鞋了解的.

参考资料

Offline Application

http://www.ibm.com/developerworks/cn/web/1011_guozb_html5off/

http://www.mhtml5.com/2011/02/583.html

http://www.mhtml5.com/resources/html5-js-api-%E6%95%99%E7%A8%8B%EF%BC%88%E5%9B%9B%EF%BC%89-%E7%A6%BB%E7%BA%BF%E5%BA%94%E7%94%A8

Vary: Accept-Encoding

http://www.falconhan.com/webanalytics/vary-accept-encoding-header.htm

http://hi.baidu.com/%B9%E3%D6%DD_it%C4%D0/blog/item/c2dd76c96d1eb4009c163d2a.html

http://mark.koli.ch/2010/09/understanding-the-http-vary-header-and-caching-proxies-squid-etc.html

Firefox的ApplicationCache

http://hi.baidu.com/erik168/blog/item/aadff9547720d8013b293559.html


推荐阅读
  • 本文介绍了使用 Python 编程语言高效抓取微博文本和动态网页图像数据的方法。通过详细的示例代码,展示了如何利用爬虫技术获取微博内容和动态图片,为数据采集和分析提供了实用的技术支持。对于对网络数据抓取感兴趣的读者,本文具有较高的参考价值。 ... [详细]
  • 深入解析Tomcat:开发者的实用指南
    深入解析Tomcat:开发者的实用指南 ... [详细]
  • 软件测试工程师必备:全面解析Web应用的浏览器兼容性测试方法与工具
    随着市场上浏览器种类的不断增多,特别是在平板和移动设备上的普及,确保网站在各种浏览器中都能正常运行变得尤为重要。本文将深入探讨Web应用的浏览器兼容性测试方法与工具,帮助软件测试工程师全面掌握这一关键技能,以提高应用的用户体验和可靠性。 ... [详细]
  • 本文深入探讨了IO复用技术的原理与实现,重点分析了其在解决C10K问题中的关键作用。IO复用技术允许单个进程同时管理多个IO对象,如文件、套接字和管道等,通过系统调用如`select`、`poll`和`epoll`,高效地处理大量并发连接。文章详细介绍了这些技术的工作机制,并结合实际案例,展示了它们在高并发场景下的应用效果。 ... [详细]
  • HTML5 Web存储技术是许多开发者青睐本地应用程序的重要原因之一,因为它能够实现在客户端本地存储数据。HTML5通过引入Web Storage API,使得Web应用程序能够在浏览器中高效地存储数据,从而提升了应用的性能和用户体验。相较于传统的Cookie机制,Web Storage不仅提供了更大的存储容量,还简化了数据管理和访问的方式。本文将从基础概念、关键技术到实际应用,全面解析HTML5 Web存储技术,帮助读者深入了解其工作原理和应用场景。 ... [详细]
  • 深入浅出解析HTTP协议的核心功能与应用
    前言——协议是指预先设定的通信规则,确保双方能够按照既定标准进行有效沟通,从而实现准确的信息交换。例如,驯兽师通过拍手使动物坐下,这实际上是一种预设的协议。本文将详细探讨HTTP协议的核心功能及其广泛应用,解析其在现代网络通信中的重要作用。 ... [详细]
  • 比尔·盖茨最新个人网站出人意料地选择Linux服务器,背后有何深意?
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 在《PHP应用性能优化实战指南:从理论到实践的全面解析》一文中,作者分享了一次实际的PHP应用优化经验。文章回顾了先前进行的一次优化项目,指出即使系统运行时间较长后出现的各种问题和性能瓶颈,通过采用一些通用的优化策略仍然能够有效解决。文中不仅详细阐述了优化的具体步骤和方法,还结合实例分析了优化前后的性能对比,为读者提供了宝贵的参考和借鉴。 ... [详细]
  • 【Python爬虫实操】 不创作小说,专精网站内容迁移,超高效!(含源代码)
    本文详细介绍了如何利用Python爬虫技术实现高效网站内容迁移,涵盖前端、后端及Android相关知识点。通过具体实例和源代码,展示了如何精准抓取并迁移网站内容,适合对Python爬虫实战感兴趣的开发者参考。 ... [详细]
  • 手机上编写和运行PHP代码的最佳软件推荐 ... [详细]
  • 在前一篇文章中,我们介绍了如何使用Requests库发送GET请求。本文将深入探讨如何通过Requests库发送POST请求,包括参数格式、请求封装等关键技巧,并通过“历史上的今天”API实例进行详细说明。 ... [详细]
  • (1)搜狗搜索人物实战 importrequestsurlhttps:www.sogou.comweb?query李荣浩 #首先我们需要观察在搜狗输入李 ... [详细]
  • 代码:headersAccept:texthtml,applicationxhtml+xml,applicationxml;q0.9,imagewebp,image ... [详细]
  • Markdown语法说明:http:www.appinn.commarkdown1、前端碎片知识总结篇1.1关于浏览器IE的内核是Trident、Mozilla的内核 ... [详细]
  • 小编给大家分享一下Css3中box-pack属性怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收 ... [详细]
author-avatar
连政宪景琪雅婷
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有