如果文件由Service Worker管理,则绕过默认缓存策略

时间:2018-07-03 13:35:36

标签: service-worker workbox

我正在使用Google的workbox-cli工具来在网站上预缓存一些文件。默认情况下是否可以将网络服务器设置为在所有文件的HTTP响应标头中返回以下内容:

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

因此,我希望服务工作者在预先缓存文件之前,将Web服务器的响应标头中的max-age=86400更改为max-age=0。这使得服务工作者可以从Web服务器获取根据sw.js中的修订而更改的文件,而不是从本地缓存中获取文件。默认情况下,任何不受服务工作者管理的文件都会被缓存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 Web服务器上,默认情况下会传递以下HTTP标头:

more_set_headers "cache-control: s-maxage=2592000, max-age=0, must-revalidate, no-transform, public";

但是,如果服务工作者未处理请求的资源,则默认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";
}

当前方法存在的问题(请参阅背景信息)

  1. 我必须跟踪文件并相应地更新nginx.conf
  2. max-age=0也用于不支持服务人员的Web浏览器。因此,每次访问页面时,他们都会向网络服务器请求资源。

第一次更新

我期望的预缓存行为可以用两个workbox strategies来说明。我希望服务人员显示场景1和2中描述的以下行为,尽管cache-control: max-age=86400是由Web服务器在资产(例如default.js)的HTTP标头中传递的。

方案1:sw.js中的修订未更改

已访问该网页,由于sw.js而从网络服务器检索了max-age=0文件,并且网络浏览器注意到default.js的修订没有更改。在这种情况下,default.js是从预缓存缓存中检索的:

enter image description here

方案2:sw.js中的修订确实发生了更改

已访问网页,由于sw.js,从网络服务器检索了max-age=0文件,并且网络浏览器注意到default.js的修订已更改。在这种情况下,default.js是从Web服务器检索的:

enter image description here

第二次更新

基本上,所需的策略类似于network-first strategy。但是,只有在sw.js中文件的修订已更改的情况下,才执行步骤2。

enter image description here

第三次更新

如果我没记错的话,上面已经有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' })
      ]))
  );
});

2 个答案:

答案 0 :(得分:0)

我认为您对服务人员的实际工作方式没有足够的了解。

您定义一个或多个缓存供服务人员使用。您可以指定要在哪个缓存中进行缓存,是否缓存将来的请求等

现在,服务工作程序会拦截来自客户端的所有网络请求,然后对它们进行响应,无论您已对其进行了编程。它可以返回缓存的内容(如果可用),在通过网络进行更新时首先缓存的内容,在没有连接的情况下首先在网络上复制到缓存,缓存图像但不缓存其他任何内容,仅缓存GET请求,仅缓存某些域,文件类型等...

它缓存的内容以及每个缓存有效的时间完全取决于您,完全不受服务器响应标头的影响。如果您告诉服务人员对资源进行提取请求,则它将通过网络加载该资源,而不管任何标头或本地已缓存的内容。

您可以完全控制整个缓存过程,这非常有用,但是有其自身的陷阱。

答案 1 :(得分:0)

我在s-max-age HTTP标头中使用了s-maxage而不是cache-control,这导致了我的反向代理和工作箱服务工作者的意外行为。修复后,服务人员正在按预期工作。