sw.js
4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
var sw = {
cacheName: "",
cache: function (req, res) {
return caches.open(this.cacheName).then(function (cache) {
return cache.put(req, res);
});
},
precache: function (files) {
return caches.open(this.cacheName).then(function (cache) {
return cache.addAll(files);
});
},
fromCache: function (request) {
return caches.open(this.cacheName).then(function (cache) {
return cache.match(request).then(function (res) {
if (res) { // 使用缓存
return Promise.resolve(res);
}
// 清理过期缓存 同时走网络请求获取新的资源
sw.delExpiredCache(cache, request);
return Promise.reject("no match");
});
});
},
delExpiredCache: function (cache, request) {
var url = new URL(request.url);
return cache.keys().then(function (keys) {
keys.every(function (req) {
var rUrl = new URL(req.url);
// 版本变更, 删除旧缓存
if (req.url != request.url && url.pathname === rUrl.pathname && url.search !== rUrl.search) {
cache.delete(req);
return false;
}
return true;
});
});
},
fromNetwork: function (request) {
return fetch(request);
},
matchRoute: function (request) {
var routes = this.routes;
var nocaches = this.nocaches;
var ismatch = false;
routes.every(function (route) {
// 匹配路由的同时 需要不匹配不缓存项
ismatch = !!request.url.match(route) && !request.url.match(nocaches);
return !ismatch;
});
return ismatch;
},
on: function (evtName, cb) {
self.addEventListener(evtName, cb);
},
/**
* settings
* - precache []
*/
init: function (cacheName, settings) {
var precache = settings.precache || [];
this.cacheName = cacheName;
this.routes = settings.routes;
this.nocaches = settings.nocaches;
// 预缓存
this.on("install", function (evt) {
evt.waitUntil(
sw.precache(precache).then(function () {
// 让sw跳过install阶段进入active
return self.skipWaiting();
})
);
});
// 监听请求 使用缓存并及时更新
this.on("fetch", function (evt) {
var request = evt.request;
if (!sw.matchRoute(request)) return;
evt.respondWith(
sw.fromCache(request).catch(function () {
return sw.fromNetwork(request).then(function (response) {
sw.cache(request, response);
return Promise.resolve(response.clone());
});
})
);
});
this.on("activate", function (evt) {
evt.waitUntil(self.clients.claim());
});
}
};
var CACHE_NAME = "mobilemode-cache";
sw.init(CACHE_NAME, {
routes: [/\/mobilemode\/mobile\/.*\.(html|js[^p]|css)/g],
nocaches: /.*nocache|demo\/.*?\.html|view\.html.*?$/g, // 针对含nocache参数和demo中的html不进行缓存
precache: [""]
});
/** 用于接受消息 */
self.addEventListener('message', function (e) {
var data = e.data;
var cmd = data.command;
switch (cmd) {
case "report":
reporting().then(function (data) {
e.ports[0].postMessage({ data: data });
});
break;
default:
}
});
/** 生成缓存报表 */
function reporting() {
return caches.open(CACHE_NAME).then(function (cache) {
return cache.keys().then(function (reqs) {
return Promise.all(
reqs.map(function (req) {
return cache.match(req).then(function (res) {
var h = res.headers;
var url = new URL(res.url);
return {
url: res.url,
pathname: url.pathname,
size: h.get("Content-Length"),
lastModified: new Date(h.get("date"))
};
});
})
);
});
});
}