如果文件由 service worker 管理,则绕过默认缓存策略
Bypass default caching policy if file is managed by service worker
我正在使用 Google 的 workbox-cli
工具来预缓存我网站上的一些文件。是否可以将网络服务器设置为 return 默认情况下所有文件的 HTTP 响应 header 中的以下内容:
cache-control: s-maxage=2592000, max-age=86400, must-revalidate, no-transform, public
但是,只有当服务工作者要预缓存文件时,让网络浏览器使用以下内容:
cache-control: s-maxage=2592000, max-age=0, must-revalidate, no-transform, public
所以,我希望 service worker 在预缓存文件之前将网络服务器的响应 header 中的 max-age=86400
更改为 max-age=0
。这使得服务工作者从网络服务器获取文件,这些文件根据 sw.js
中的修订而更改,而不是从本地缓存中检索它们。默认情况下,任何不由 Service Worker 管理的文件都会缓存 86400 秒。
一些背景信息
目前,我正在使用以下 bash 脚本来设置我的 sw.js
:
#!/bin/bash
if [ ! -d /tmp/workbox-configuration ]; then
mkdir /tmp/workbox-configuration
fi
cat <<EOF > /tmp/workbox-configuration/workbox-config.js
module.exports = {
"globDirectory": "harp_output/",
"globPatterns": [
EOF
( cd harp_output && find assets de en -type f ! -name "map.js" ! -name "map.json" ! -name "markerclusterer.js" ! -name "modal.js" ! -name "modal-map.html" ! -name "service-worker-registration.js" ! -name "sw-registration.js" ! -path "assets/fonts/*" ! -path "assets/img/*-1x.*" ! -path "assets/img/*-2x.*" ! -path "assets/img/*-3x.*" ! -path "assets/img/maps/*" ! -path "assets/img/video/*_1x1.*" ! -path "assets/img/video/*_4x3.*" ! -path "assets/js/workbox-*" ! -path "assets/videos/*" ! -path "de/4*" ! -path "de/5*" ! -path "en/4*" ! -path "en/5*" | sort | sed 's/^/"/' | sed 's/$/"/' | sed -e '$ ! s/$/,/' >> /tmp/workbox-configuration/workbox-config.js )
cat <<EOF >> /tmp/workbox-configuration/workbox-config.js
],
"swDest": "/tmp/workbox-configuration/sw.js"
};
EOF
workbox generateSW /tmp/workbox-configuration/workbox-config.js
sed -i 's#^importScripts(.*);$#importScripts("/assets/js/workbox-sw.js");\nworkbox.setConfig({modulePathPrefix: "/assets/js/"});#' /tmp/workbox-configuration/sw.js
sed -i 's/index.html"/"/' /tmp/workbox-configuration/sw.js
uglifyjs /tmp/workbox-configuration/sw.js -c -m -o harp_output/sw.js
在我的 Nginx 网络服务器上,默认传送以下 HTTP header:
more_set_headers "cache-control: s-maxage=2592000, max-age=0, must-revalidate, no-transform, public";
但是,如果请求的资源没有被 service worker 处理,默认的 cache-control
设置将被覆盖:
location ~ ^/(assets/(data/|fonts/|img/(.*-(1|2|3)x\.|maps/|video/.*_(1x1|4x3)\.)|js/(map|markerclusterer|modal|service-worker-registration|sw-registration)\.js|videos/)|(de|en)/((4|5).*|modal-map\.html)) {
more_set_headers "cache-control: s-maxage=2592000, max-age=86400, must-revalidate, no-transform, public";
}
当前方法存在问题(参见背景信息)
- 我必须跟踪文件并相应地更新
nginx.conf
。
max-age=0
也用于不支持 service-workers 的网络浏览器。因此,他们在每次访问页面时都从网络服务器请求资源。
第一次更新
我想要的预缓存行为可以用 workbox strategies 中的两个来说明。我希望 service worker 显示场景 1 和场景 2 中描述的以下行为,尽管 cache-control: max-age=86400
是由网络服务器在 HTTP header 中为资产(例如 default.js
)提供的。
情况 1:sw.js 中的修订没有更改
访问网页,由于 max-age=0
从网络服务器检索 sw.js
文件,网络浏览器注意到 default.js
的修订没有改变。在这种情况下,default.js
从预缓存缓存中检索:
场景 2:sw.js 中的修订确实发生了变化
访问网页,由于 max-age=0
从网络服务器检索 sw.js
文件,网络浏览器注意到 default.js
的修订已更改。在这种情况下,default.js
是从网络服务器检索到的:
第二次更新
基本上,所需的策略类似于 network-first strategy。但是,仅当 sw.js
中的文件修订已更改时才执行第 2 步。
第三次更新
如果我没记错的话,这个上面已经有some work了:
self.addEventListener('install', event => {
event.waitUntil(
caches.open(`static-${version}`)
.then(cache => cache.addAll([
new Request('/styles.css', { cache: 'no-cache' }),
new Request('/script.js', { cache: 'no-cache' })
]))
);
});
我认为您对 Service Worker 的实际工作方式了解不够全面。
您定义一个或多个缓存供服务工作者使用。您指定缓存中的内容,是否缓存未来的请求等
Service Worker 现在会拦截来自客户端的所有网络请求,然后按照您编程的方式响应它们。它可以 return 缓存内容(如果可用),在通过网络更新时先缓存内容,在没有连接的情况下先网络并复制到缓存,缓存图像但不缓存其他任何内容,仅缓存 GET 请求,仅缓存某些域、文件类型等......
它缓存什么以及每个缓存的有效时间完全取决于您,完全不受服务器响应的影响 headers。如果你告诉你的 service worker 对资源发出获取请求,那么它会通过网络加载该资源,而不管任何 headers 或已经在本地缓存的内容。
您可以完全控制整个缓存过程,这非常有用,但也有一些缺陷。
我在 cache-control
HTTP header 中使用 s-max-age
而不是 s-maxage
,这导致我的反向代理和工作箱服务工作者出现一些意外行为。修复后,Service Worker 按预期工作。
我正在使用 Google 的 workbox-cli
工具来预缓存我网站上的一些文件。是否可以将网络服务器设置为 return 默认情况下所有文件的 HTTP 响应 header 中的以下内容:
cache-control: s-maxage=2592000, max-age=86400, must-revalidate, no-transform, public
但是,只有当服务工作者要预缓存文件时,让网络浏览器使用以下内容:
cache-control: s-maxage=2592000, max-age=0, must-revalidate, no-transform, public
所以,我希望 service worker 在预缓存文件之前将网络服务器的响应 header 中的 max-age=86400
更改为 max-age=0
。这使得服务工作者从网络服务器获取文件,这些文件根据 sw.js
中的修订而更改,而不是从本地缓存中检索它们。默认情况下,任何不由 Service Worker 管理的文件都会缓存 86400 秒。
一些背景信息
目前,我正在使用以下 bash 脚本来设置我的 sw.js
:
#!/bin/bash
if [ ! -d /tmp/workbox-configuration ]; then
mkdir /tmp/workbox-configuration
fi
cat <<EOF > /tmp/workbox-configuration/workbox-config.js
module.exports = {
"globDirectory": "harp_output/",
"globPatterns": [
EOF
( cd harp_output && find assets de en -type f ! -name "map.js" ! -name "map.json" ! -name "markerclusterer.js" ! -name "modal.js" ! -name "modal-map.html" ! -name "service-worker-registration.js" ! -name "sw-registration.js" ! -path "assets/fonts/*" ! -path "assets/img/*-1x.*" ! -path "assets/img/*-2x.*" ! -path "assets/img/*-3x.*" ! -path "assets/img/maps/*" ! -path "assets/img/video/*_1x1.*" ! -path "assets/img/video/*_4x3.*" ! -path "assets/js/workbox-*" ! -path "assets/videos/*" ! -path "de/4*" ! -path "de/5*" ! -path "en/4*" ! -path "en/5*" | sort | sed 's/^/"/' | sed 's/$/"/' | sed -e '$ ! s/$/,/' >> /tmp/workbox-configuration/workbox-config.js )
cat <<EOF >> /tmp/workbox-configuration/workbox-config.js
],
"swDest": "/tmp/workbox-configuration/sw.js"
};
EOF
workbox generateSW /tmp/workbox-configuration/workbox-config.js
sed -i 's#^importScripts(.*);$#importScripts("/assets/js/workbox-sw.js");\nworkbox.setConfig({modulePathPrefix: "/assets/js/"});#' /tmp/workbox-configuration/sw.js
sed -i 's/index.html"/"/' /tmp/workbox-configuration/sw.js
uglifyjs /tmp/workbox-configuration/sw.js -c -m -o harp_output/sw.js
在我的 Nginx 网络服务器上,默认传送以下 HTTP header:
more_set_headers "cache-control: s-maxage=2592000, max-age=0, must-revalidate, no-transform, public";
但是,如果请求的资源没有被 service worker 处理,默认的 cache-control
设置将被覆盖:
location ~ ^/(assets/(data/|fonts/|img/(.*-(1|2|3)x\.|maps/|video/.*_(1x1|4x3)\.)|js/(map|markerclusterer|modal|service-worker-registration|sw-registration)\.js|videos/)|(de|en)/((4|5).*|modal-map\.html)) {
more_set_headers "cache-control: s-maxage=2592000, max-age=86400, must-revalidate, no-transform, public";
}
当前方法存在问题(参见背景信息)
- 我必须跟踪文件并相应地更新
nginx.conf
。 max-age=0
也用于不支持 service-workers 的网络浏览器。因此,他们在每次访问页面时都从网络服务器请求资源。
第一次更新
我想要的预缓存行为可以用 workbox strategies 中的两个来说明。我希望 service worker 显示场景 1 和场景 2 中描述的以下行为,尽管 cache-control: max-age=86400
是由网络服务器在 HTTP header 中为资产(例如 default.js
)提供的。
情况 1:sw.js 中的修订没有更改
访问网页,由于 max-age=0
从网络服务器检索 sw.js
文件,网络浏览器注意到 default.js
的修订没有改变。在这种情况下,default.js
从预缓存缓存中检索:
场景 2:sw.js 中的修订确实发生了变化
访问网页,由于 max-age=0
从网络服务器检索 sw.js
文件,网络浏览器注意到 default.js
的修订已更改。在这种情况下,default.js
是从网络服务器检索到的:
第二次更新
基本上,所需的策略类似于 network-first strategy。但是,仅当 sw.js
中的文件修订已更改时才执行第 2 步。
第三次更新
如果我没记错的话,这个上面已经有some work了:
self.addEventListener('install', event => {
event.waitUntil(
caches.open(`static-${version}`)
.then(cache => cache.addAll([
new Request('/styles.css', { cache: 'no-cache' }),
new Request('/script.js', { cache: 'no-cache' })
]))
);
});
我认为您对 Service Worker 的实际工作方式了解不够全面。
您定义一个或多个缓存供服务工作者使用。您指定缓存中的内容,是否缓存未来的请求等
Service Worker 现在会拦截来自客户端的所有网络请求,然后按照您编程的方式响应它们。它可以 return 缓存内容(如果可用),在通过网络更新时先缓存内容,在没有连接的情况下先网络并复制到缓存,缓存图像但不缓存其他任何内容,仅缓存 GET 请求,仅缓存某些域、文件类型等......
它缓存什么以及每个缓存的有效时间完全取决于您,完全不受服务器响应的影响 headers。如果你告诉你的 service worker 对资源发出获取请求,那么它会通过网络加载该资源,而不管任何 headers 或已经在本地缓存的内容。
您可以完全控制整个缓存过程,这非常有用,但也有一些缺陷。
我在 cache-control
HTTP header 中使用 s-max-age
而不是 s-maxage
,这导致我的反向代理和工作箱服务工作者出现一些意外行为。修复后,Service Worker 按预期工作。