Authored by 毕凯

PWA 基本可用

... ... @@ -114,11 +114,12 @@
{{#wechatShare}}
<script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>
{{/wechatShare}}
<script>var STATIC_RESOURCE_HASH = '{{startTime}}';</script>
{{#if devEnv}}
<script>var STATIC_RESOURCE_PATH = '//{{devHost}}:{{port}}';</script>
<script src="//{{devHost}}:{{port}}/libs.js"></script>
<script src="//{{devHost}}:{{port}}/{{module}}.{{page}}.js"></script>
<script src="//{{devHost}}:{{port}}/libs.js?t={{startTime}}"></script>
<script src="//{{devHost}}:{{port}}/{{module}}.{{page}}.js?t={{startTime}}"></script>
{{^}}
<script>var STATIC_RESOURCE_PATH = '//cdn.yoho.cn/yohobuywap-node/{{version}}';</script>
<script src="//cdn.yoho.cn/yohobuywap-node/{{version}}/libs.js?t={{startTime}}" crossorigin="anonymous"></script>
... ...
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js', {scope: '/'}).then(function(registration) {
window.addEventListener('load', function() {
if ('serviceWorker' in navigator) {
const t = window.STATIC_RESOURCE_HASH || '';
const staticServer = window.STATIC_RESOURCE_PATH || '';
navigator.serviceWorker.register(`/sw.js?t=${t}&staticServer=${staticServer}`, {
scope: '/'
}).then(function(registration) {
console.log('SW registered: ', registration);
}).catch(registrationError => {
console.log('SW registration failed: ', registrationError);
});
});
}
}
});
... ...
importScripts('workbox-sw.prod.v2.1.2.js');
var precacheStaticFile = [
'/index.css',
'/common.css',
'/libs.js'
];
var customCacheDomain = [
'cdn.yoho.cn',
'static.yhbimg.com'
]
// 工具函数
function parseQs(str) {
var vars = {},
hashes,
hash,
i;
str = str || '';
if (str) {
hashes = str.split('&');
for (i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars[hash[0]] = hash[1];
}
}
return vars;
};
function iSInCustomCacheDomain(domain) {
var isIn = false;
customCacheDomain.forEach(function(d) {
if (domain.indexOf(d) >= 0) {
isIn = true
}
})
return isIn;
}
var qs = parseQs(self.location.search.substr(1))
// WorkboxSW
var workboxSW = new self.WorkboxSW({
clientsClaim: true,
skipWaiting: true
});
var precacheFile = [
{
url: '/sw.js?t=' + qs.t + '&staticServer=' + qs.staticServer
},
{
url: '/workbox-sw.prod.v2.1.2.js'
}
];
precacheFile = precacheFile.concat(precacheStaticFile.map(function (file) {
// 根据业务自定义资源路径
var url = self.location.protocol + qs.staticServer + file + '?t=' + qs.t;
return {
url: url
}
}));
workboxSW.precache(precacheFile);
// self.addEventListener('install', function(event) {
// event.waitUntil(
// caches.open('common-cache').then(function(cache) {
... ... @@ -11,6 +79,7 @@ importScripts('workbox-sw.prod.v2.1.2.js');
// });
self.addEventListener('error', event => {
console.error('error', event)
// 上报错误信息
// 常用的属性:
// event.message
... ... @@ -20,58 +89,47 @@ self.addEventListener('error', event => {
// event.error.stack
})
self.addEventListener('unhandledrejection', event => {
console.error('unhandledrejection', event)
// 上报错误信息
// 常用的属性:
// event.reason
})
self.addEventListener('fetch', function (event) {
console.log(event.request);
event.respondWith(
caches.match(event.request).then(function (response) {
// 来来来,代理可以搞一些代理的事情
// 如果 Service Worker 有自己的返回,就直接返回,减少一次 http 请求
if (response) {
return response;
}
// 如果 service worker 没有返回,那就得直接请求真实远程服务
let request = event.request.clone(); // 把原始请求拷过来
var domain = event.request.url.split('/')[2];
var shouldCache = iSInCustomCacheDomain(domain);
return fetch(request).then(function (httpRes) {
// http请求的返回已被抓到,可以处置了。
// 请求失败了,直接返回失败的结果就好了。。
if (!httpRes || httpRes.status !== 200) {
return httpRes;
// 使用域名白名单进行缓存
if (shouldCache) {
event.respondWith(
caches.match(event.request).then(function (response) {
// 如果 Service Worker 有自己的返回,就直接返回,减少一次 http 请求
if (response) {
return response;
}
// 请求成功的话,将请求缓存起来。
let responseClone = httpRes.clone();
// 如果 service worker 没有返回,那就得直接请求真实远程服务
let request = event.request.clone(); // 把原始请求拷过来
console.log(httpRes)
caches.open('custom-cache').then(function (cache) {
cache.put(event.request, responseClone);
});
return fetch(request, {
mode: 'cors',
credentials: 'same-origin'
}).then(function (httpRes) {
// 请求失败了,直接返回失败的结果就好了。。
if (!httpRes || httpRes.status !== 200) {
return httpRes;
}
return httpRes;
}).catch(console.error);
})
);
});
// 请求成功的话,将请求缓存起来。
let responseClone = httpRes.clone();
const workboxSW = new self.WorkboxSW({
clientsClaim: true,
skipWaiting: true
});
caches.open('custom-cache').then(function (cache) {
cache.put(event.request, responseClone);
});
workboxSW.precache([
{
"url": "/sw.js"
},
{
"url": "/workbox-sw.prod.v2.1.2.js"
}
]);
return httpRes;
}).catch(console.error);
})
);
}
});
... ...