如何使用服务工作者缓存外部URL?

jez*_*nag 13 javascript caching service-worker

我一直在使用Google网络入门套件(https://github.com/google/web-starter-kit)并且有一个小小的渐进式网络应用程序正在运行,但我坚持一件事:从外部CDN缓存静态文件.例如,我正在使用来自https://fonts.googleapis.com/icon?family=Material+Icons的 MDL图标我看不到缓存请求的方法,因为服务工作者仅响应我的应用程序域中的URL.

我看到的选项:1.下载文件并将其放在供应商文件夹中.优点:易于设置SW缓存.缺点:文件不会随着新图标的添加而保持最新状态(尽管这并不重要,因为我的代码只会使用可用的图标).

  1. 使用NPM repo:https://www.npmjs.com/package/material-design-icons并使用构建步骤从node_modules复制CSS文件.优点:允许从NPM自动更新.缺点:设置稍微复杂一些.

  2. 一些花哨的代理方法,允许我使用SW来缓存外部URL.例如myapp.com/loadExternal?url= https://fonts.googleapis.com/icon?family=Material+Icons

我现在正倾向于2,但知道3是否可能会很酷.

Asi*_*K T 10

TLDR:尝试选项 3。以后你会感谢我的。

来自谷歌文档

默认情况下,如果不支持 CORS,则从第三方 URL 获取资源将失败。您可以no-CORS在请求中添加一个选项来解决这个问题,尽管这会导致“不透明”响应,这意味着您将无法判断响应是否成功。

所以

选项1

添加no-cors标题

var CACHE_NAME = 'my-site-cache-v1';
var urlsToPrefetch = [
  '/',
  '/styles/main.css',
  '/script/main.js',
  'https://fonts.googleapis.com/icon?family=Material+Icons'
];

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        // Magic is here. Look the  mode: 'no-cors' part.
        cache.addAll(urlsToPrefetch.map(function(urlToPrefetch) {
           return new Request(urlToPrefetch, { mode: 'no-cors' });
        })).then(function() {
          console.log('All resources have been fetched and cached.');
        });
      })
  );
});
Run Code Online (Sandbox Code Playgroud)

正如OP所说,当资源更新时,在这种情况下很难获得最新的副本。另一个问题是,正如我所说,您不会知道响应是否成功。

选项 2

或者像 OP 所说的,我们可以创建一个代理服务器:一些简单的东西(伪代码,未测试,Node Express 代码)

var request = require('request');
app.get('/library', function(req,res) {
  // read the param 
  var thirdPartyUrl = req.query.thirdPartyUrl;
  request(thirdPartyUrl).pipe(res);
});
Run Code Online (Sandbox Code Playgroud)

当你 goto/library?thirdPartyUrl=https://fonts.googleapis.com/icon?family=Material+Icons应该给你响应并缓存它时我们通常缓存我们的响应。例如:删除no-cors并替换urlsToPrefetch为以下值:

var urlsToPrefetch = [
      '/',
      '/library?thirdPartyUrl=https://fonts.googleapis.com/icon?family=Material+Icons',
      '/library?thirdPartyUrl=https://fonts.googleapis.com/icon?family=Roboto'
    ];
Run Code Online (Sandbox Code Playgroud)

选项 3

我认为这是最好和更简单的方法。使用工作箱。我们尝试使用和不使用工作箱来创建 PWA,使用工作箱很简单。

阅读工作箱:https : //developers.google.com/web/tools/workbox/

在初始设置后实现这样的路由:

workbox.routing.registerRoute(
  new RegExp('^https://third-party.example.com/images/'),
  new workbox.strategies.CacheFirst({
    cacheName: 'image-cache',
    plugins: [
      new workbox.cacheableResponse.Plugin({
        statuses: [0, 200],
      })
    ]
  })
);
Run Code Online (Sandbox Code Playgroud)

  • 似乎没有获取外部/第 3 方资源的示例,您能否在示例中添加该示例? (3认同)

jez*_*nag 4

我阅读了sw-toolbox 文档并弄清楚了如何做到这一点。只需将其添加到我的运行时缓存中:

// cache fonts hosted on google CDN
global.toolbox.router.get(/googleapis/, global.toolbox.fastest);
Run Code Online (Sandbox Code Playgroud)

  • 您可能想使用 Workbox,它是 sw-toolbox 和 sw-precache 的后继者:https://developers.google.com/web/ilt/pwa/lab-migration-to-workbox-from-sw-precache-和-sw-工具箱 (4认同)