我有一个单页应用程序,正在注册服务人员。注册、安装和激活工作正常。
Fetch 没有。它永远不会着火。我猜测这是因为 SPA 使用子域 (api.mydomain.com) 来进行 API 调用,并且服务工作线程注册为 app.mydomain.com。
所以...
Service Worker 注册
<script>
// ServiceWorker is a progressive technology. Ignore unsupported browsers
if ("serviceWorker" in navigator) {
navigator.serviceWorker
.register("./src/sw.js")
.then(function (registration) {
console.log("Yay, service worker registered", registration);
})
.catch(function (err) {
console.log("Noooo, sevice worker didnt register", err);
});
}
</script>
服务人员档案
var precacheVersion = 22;
var precacheName = "precache-v" + precacheVersion;
var precacheFiles = ["/assets/offline.html"];
self.addEventListener("install", function (e) {
console.log("[ServiceWorker] Installed");
self.skipWaiting();
e.waitUntil(
caches.open(precacheName).then(function (cache) {
console.log("[ServiceWorker] Precaching files");
return cache.addAll(precacheFiles);
})
); // end e.waitUntil
});
self.addEventListener("activate", function (e) {
console.log("[ServiceWorker] Activated");
e.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.map(function (thisCacheName) {
if (
thisCacheName.indexOf("precache") !== -1 &&
thisCacheName !== precacheName
) {
console.log(
"[ServiceWorker] Removing cached files from old cache - ",
thisCacheName
);
return caches.delete(thisCacheName);
}
})
);
})
); // end e.waitUntil
});
self.addEventListener("fetch", function (e) {
console.log("[ServiceWorker] Fetch event for ");
e.respondWith(
caches.match(e.request).then(function (cacheResponse) {
if (cacheResponse) {
console.log("Found in cache!");
return cacheResponse;
}
return fetch(e.request)
.then(function (fetchResponse) {
return fetchResponse;
})
.catch(function (err) {
var isHTMLPage =
e.request.method == "GET" &&
e.request.headers.get("accept").includes("text/html");
if (isHTMLPage) {
return caches.match("/assets/offline.html");
}
});
})
);
});
您致电
navigator.serviceWorker.register("./src/sw.js")
。这意味着您的整个站点现在由您的服务人员处理,对吗?
可悲的是,事情没那么简单。如果您调用
register()
时未在可选 options
参数中指定范围,则 Service Worker 的位置将成为其范围。根据MDN,
默认情况下,Service Worker 注册的
值设置为 Service Worker 脚本所在的目录(通过解析scope
与./
)。scriptURL
那么“范围”是什么意思?
代表 URL 的字符串,定义 Service Worker 的注册范围;也就是说,Service Worker 可以控制的 URL 范围。
因此,如果您的脚本托管在
app.mydomain.com
上并位于相对 URL src/sw.js
,则意味着它只能处理 app.mydomain.com/src
下的请求,这可能不是您想要的。我只能假设您的 fetch()
调用是直接对 app.mydomain.com
进行的,这超出了您的 Service Worker 的范围。
那么,如何解决这个问题呢?
sw.js
文件直接托管在服务器的根目录下,并使用 navigator.serviceWorker.register("./sw.js")
注册您的 Service Worker。当然,这是一个简单的修复,但您可能希望所有脚本文件都位于 src/
目录下以保持一致性。register
,如下所示:
navigator.serviceWorker.register("./src/sw.js", {
scope: "app.domain.com" // could be a relative URL
})
这样,范围就明确设置为站点的根目录,现在每个获取请求都应该通过您的服务工作线程。