前端性能优化(Application Cache篇)
正巧看到在送书,于是乎找了找自己博客上记录过的一些东西来及其无耻的蹭书了~~~
小广告:更多内容可以看我的博客
之前在segmentfault上刷问题看到一个关于manifest的问题,很好奇就研究了一下application cache。Application Cache是HTML5的新特性,允许浏览器在本地存储页面所需要的资源,使得页面离线也可以访问。之前研究的目的是为了在博客中使用,将一些不需要改动的CSS、JavaScript、图片文件离线缓存,这样加载速度必然飞起,希望能用在博客上,但是失败了,但还是记录一下学到的知识
Application Cache的配置文件
首先需要在服务器上建立一个文件,里面的内容确定了哪些文件需要缓存,哪些文件不需要,如果资源无法访问会使用什么页面等
这个文件一般为.appcache类型,称为缓存清单(cache manifest)文件,一个完整的缓存清单文件如下:
CACHE MANIFEST
# version xx.xx.xx
CACHE:
needBeCached.png
needBeCached2.js
NETWORK:
notNeedBeCached.html
notNeedBeCached2.css
FALLBACK:
/ 404.html
可以看到,文件的头部信息CACHE MANIFEST用来标注这个文件是缓存清单文件,其后一般情况下(最好是)跟着一行标明版本的注释,这行注释非常重要,将在后面文件加载部分详细介绍这行注释的重要性
CACHE部分
除了头部信息,这个缓存清单文件分为几部分,第一部分为CACHE部分:
CACHE:
needBeCached.png
needBeCached2.js
这一部分标注了哪些资源文件需要被缓存可以列出多个
如果有路径,如需要缓存blog下的blog.css文件,可以写成blog/blog.css。
另外CACHE:可以被省略,让需要缓存的资源文件直接跟在注释之后
NETWORK部分
第二部分为NETWORK部分:
NETWORK:
notNeedBeCached.html
notNeedBeCached2.css
这一部分定义了哪些文件不需要缓存,这些文件需要与服务器连接
与CACHE一样,可以定义多个资源,而如果直接输入一个文件夹路径,也是合法的,比如/blog这样,blog文件夹下的所有文件都不会被缓存
可以使用通配符来,如除了上面CACHE中定义的资源,其他都必须与服务器连接:
NETWORK:
*
需要注意一点是,载有这个manifest文件的HTML文档将一定会缓存,这个会在后面再次提到
FALLBACK部分
第三部分为FALLBACK部分:
FALLBACK:
/ 404.html
这一部分指定了一个后备页面,当资源无法访问时,浏览器会使用该页面
同样可以定义多条记录,每条记录列出两个URI,一个表示资源,一个表示后备页面。需要注意的是两个资源文件都需要使用相对路径切与manifest文件同源
同样可以使用通配符
保存和引用manifest文件
manifest文件可以保存在服务器上,保存为.appcache后缀,但必须与应用本身同源。在HTML文档中,可以指定清单文件的相对路径和绝对URL。需要注意的是,manifest文件的MIME类型必须是text/cache-manifest
需要在HTML文档中引入manifest文件,可以使用类似如下代码:
<!doctype html>
<html manifest="manifest.appcache">
...
</html>
这样,HTML文档加载后,就会根据manifest.appcache的内容来缓存资源文件,在下次访问相同页面的时候,会直接使用缓存的资源文件来进行加速
缓存和加载机制
在第一次访问时,浏览器加载完HTML文档后,会查看其是否有引入manifest文件。若引入,则加载manifest文件,然后根据manifest的文件内容进行资源的缓存,并缓存当前文档
之后访问,浏览器首先会查看manifest文件是否被修改(无论是内容还是注释),如果被修改,将当做第一次访问,重新根据manifest文件内容进行缓存
如果应用缓存存在,且manifest没有被修改,浏览器直接从缓存中加载文档(注意:加载文档)和资源,不会访问网络(注意:无论联网与否,都不会访问网络)
在缓存多个资源文件时,浏览器下载资源文件会先放在一个临时的缓存中,如果有任何一个资源文件下载失败,浏览器将停止其他缓存资源的下载,并清除临时缓存。如果所有资源文件都被成功下载,浏览器将会把这些资源文件以及引用manifest文件的HTML文档移动到永久离线缓存中
满满的都是坑
一些小坑
- 需要注意的是manifest文件放在服务器上,MIME类型必须是
text/cache-manifest,如果使用 Apache,需要修改.htaccess文件。IE下默认application/octet-stream,需要在服务器指定 - 每个需要缓存的页面的html都需要加入manifest属性
- 不要将manifest文件本身加入缓存,如果加入,浏览器将不会检测到服务器上manifest的更新,页面版本将万年不变
- 不要以为一个资源文件加载失败,其他文件就会被缓存,原因参见缓存和加载机制的最后一段
一些大坑
- 在manifest文件中定义的资源全部被成功加载后,这些资源文件连同引用manifest文件的HTML文档一并被移动到永久离线缓存中。所以如果想只缓存js、css、图片等文件,而不希望缓存HTML文档以保持获得最新内容的情况来说,这就是个大坑
- 根据Application Cache的加载机制,如果仅仅修改资源文件的内容(没有修改资源文件的路径或名称),浏览器将直接从本地离线缓存中获取资源文件。所以在每次修改资源文件的同时,需要修改manifest文件,以触发资源文件的重新加载和缓存。这其中,最有效的方式是修改manifest文件内部的版本注释(所以说那句注释相当重要)
- 如果资源没有被缓存,在而没有设置NETWORK的情况下,将会无法加载(浏览器不会去网络上进行加载),所以需要使用通配符来表明除了CACHE中确定的资源以外,其他资源都需要去网络上加载
使用iframe来避开一号坑?
网上传言避开一号坑的方法是使用iframe来指定需要缓存的资源,而避开HTML文档的缓存。具体做法是在HTML中嵌入一个iframe,iframe中的页面的HTML标签包含manifest属性引用manifest文件,里面定义了需要缓存的文件。这样就会只缓存iframe中的HTML文档,而持续更新主页面:
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>主页面</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/javascript.js"></script>
</head>
<body>
<iframe src="cache.html"></iframe>
</body>
</html>
可以看到,主页面的html标签中,并没有引入manifest文件。只是在其中加载了一个iframe,而这个iframe所加载的页面文档如下:
<!DOCTYPE html>
<html manifest="manifest.appcache">
<head>
<meta charset=utf-8 />
<title>缓存页面</title>
</head>
<body>
</body>
</html>
缓存页面中引入了manifest文件,这样浏览器就会缓存manifest文件中定义的资源列表,比如这里manifest文件的内容如下:
CACHE MANIFEST
# VERSION 1.0
CACHE:
css/someStyle.css
js/someJavaScript.js
NETWORK:
*
在chrome中运行,可以在命令行中看到如下效果:
Creating Application Cache with manifest http://localhost:8000/manifest.appcache
Application Cache Checking event
Application Cache Downloading event
Application Cache Progress event (0 of 2) http://localhost:8000/css/someStyle.css
Application Cache Progress event (1 of 2) http://localhost:8000/js/someJavaScript.js
Application Cache Progress event (2 of 2)
Application Cache Cached event
浏览器缓存了manifest文件中定义的资源文件,其实同时还缓存了iframe中的缓存页面的文档,但不会缓存主页面,修改一下主页面,并按F5刷新
Document was loaded from Application Cache with manifest http://localhost:8000/manifest.appcache
Application Cache Checking event
Application Cache NoUpdate event
可以看到主页面被更新了,但是someStyle.css和someJavaScript.js文件依旧从网络上加载了,而没有从cache中加载。打开chrome的chrome://appcache-internals/可以看到,里面cache.html、someStyle.css、someJavaScript.js确实被缓存了,去掉NETWORK段,结果也是一样
Flags URL Size (headers and data)
Master, http://localhost:8000/cache.html 388 B
Explicit, http://localhost:8000/css/someStyle.css 228 B
Explicit, http://localhost:8000/js/someJavaScript.js 244 B
Manifest, http://localhost:8000/manifest.appcache 316 B
在firefox、opera上测试也是一样,虽然被缓存了,但依旧会从网络上加载,而iframe的解答方法也是2011~2012年左右提出的,后来就没有相关文章了,估计已经彻底失效了
总结
Application主要是为了构建离线缓存,使得页面在离线模式下也能浏览。这比较适合一些页面上的应用以及静态的不经常变更的页面。其会缓存载体页面也是由于其机制。如果上面iframe机制实现有错误,或是有其他方法只缓存资源不缓存HTML文档,请联系我
参考资料
前端性能优化(Application Cache篇)的更多相关文章
- 前端性能优化(JavaScript篇)
正巧看到在送书,于是乎找了找自己博客上记录过的一些东西来及其无耻的蹭书了~~~ 小广告:更多内容可以看我的博客 优化循环 如果现在有个一个data[]数组,需要对其进行遍历,应当怎么做?最简单的代码是 ...
- Web前端性能优化进阶——完结篇
前言 在之前的文章 如何优化网站性能,提高页面加载速度 中,我们简单介绍了网站性能优化的重要性以及几种网站性能优化的方法(没有看过的可以狂戳 链接 移步过去看一下),那么今天我们深入讨论如何进一步优化 ...
- 前端性能优化(DOM篇)
原文链接:https://segmentfault.com/a/1190000000490322 缓存DOM对象 JavaScript的DOM操作可以说是JavaScript最重要的功能,我们经常要根 ...
- 前端性能优化JavaScript篇
关于前端性能优化的讨论一直都很多,包罗的知识也很多,可以说性能优化只有更好,没有最好.前面我写了一篇关于css优化的总结文章,今天再从javascript方面聊一聊. 1.从资源加载方面来说,浏览器的 ...
- CSS3与页面布局学习总结(八)——浏览器兼容与前端性能优化
一.浏览器兼容 1.1.概要 世界上没有任何一个浏览器是一样的,同样的代码在不一样的浏览器上运行就存在兼容性问题.不同浏览器其内核亦不尽相同,相同内核的版本不同,相同版本的内核浏览器品牌不一样,各种运 ...
- CSS3与页面布局学习笔记(八)——浏览器兼容性问题与前端性能优化方案
一.浏览器兼容 1.1.概要 世界上没有任何一个浏览器是一样的,同样的代码在不一样的浏览器上运行就存在兼容性问题.不同浏览器其内核亦不尽相同,相同内核的版本不同,相同版本的内核浏览器品牌不一样,各种运 ...
- Web前端性能优化全攻略
网页制作poluoluo文章简介:Web 前端性能优化是个大话题,是个值得运维人员持续跟踪的话题,是被很多网站无情忽视的技术. Web 前端性能优化是个大话题,是个值得运维人员持续跟踪的话题,是被很多 ...
- Web前端性能优化全攻略[转载]
1. 尽量减少 HTTP 请求 (Make Fewer HTTP Requests) 作为第一条,可能也是最重要的一条.根据 Yahoo! 研究团队的数据分析,有很大一部分用户访问会因为这一条而取得最 ...
- 前端性能优化:Add Expires headers
前端性能优化:Add Expires headers Expires headers 是什么? Expires headers:直接翻译是过期头.Expires headers 告诉浏览器是否应该从服 ...
- vue-小爱ADMIN系列文章(二):微信微博等分享,国际化,前端性能优化,nginx服务器部署
最近在做我的小爱ADMIN后台管理系统,结合当前市场后台管理系统对相关功能的需求,我又开始新增了一些新的功能和组件,如分享功能组件,项目国际化功能:项目完成后,部署在nginx服务器,发现首次访问的速 ...
随机推荐
- MySql日常解决错误
MySql数据库导入sql错误 Unknown collation: 'utf8mb4_0900_ai_ci 导入语句:mysql -u root -p database < E:/SS/Tes ...
- Go基础知识梳理(一)
Go基础知识梳理(一) Go中package的用法及作用 package hello 用于分包,Go通过包来管理命名空间 import ( "hello" //通过import关键 ...
- LeetCode-099-恢复二叉搜索树
恢复二叉搜索树 题目描述:给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换.请在不改变其结构的情况下,恢复这棵树. 进阶:使用 O(n) 空间复杂度的解法很容易实现.你能想出一个只使用 ...
- Kubernetes上安装Metrics-Server
操作场景 metrics-server 可实现 Kubernetes 的 Resource Metrics API(metrics.k8s.io),通过此 API 可以查询 Pod 与 Node 的部 ...
- 基于 vite2 + Vue3 写一个在线帮助文档工具
提起帮助文档,想必大家都会想到 VuePress等,我也体验了一下,但是感觉和我的思路不太一样,我希望的是那种可以直接在线编辑文档,然后无需编译就可以直接发布的方式,另外可以在线写(修改)代码并且运行 ...
- .NET6: 开发基于WPF的摩登三维工业软件 (8) - MVVM
基于WPF开发界面的一个很大优势是可以方便地基于MVVM设计模式开发应用.本文从应用的角度基于MVVM实现参数化管材的创建界面. 1 MVVM MVVM是Model-View-ViewModel的简写 ...
- PHP魔术方法11种
1.构造函数:__construct(): 构造函数是类中的一个特殊函数,当我们使用new关键字实例化对象时,相当于调用了类的构造函数. function __construct($name){ $t ...
- 构造方法__construct()与析构方法__destruct() 构造方法:刚出生时婴儿的啼哭 析构方法:老人临终时的遗言
<?phpclass person{ var $name; var $sex; var $age;//构造方法 function __construct($name, $sex, $age) { ...
- laravel 7 H-ui模板ajax批删
1,HTML页面写一个button按钮 <a href="javascript:;" onclick="deleteAll()" class=" ...
- tp5 git 常见命令
git clone git add . # 跟踪所有改动过的文件 git commit -m "commit message" # 提交所有更新过的文件 git checkout ...