web-dev-qa-db-fra.com

Comment mettre en cache des URL externes à l'aide de Service Worker?

J'ai joué avec le Google Web Starter Kit ( https://github.com/google/web-starter-kit ) et j'ai une petite application web progressive qui fonctionne mais je suis coincé sur une chose : mise en cache de fichiers statiques à partir de CDN externes. Par exemple. J'utilise des icônes MDL de https://fonts.googleapis.com/icon?family=Material+Icons Je ne vois pas de moyen de mettre en cache la demande car le technicien ne répond qu'aux URL au sein de mon domaine d'application.

Options que je vois: 1. Téléchargez le fichier et placez-le dans un dossier fournisseur. Avantages: configuration facile du cache SW. Inconvénients: le fichier ne restera pas à jour lorsque de nouvelles icônes sont ajoutées (bien que cela n'ait pas vraiment d'importance car mon code utilisera uniquement les icônes disponibles).

  1. Utilisez le référentiel NPM: https://www.npmjs.com/package/material-design-icons et utilisez l'étape de génération pour copier le fichier CSS à partir de node_modules. Avantages: permettra la mise à jour automatique depuis NPM. Inconvénients: un peu plus complexe à mettre en place.

  2. Une méthode de proxy sophistiquée qui me permettrait d'utiliser le SW pour mettre en cache une URL externe. par exemple. myapp.com/loadExternal?url= https://fonts.googleapis.com/icon?family=Material+Icons

Je penche vers 2 en ce moment mais ce serait cool de savoir si 3 est possible.

15
jeznag

J'ai lu les documents sw-toolbox et compris comment le faire. Juste eu à ajouter cela à ma mise en cache d'exécution:

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

TLDR: Essayez Option 3. Tu me remercieras plus tard.

De Google Docs :

Par défaut, la récupération d'une ressource à partir d'une URL tierce échouera si elle ne prend pas en charge CORS. Vous pouvez ajouter un no-CORS option à la demande pour résoudre ce problème, bien que cela provoquera une réponse "opaque", ce qui signifie que vous ne pourrez pas dire si la réponse a réussi ou non.

Alors

Option 1

Ajouter no-cors entête

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

Comme OP l'a dit, lorsque la ressource est mise à jour, il est difficile d'obtenir la dernière copie dans ce scénario. Et un autre problème est, comme je l'ai dit, vous ne saurez pas si la réponse a été un succès ou non.

Option 2

Ou comme OP l'a dit, nous pouvons créer un serveur proxy: quelque chose de simple comme (Pseudocode, non testé, Node Express code)

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

Et quand tu vas /library?thirdPartyUrl=https://fonts.googleapis.com/icon?family=Material+Icons devrait vous donner la réponse et la mettre en cache comme d'habitude nous mettons en cache notre réponse. Pour Ex: supprimez no-cors & remplacez urlsToPrefetch par la valeur ci-dessous:

var urlsToPrefetch = [
      '/',
      '/library?thirdPartyUrl=https://fonts.googleapis.com/icon?family=Material+Icons',
      '/library?thirdPartyUrl=https://fonts.googleapis.com/icon?family=Roboto'
    ];

Option 3

Je pense que c'est la meilleure façon et la plus simple. Utilisez la boîte de travail. Nous avons essayé de créer PWA avec et sans workbox et l'utilisation de workbox était simple.

En savoir plus sur la boîte de travail: https://developers.google.com/web/tools/workbox/

Implémentez un itinéraire comme celui-ci après la configuration initiale:

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],
      })
    ]
  })
);
4
Asim K T

Je ne vois aucun moyen de mettre en cache la demande, car le technicien de service ne répond qu'aux URL de mon domaine d'application.

Ce n'est pas correct. Un technicien qui contrôle activement une page aura la possibilité d'intercepter et de répondre aux demandes du réseau pour les ressources cross-Origin; l'événement standard fetch se déclenchera et event.request.mode sera soit "cors" ou "no-cors", selon le contexte de la demande faite par la page.

En bref, tant qu'il y a un technicien de service qui contrôle une page, lorsque cette page fait une demande réseau, pour une ressource d'origine identique ou croisée, le technicien de service sera en mesure de répondre à la fetch un événement.

2
Jeff Posnick

Je suis peut-être mal aligné, mais est-ce aussi simple que ce qui suit?

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

L'utilisation de cette méthode et l'inspection du cache de mon application dans chrome semblent le montrer correctement en cache.

0
karns