web-dev-qa-db-ja.com

Service Workerを使用して外部URLをキャッシュするにはどうすればよいですか?

私はGoogle Web Starter Kit( https://github.com/google/web-starter-kit )で遊んでいて、少しプログレッシブWebアプリが機能しているのに1つのことにこだわっています:外部CDNからの静的ファイルのキャッシュ。例えば。 https://fonts.googleapis.com/icon?family=Material+Icons のMDLアイコンを使用しています。ServiceWorkerはURLにのみ応答するため、リクエストをキャッシュする方法がわかりませんアプリドメイン内。

表示されるオプション:1.ファイルをダウンロードし、ベンダーフォルダーに配置します。利点:SWキャッシュを簡単に設定できます。短所:新しいアイコンが追加されても、ファイルは最新の状態に保たれません(ただし、コードでは使用可能なアイコンのみを使用するため、実際には問題になりません)。

  1. NPMリポジトリを使用: 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が可能かどうかを知るのはクールです。

15
jeznag

sw-toolbox docs を読んで、その方法を理解しました。これを私の実行時キャッシングに追加する必要がありました:

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

TLDR:オプション3を試してください。後で感謝します。

Google Docs から:

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

OPが言ったように、リソースが更新されると、このシナリオでは最新のコピーを取得するのは困難です。もう1つの問題は、先ほど述べたように、応答が成功したかどうかはわかりません。

オプション2

またはOPが言ったように、プロキシサーバーを作成できます:(Pseudocode、not not 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);
});

そして、あなたが行くとき/library?thirdPartyUrl=https://fonts.googleapis.com/icon?family=Material+Iconsは応答を提供し、通常は応答をキャッシュする方法でキャッシュする必要があります。例:削除no-corsurlsToPrefetchを以下の値に置き換えます:

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

オプション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],
      })
    ]
  })
);
4
Asim K T

Service Workerはアプリドメイン内のURLにのみ応答するため、リクエストをキャッシュする方法がわかりません。

不正解です。ページをアクティブに制御しているサービスワーカーは、クロスオリジンリソースに対するネットワークリクエストを傍受して応答する機会があります。標準のfetchイベントが発生し、 event.request.mode は、によって行われたリクエストのコンテキストに応じて、"cors"または"no-cors"になりますページ。

つまり、ページを制御するService Workerがある限り、そのページが同じリソースまたはCross-Originリソースに対してネットワークリクエストを行うと、Service Workerはfetchに応答できます。イベント。

2
Jeff Posnick

ずれているかもしれませんが、次のように簡単ですか?

  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ツールでアプリのキャッシュを検査すると、適切にキャッシュされているように見えます。

0
karns