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

时间:2016-09-11 03:59:38

标签: javascript caching service-worker

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

我看到的选项:  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

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

5 个答案:

答案 0 :(得分:3)

我阅读了sw-toolbox docs,并想出了如何做到这一点。只需将其添加到我的运行时缓存中:

// cache fonts hosted on google CDN
global.toolbox.router.get(/googleapis/, global.toolbox.fastest);

答案 1 :(得分:2)

来自Google Docs

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

所以这样的代码:

var CACHE_NAME = 'my-site-cache-v1';
var urlsToPrefetch = [
  '/',
  '/styles/main.css',
  '/script/main.js'
];

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.');
        });
      })
  );
});

正如OP所说,当资源更新时,在这种情况下很难获得最新的副本。

答案 2 :(得分:2)

在service worker中实现缓存时遇到了相同的问题。问题是实际上如何从服务器获取图标。

1.Request是通过主url(来自应用程序)发出的(以黄色突出显示)。 我想这是您要缓存的静态请求。

2。实际通过动态网络请求获取图标(红色突出显示)。

enter image description here

要解决此问题,您需要动态填充缓存(类似这样的内容)-

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
    .then((response)=>{
      if(response){
        return response;
      }
      else{
        return fetch(event.request) // response of requests
        .then((res)=>{
          return caches.open('dynamic') //create dynamic cache
          .then((cache)=>{
            cache.put(event.request.url,res.clone());
            return res;
          })
        })
      }
    })
    .catch(()=>{})
  )
});

答案 3 :(得分:1)

  

我无法看到将请求缓存为服务工作者的方法   响应我的应用域内的网址。

这不正确。主动控制页面的服务工作者将有机会拦截和响应对跨源资源的网络请求;标准fetch事件将触发,event.request.mode将为"cors""no-cors",具体取决于页面请求的上下文。

简而言之,只要服务人员控制页面,当该页面发出任何网络请求时,对于相同或跨源资源,服务工作人员就能够响应fetch事件。

答案 4 :(得分:0)

我可能会错位,但是它跟下面一样简单吗?

  caches.open(version)
  .then(function(cache) {
    return cache.addAll([
      '/',
      'index.html',
      '/css/app.css',
      '/js/app.min.js',
      '/assets/images/logo_target_white.png',
      '/scripts/angular-jwt.min.js',
      '/scripts/ng-file-upload.min.js',

       // this guy here
      'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'
    ]);
  })

使用此方法并在chrome工具中检查我的应用缓存似乎可以正确显示缓存。