Service Worker 允许基于 URL 对缓存行为进行非常精细的控制 https://web.dev/service-worker-caching-and-http-caching/.
默认情况下,您的PWA(渐进式网络应用程序) https://web.dev/progressive-web-apps/ is 缓存所有资产,包括您的 API 调用 https://web.dev/cache-api-quick-guide/#what-can-be-stored,因此您在使用 Google 身份验证时遇到问题。您必须从缓存中排除特定路由,特别是/api/users/auth/google
.
从你的serviceWorker.js
文件,我注意到你没有处理fetch
事件,通常用于管理缓存和离线支持。
例如参见这个“simple-service-worker/sw.js https://github.com/mdn/dom-examples/blob/e745b9be81c39c5c7a62af96e11aaa55898ce818/service-worker/simple-service-worker/sw.js#L26-L47".
您需要首先实现该部分,以便您可以控制缓存的内容。
In the registerValidSW
函数,之后onupdatefound
事件监听器,添加一个fetch
事件监听器,您可以在其中指定缓存逻辑:
registration.addEventListener('fetch', event => {
const url = new URL(event.request.url);
// Do not handle non-GET requests.
if (event.request.method !== 'GET') {
return;
}
// Ignore /api/users/auth/google route.
if (url.pathname.startsWith('/api/users/auth/google')) {
return;
}
// Here, you can add your logic to handle other requests and caching.
event.respondWith(
caches.match(event.request)
.then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return caches.open(CACHE_NAME)
.then(cache => {
return fetch(event.request).then(response => {
return cache.put(event.request, response.clone()).then(() => {
return response;
});
});
});
})
);
});
在这里,您首先检查该方法是否是GET
。如果不是,请跳过它。
然后,检查请求是否针对/api/users/auth/google
路线。如果是,也跳过它。
对于其他路由,您从缓存中执行获取,如果缓存中不存在,则从网络中获取它,缓存它,然后将其提供给客户端。
(请更换CACHE_NAME
与您打算使用的实际缓存名称)。
理想情况下,该代码应该位于服务工作者文件内(例如,service-worker.js
),它与您的 Web 应用程序使用的主 JavaScript 包是分开的。
我看到你的serviceWorker.js
文件(它似乎是主 JavaScript 包的一部分,因为它导入了其他模块,例如axios
)尝试从以下位置注册一个单独的 Service Workerservice-worker.js
文件。如果您提供的 Service Worker 文件确实是主 JavaScript 包的一部分,那么理想情况下您应该将此 fetch 事件处理代码移至单独的service-worker.js
正在注册为 Service Worker 的文件。该单独的服务工作者文件应该not使用现代 ES6 导入,并且应该以可以用作独立脚本文件的方式编写。您还需要在执行期间处理缓存适当的文件install
and activate
Service Worker 的事件。
再次,service-worker/simple-service-worker/sw.js https://github.com/mdn/dom-examples/blob/e745b9be81c39c5c7a62af96e11aaa55898ce818/service-worker/simple-service-worker/sw.js就是一个很好的例子。
如何强制浏览器在以下情况下调用服务器site_name/api/users/auth/google
在浏览器中输入而不是使用网站的缓存版本?
Service Worker 旨在提供对网页发出的网络请求的控制,允许您拦截这些请求并提供自定义响应,例如在离线时提供缓存的内容。
他们是这样not通常可以通过在浏览器地址栏中输入 URL 来控制导航请求,因为这些请求是在比页面本身更高的级别发出的。
当您处理对应该始终到达服务器(例如 API 端点)的外部 URL 的请求时,您可以明确告诉 Service Worker 绕过缓存并发出网络请求。您可以通过以下方式设置您的fetch
事件侦听器对您提到的 URL 路径执行此操作:
self.addEventListener('fetch', event => {
// Check if the request is for the specific API endpoint
if (event.request.url.endsWith('/api/users/auth/google')) {
// Respond to this request with a network fetch, bypassing the cache
event.respondWith(fetch(event.request));
return;
}
// Handle other requests here, possibly using caches
});
这将设立一个fetch
Service Worker 内部的事件监听器检查请求的 URL 是否以您提到的特定路径结尾。如果是,它会通过网络获取响应请求,绕过任何缓存的内容。其他请求可以以不同的方式处理,可能酌情使用缓存的内容。
注意:请确保URL路径与您请求的完全匹配;相应地调整条件。
这将确保对该特定 URL 的任何请求始终会到达网络,而不是使用缓存的内容。但它不会对直接在地址栏中输入 URL 发出的导航请求产生任何影响,因为这些请求不受 Service Worker 的控制。fetch
事件监听器。
如果您想确保整个页面始终从网络获取,而不是从缓存提供,您可能需要调整服务工作人员使用的整体缓存策略,可能使用NetworkOnly
由一些 Service Worker 库(例如 Workbox)提供的策略。
但是,身份验证的工作方式是,当用户单击“使用 Google 登录”时,它会通过执行以下操作在浏览器中加载身份验证 URL(就好像我直接将其输入到地址栏中一样)window.location.href = "http://example.com/api/users/auth/google";
所以 Service Worker 将无法拦截它。
True:使用重定向整个页面window.location.href
确实会导致不受服务工作人员控制的全页导航请求。
在这种情况下,您可能需要采用不同的策略来处理这些身份验证请求。
例如,而不是直接改变window.location.href
,您可以使用 fetch 或 AJAX 来访问端点。这样,您将发出可以被服务工作者拦截的请求。但是,这对于 OAuth 重定向流程可能会很棘手。
或者,设置时window.location.href
,将唯一的缓存清除参数附加到 URL。这将使每个请求都是唯一的,因此不会从缓存中提供服务。
window.location.href = `http://example.com/api/users/auth/google?timestamp=${new Date().getTime()}`;
确保您的服务器为 URL 设置了适当的 Cache-Control 标头,指示不应缓存该请求。该标头将建议服务工作人员不要缓存此请求。
Cache-Control: no-store
如果您使用像 Workbox 这样的库来控制缓存行为,您可以明确告诉它永远不要缓存某些 URL。不过,如果您像您的情况一样使用全页导航,这可能不起作用。