《offline coolbook》笔记
https://jakearchibald.com/2014/offline-cookbook/
在install中对依赖进行缓存
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('mysite-static-v3').then(function(cache) {
return cache.addAll([
'/css/whatever-v3.css',
'/css/imgs/sprites-v6.png',
'/css/fonts/whatever-v8.woff',
'/js/all-min-v4.js'
// etc
]);
})
);
});
waitUntil接收的参数是一个promise,这个promise决定了install阶段的持续时长和是否成功。
在install中对非依赖进行缓存
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('mygame-core-v1').then(function(cache) {
cache.addAll(
// levels 11-20
);
return cache.addAll(
// core assets & levels 1-10
);
})
);
});
以上waitUntil接收到的promise,仅仅是对应加载了核心的缓存。虽然也加载了非关键的缓存(levels11-20),但是对install的状态无影响。
在activate阶段清除缓存
self.addEventListener('activate', function(event) {
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.filter(function(cacheName) {
// Return true if you want to remove this cache,
// but remember that caches are shared across
// the whole origin
}).map(function(cacheName) {
return caches.delete(cacheName);
})
);
})
);
});
Keep your activation as lean as possible, only use it for things you couldn't do while the old version was active
处理用户的交互
给用户一个按钮,让用户选择保存某些资源以离线访问。资源的唯一标识与某个cache要一一对应
document.querySelector('.cache-article').addEventListener('click', function(event) {
event.preventDefault();
var id = this.dataset.articleId;
caches.open('mysite-article-' + id).then(function(cache) {
fetch('/get-article-urls?id=' + id).then(function(response) {
// /get-article-urls returns a JSON-encoded array of
// resource URLs that a given article depends on
return response.json();
}).then(function(urls) {
cache.addAll(urls);
});
});
});
以上代码与sw是否被激活无关。也就是说cache和sw的运行是分开的两部分。
拦截网络请求
当一个请求的响应不在cache中,就从网络获取,显示到界面上,最后保存到cache中。
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open('mysite-dynamic').then(function(cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request).then(function(response) {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
以上的clone是为了让页面对response的读取与cache对response的读取分离开来,互不影响。
更新cache
总是先更新缓存
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.open('mysite-dynamic').then(function(cache) {
return cache.match(event.request).then(function(response) {
var fetchPromise = fetch(event.request).then(function(networkResponse) {
cache.put(event.request, networkResponse.clone());
return networkResponse;
})
return response || fetchPromise;
})
})
);
});
消息推送
后台同步
只使用缓存
self.addEventListener('fetch', function(event) {
// If a match isn't found in the cache, the response
// will look like a connection error
event.respondWith(caches.match(event.request));
});
只使用网络
self.addEventListener('fetch', function(event) {
event.respondWith(fetch(event.request));
// or simply don't call event.respondWith, which
// will result in default browser behaviour
});
缓存优先,后访问网络
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
})
访问缓存和访问网络同时开始
对于某些情况,古老的硬盘+病毒扫描软件+快速的网络。访问网络的速度可能比访问硬盘更快。
self.addEventListener('fetch', function(event) {
event.respondWith(
promiseAny([
caches.match(event.request),
fetch(event.request)
])
);
});
访问网络失败后才取缓存
self.addEventListener('fetch', function(event) {
event.respondWith(
fetch(event.request).catch(function() {
return caches.match(event.request);
})
);
});
用于资源经常更新的站点,当离线访问时才使用旧的资源。
访问缓存后再访问网络
var networkDataReceived = false; startSpinner(); // fetch fresh data
var networkUpdate = fetch('/data.json').then(function(response) {
return response.json();
}).then(function(data) {
networkDataReceived = true;
updatePage();
}); // fetch cached data
caches.match('/data.json').then(function(response) {
if (!response) throw Error("No data");
return response.json();
}).then(function(data) {
// don't overwrite newer network data
if (!networkDataReceived) {
updatePage(data);
}
}).catch(function() {
// we didn't get cached data, the network is our last hope:
return networkUpdate;
}).catch(showErrorMessage).then(stopSpinner);
generic fallback
self.addEventListener('fetch', function(event) {
event.respondWith(
// Try the cache
caches.match(event.request).then(function(response) {
// Fall back to network
return response || fetch(event.request);
}).catch(function() {
// If both fail, show a generic fallback:
return caches.match('/offline.html');
// However, in reality you'd have many different
// fallbacks, depending on URL & headers.
// Eg, a fallback silhouette image for avatars.
})
);
});
模板
importScripts('templating-engine.js');
self.addEventListener('fetch', function(event) {
var requestURL = new URL(event.request);
event.respondWith(
Promise.all([
caches.match('/article-template.html').then(function(response) {
return response.text();
}),
caches.match(requestURL.path + '.json').then(function(response) {
return response.json();
})
]).then(function(responses) {
var template = responses[0];
var data = responses[1];
return new Response(renderTemplate(template, data), {
headers: {
'Content-Type': 'text/html'
}
});
})
);
});
大概意思就是app shell缓存在本地,然后请求动态数据,两者渲染,得出结果。
将以上的技巧组合到一起
self.addEventListener('fetch', function(event) {
// Parse the URL:
var requestURL = new URL(event.request.url);
// Handle requests to a particular host specifically
if (requestURL.hostname == 'api.example.com') {
event.respondWith(/* some combination of patterns */);
return;
}
// Routing for local URLs
if (requestURL.origin == location.origin) {
// Handle article URLs
if (/^\/article\//.test(requestURL.pathname)) {
event.respondWith(/* some other combination of patterns */);
return;
}
if (/\.webp$/.test(requestURL.pathname)) {
event.respondWith(/* some other combination of patterns */);
return;
}
if (request.method == 'POST') {
event.respondWith(/* some other combination of patterns */);
return;
}
if (/cheese/.test(requestURL.pathname)) {
event.respondWith(
new Response("Flagrant cheese error", {
status: 512
})
);
return;
}
}
// A sensible default pattern
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
完。
《offline coolbook》笔记的更多相关文章
- HTML+CSS笔记 CSS笔记集合
HTML+CSS笔记 表格,超链接,图片,表单 涉及内容:表格,超链接,图片,表单 HTML+CSS笔记 CSS入门 涉及内容:简介,优势,语法说明,代码注释,CSS样式位置,不同样式优先级,选择器, ...
- CSS笔记--选择器
CSS笔记--选择器 mate的使用 <meta charset="UTF-8"> <title>Document</title> <me ...
- HTML+CSS笔记 CSS中级 一些小技巧
水平居中 行内元素的水平居中 </a></li> <li><a href="#">2</a></li> &l ...
- HTML+CSS笔记 CSS中级 颜色&长度值
颜色值 在网页中的颜色设置是非常重要,有字体颜色(color).背景颜色(background-color).边框颜色(border)等,设置颜色的方法也有很多种: 1.英文命令颜色 语法: p{co ...
- HTML+CSS笔记 CSS中级 缩写入门
盒子模型代码简写 回忆盒模型时外边距(margin).内边距(padding)和边框(border)设置上下左右四个方向的边距是按照顺时针方向设置的:上右下左. 语法: margin:10px 15p ...
- HTML+CSS笔记 CSS进阶再续
CSS的布局模型 清楚了CSS 盒模型的基本概念. 盒模型类型, 我们就可以深入探讨网页布局的基本模型了.布局模型与盒模型一样都是 CSS 最基本. 最核心的概念. 但布局模型是建立在盒模型基础之上, ...
- HTML+CSS笔记 CSS进阶续集
元素分类 在CSS中,html中的标签元素大体被分为三种不同的类型:块状元素.内联元素(又叫行内元素)和内联块状元素. 常用的块状元素有: <div>.<p>.<h1&g ...
- HTML+CSS笔记 CSS进阶
文字排版 字体 我们可以使用css样式为网页中的文字设置字体.字号.颜色等样式属性. 语法: body{font-family:"宋体";} 这里注意不要设置不常用的字体,因为如果 ...
- HTML+CSS笔记 CSS入门续集
继承 CSS的某些样式是具有继承性的,那么什么是继承呢?继承是一种规则,它允许样式不仅应用于某个特定html标签元素,而且应用于其后代(标签). 语法: p{color:red;} <p> ...
- HTML+CSS笔记 CSS入门
简介: </span>年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的<span>脚本解释程序</span>,作为ABC语言的一种继承. & ...
随机推荐
- 50 个加速包都抢不到车票,还不如这个 Python 抢票神器!
又到了一年一度的抢票大战,本来就辛苦劳累了一年,想着可以早点订到票跟家里人团聚.所以有挺多的人,宁愿多花些钱去找黄牛买票.但今年各种抢票软件的横行,还有官方出的加速包,导致连黄牛都不敢保证能买到票.你 ...
- 51Nod 1873 初中的算术
大神的字符串快速幂 #include <iostream> #include <string> #include <algorithm> #include < ...
- Linux (二)
PS :显示系统进程 -a :显示所有进程(包括其他用户的进程) -u :用户以及其他详细信息 -x :显示没有控制终端的进程 -ef :显示所有 top :用于动态地监视进程活动与系统负载的信息 p ...
- 牛客寒假5-A.炫酷双截棍
链接:https://ac.nowcoder.com/acm/contest/331/A 题意: 小希现在手里有一个连着的两块木条,长度分别为l1l1,l2l2,木条之间有一个无摩擦的连接点,木条之间 ...
- SpringMVC-高级参数绑定
绑定数组 需求 在商品列表页面选中多个商品,然后删除. 需求分析 此功能要求商品列表页面中的每个商品前有一个checkbook,选中多个商品后点击删除按钮把商品id传递给Controller,根据商品 ...
- python+selenium+requests爬取qq空间相册时遇到的问题及解决思路
最近研究了下用python爬取qq空间相册的问题,遇到的问题及解决思路如下: 1.qq空间相册的访问需要qq登录并且需是好友,requests模块模拟qq登录略显麻烦,所以采用selenium的dri ...
- NUP2201MR
NUP2201MR:双总线保护IC(瞬态抑制二极管),常用于USB总线的保护.
- C++面试中的singleton类
引子 “请写一个Singleton.”面试官微笑着和我说. “这可真简单.”我心里想着,并在白板上写下了下面的Singleton实现: 1 class Singleton 2 { 3 public: ...
- Less的学习和使用
官网 http://less.bootcss.com/usage/ 在线编译器 http://tool.oschina.net/less
- java定时读取文件
在项目中经常会用到定时器,在笔试或者面试中也会经常问到定时器和IO流. public class TimerDemo { public static void main(String[] args) ...