我正试图使我的网站脱机工作,但似乎无法正常工作。 我的项目基于node.js以及由angular生成的外部js文件。
这一切似乎都工作正常,当服务器正在运行并且我进入localhost:3000时,service worker安装正确,那么如果我进入Chrome Devtools中的“应用程序”选项卡,然后选中“脱机”,我重新加载页面,它也可以工作。
但是,如果我关闭服务器并重新加载页面,则会在控制台中收到以下错误:An unknown error occurred when fetching the script.
这是我的index.html:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='/stylesheets/style.css' />
<link rel="icon" type="image/x-icon" href="/dist/favicon.ico">
<link href="/dist/assets/fontawesome.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Roboto:100,100i,300,300i,400,400i,500&display=swap" rel="stylesheet">
</head>
<body>
{% block body %}{% endblock %}
</body>
<script src="/client.js"></script>
<script src="/service-worker.js"></script>
<script src="/dist/runtime-es2015.js" type="module"></script>
<script src="/dist/polyfills-es2015.js" type="module"></script>
<script src="/dist/runtime-es5.js" nomodule></script>
<script src="/dist/polyfills-es5.js" nomodule></script>
<script src="/dist/styles-es2015.js" type="module"></script>
<script src="/dist/styles-es5.js" nomodule></script>
<script src="/dist/vendor-es2015.js" type="module"></script>
<script src="/dist/main-es2015.js" type="module"></script>
<script src="/dist/vendor-es5.js" nomodule></script>
<script src="/dist/main-es5.js" nomodule></script>
</body>
</html>
client.js:
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('./service-worker.js')
.then(function() { console.log('Service Worker Registered'); });
}
service-worker.js:
var cacheName = 'myCacheVersion';
var filesToCache = [
'/dist/favicon.ico',
'/dist/runtime-es2015.js',
'/dist/polyfills-es2015.js',
'/dist/runtime-es5.js',
'/dist/polyfills-es5.js',
'/dist/styles-es2015.js',
'/dist/styles-es5.js',
'/dist/vendor-es2015.js',
'/dist/main-es2015.js',
'/dist/vendor-es5.js',
'/dist/main-es5.js',
'/client.js',
'/service-worker.js',
];
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
return cache.addAll(filesToCache);
})
);
});
self.addEventListener('activate', function(e) {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (key !== cacheName) {
console.log('[ServiceWorker] Removing old cache', key);
return caches.delete(key);
}
}));
})
);
return self.clients.claim();
});
self.addEventListener('fetch', function(e) {
console.log('[ServiceWorker] Fetch', e.request.url);
e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
});
对为什么它不起作用有任何想法吗?
答案 0 :(得分:0)
首先:永远不要缓存service-worker.js!从文件中删除它以进行缓存。浏览器具有可用的本地副本,只要浏览器从服务器更新脚本,就会使用该副本。永远不要有理由将脚本放入由SW管理的缓存中。 <script src="/service-worker.js"></script>
这也是您不应该执行的操作。不应通过常规脚本标签包括service-worker.js,而应像在其他文件中那样通过navigator.serviceWorker.register(...)
调用来包括它:)
您收到错误消息,因为浏览器通过Service Worker尝试加载服务器的根目录,并且该根目录不可用。加载会导致一个不可用的错误,并且在yuor Service Worker的缓存中也找不到该错误,因为您没有对其进行缓存(未在要缓存的文件中列出)。
我真的很想知道您提供的这段代码实际上根本不能脱机工作,因为它没有缓存根页。它根本不应该脱机工作-Service Worker不会缓存根,因此离线时应该无法从缓存中获取任何内容。
毫无价值的浏览器没有连接(脱机)和网站不可用(服务器关闭)是两种完全不同的情况。在前者中,SW知道网络不可用,因此在决定如何响应时(如果被告知),可以将其考虑在内。但是,在后者中,浏览器正试图从网络中获取某些信息,而网络本身仍在工作,但目的地本身不可用。这是连接到站点的故障,不是脱机模式。在后一种情况下,SW必须决定如何处理,也许必须回退到offline.html占位符页面,并且最显着的是不缓存响应。