Service Workカー学習と実践(一)——オフラインキャッシュ

10864 ワード

何がService Workerですか?Service Workerは、本質的にはWebアプリケーションとブラウザとの間のプロキシサーバとして機能し、ネットワークが利用可能な場合はブラウザとネットワーク間のプロキシとして機能してもよい.これらは、ネットワーク要求をブロックし、ネットワークが利用可能かどうかおよび更新されたリソースがサーバ上に存在するかどうかに基づいて適切な動作をとるために、有効なオフライン体験を作成することを目的とする.彼らはまた、訪問プッシュ通知とバックグラウンド同期APIを許可する.
  • Service Workerの本質はWeb Workerであり、JavaScriptのメインスレッドから独立しているので、DOMに直接アクセスすることもできず、windowオブジェクトに直接アクセスすることもできない.
  • Service Workerは、navigatorページのすべてのネットワーク要求を制御することができるネットワークエージェントである.
  • JavaScriptは、自身のライフサイクルを持ち、Service Workerを上手に使う鍵は、そのライフサイクルを柔軟に制御することである.
  • Webの役割
  • ブラウザキャッシュ
  • オフラインService Worker
  • を実現します.
  • メッセージプッシュ
  • Service Worker互換性Service Workerは、近代的なブラウザの高機能であり、Web APPService WorkerService Workerなどに依存しており、fetch APIは、Cache Storageオブジェクトペアの記憶メカニズムを提供し、Promiseは複数のCacheを記憶する.
    Request / Responseの原理を理解する前に、セクションCache Storageの例を先に見てみる.
    self.importScripts('./serviceworker-cache-polyfill.js');
    
    var urlsToCache = [
      '/',
      '/index.js',
      '/style.css',
      '/favicon.ico',
    ];
    
    var CACHE_NAME = 'counterxing';
    
    self.addEventListener('install', function(event) {
      self.skipWaiting();
      event.waitUntil(
        caches.open(CACHE_NAME)
        .then(function(cache) {
          return cache.addAll(urlsToCache);
        })
      );
    });
    
    self.addEventListener('fetch', function(event) {
      event.respondWith(
        caches.match(event.request)
        .then(function(response) {
          if (response) {
            return response;
          }
          return fetch(event.request);
        })
      );
    });
    
    
    self.addEventListener('activate', function(event) {
      var cacheWhitelist = ['counterxing'];
    
      event.waitUntil(
        caches.keys().then(function(cacheNames) {
          return Promise.all(
            cacheNames.map(function(cacheName) {
              if (cacheWhitelist.indexOf(cacheName) === -1) {
                return caches.delete(cacheName);
              }
            })
          );
        })
      );
    });
    
    次は段階を追って分析して、Cacheの神秘的なベールを開けます.Service Worker最初の行を参照してください.Service Workerは、ここにCache APIのpolyfillを導入しています.このService Workerは、より低いバージョンのブラウザの下でpolyfillを使用することができるようにサポートしています.self.importScripts('./serviceworker-cache-polyfill.js');の機能を実現するには、一般的には、polyfillプロキシネットワーク要求をキャッシュに組み合わせる必要がある.Cache Storage APIスレッドでは、Service Workerを使用してCache APIスクリプトを導入し、低バージョンブラウザの互換性を目的としている.Service Worker And importScriptsその後、1つのpolyfillリストを使用してキャッシュが必要な静的リソースを宣言し、もう1つの変数Cache Resources Listを使用してキャッシュのCache Nameを決定し、ここではurlsToCacheCACHE_NAMEであり、Cache Storage NameCache Storageであると理解できる.
    var urlsToCache = [
      '/',
      '/index.js',
      '/style.css',
      '/favicon.ico',
    ];
    
    var CACHE_NAME = 'counterxing';
    DBCACHE_NAMEは、ブラウザDBのメインスレッドから独立しており、独自のライフサイクルがある.
    ウェブサイトにLifecycleをインストールする必要がある場合、Service Workerメインスレッドには、以下のコードを使用してJavaScriptを導入する必要がある.
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js').then(function(registration) {
        console.log('    ', registration.scope);
      }).catch(function(err) {
        console.log(err);
      });
    }
    ここで、Service Workerファイルのパスに注意しなければならない.私の例では、現在のドメインルートディレクトリの下にある.これは、JavaScriptとウェブサイトが同じソースであることを意味し、現在のウェブサイトのすべての要求のためにプロキシをすることができ、Service Workerに登録されたら、プロキシsw.jsの下のネットワーク要求しかできない.Service Workerコンソールを使用して、現在のページのService Worker状況を確認できます.
    インストールが完了したら、/imaging/sw.jsは次のライフサイクルを経験します.
  • ダウンロード(/imaging)
  • インストール(Chrome)
  • 起動(Service Worker)
  • ユーザが初めてService Workerが制御するウェブサイトまたはページにアクセスすると、downloadはすぐにダウンロードされる.その後少なくともinstall時間ごとにダウンロードされます.もっと頻繁にダウンロードされるかもしれませんが、activate時間ごとに必ず一回ダウンロードされます.
  • はダウンロードが完了した後、Service Workerのインストールを開始します.インストール段階では、通常、私たちがあらかじめ宣言している静的リソースをキャッシュする必要があります.
  • はインストールが完了すると、起動されます.ブラウザはService Workerスクリプトファイルをダウンロードしようとします.ダウンロードが成功すると、前回キャッシュされた24スクリプトファイルと比較します.前回の24スクリプトファイルと違って、Service Workerが新たになったと証明され、urlsToCacheイベントをトリガします.アクティブ化が完了しました
  • 図に示すように、Service Workerのおおよそのライフサイクルである.Service Workerインストールが完了したら、いくつかの静的リソースをキャッシュしようとします.
    self.addEventListener('install', function(event) {
      self.skipWaiting();
      event.waitUntil(
        caches.open(CACHE_NAME)
        .then(function(cache) {
          return cache.addAll(urlsToCache);
        })
      );
    });
    まず、Service Workerは、待ち時間をブラウザに直接飛ばしてくださいと通知し、Service Workerの期限切れのactivateスクリプトを淘汰して、新しいService Workerの起動を直接試みる.installを使用してself.skipWaiting()を開き、sw.jsを介して予め宣言した静的ファイルのキャッシュを試みる.Service Workerを傍受し、代理ネットワーク要求
    ページのすべてのネットワーク要求は、Service Workercaches.openイベントを通じてトリガされ、Cachecache.addAllを介して、fetchからキャッシュを検索しようと試み、キャッシュが命中したら、直接キャッシュ中のService Workerに戻り、そうでなければ、リアルなネットワーク要求を作成する.
    self.addEventListener('fetch', function(event) {
      event.respondWith(
        caches.match(event.request)
        .then(function(response) {
          if (response) {
            return response;
          }
          return fetch(event.request);
        })
      );
    });
    要求中に新たなキャッシュをfetchに追加する必要がある場合、Service Worker方法によって追加することができ、以下の例を参照してください.
    self.addEventListener('fetch', function(event) {
      event.respondWith(
        caches.match(event.request)
        .then(function(response) {
          //     
          if (response) {
            return response;
          }
    
          //   ,      clone        
          //    response   Stream,              response
          //       response,      ,        。
          //        ,      ,  clone  
          var fetchRequest = event.request.clone();
    
          return fetch(fetchRequest).then(
            function(response) {
              //        ,       ,      ,     ,      
              if (!response || response.status !== 200 || response.type !== 'basic') {
                return response;
              }
    
              //      ,        
              var responseToCache = response.clone();
              caches.open(CACHE_NAME)
                .then(function(cache) {
                  cache.put(event.request, responseToCache);
                });
              return response;
            }
          );
        })
      );
    });
    プロジェクトの中で、必ずキャッシュを制御することに注意して、インターフェースの要求は普通はキャッシュを推薦しないのです.ですから、自分のプロジェクトの中では、ここでダイナミックなキャッシュプランを作っていません.caches.matchCacheは常に更新が必要な日があります.バージョンの反復に伴い、ある日、私たちは新しいバージョンの機能をオンラインにリリースする必要があります.この時は古いキャッシュを淘汰する必要があります.古いresponseCache Storageはどうやって淘汰しますか?
    self.addEventListener('activate', function(event) {
      var cacheWhitelist = ['counterxing'];
    
      event.waitUntil(
        caches.keys().then(function(cacheNames) {
          return Promise.all(
            cacheNames.map(function(cacheName) {
              if (cacheWhitelist.indexOf(cacheName) === -1) {
                return caches.delete(cacheName);
              }
            })
          );
        })
      );
    });
  • はまずホワイトリストがあります.ホワイトリストのcache.putは淘汰されません.
  • の後、activateを通じて、すべてのService Workerを取得し、ホワイトリストにないService Workerを淘汰します.
  • 淘汰Cache Storageメソッドを使用します.これは、Cacheをパラメータとして受信し、caches.keys()のすべてのキャッシュを削除する.
  • sw-precache-webpack-plugin
    sw-precache-webpack-pluginはCache Storageであり、Cacheをパッケージ化する際に、私たちが欲しいcaches.delete()cacheNameのシナリオを構成することによって生成することができる.
    一番簡単な構成は以下の通りです.
    var path = require('path');
    var SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
    
    const PUBLIC_PATH = 'https://www.my-project-name.com/';  // webpack needs the trailing slash for output.publicPath
    
    module.exports = {
    
      entry: {
        main: path.resolve(__dirname, 'src/index'),
      },
    
      output: {
        path: path.resolve(__dirname, 'src/bundles/'),
        filename: '[name]-[hash].js',
        publicPath: PUBLIC_PATH,
      },
    
      plugins: [
        new SWPrecacheWebpackPlugin(
          {
            cacheId: 'my-project-name',
            dontCacheBustUrlsMatching: /\.\w{8}\./,
            filename: 'service-worker.js',
            minify: true,
            navigateFallback: PUBLIC_PATH + 'index.html',
            staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
          }
        ),
      ],
    }
    cacheNameパッキングを実行すると、バッファwebpack pluginがパッキングした後の静的ファイルという名前のファイルが生成される.
    一番簡単な例です.webpack VS sw.jsService Workerバッファに比べて、webpackservice-worker.jsに協力しても自分の強みがあります.
  • キャッシュと更新は共存しています.バージョンを更新するたびに、webpackを介してキャッシュを使ってすぐに戻すことができますが、同時に要求を開始して、新しいバージョンの更新があるかどうか確認してもいいです.
  • 侵入なし式:Service Worker Cache値は本当にみっともないです.
  • は流されにくいです.Http Cacheはキャッシュが流されやすく、期限が切れやすいです.Http Headerは流されにくいです.有効期限が過ぎたという話もありません.
  • オフライン:Service Workerを介してオフラインアクセスアプリケーションを実現することができます.
  • しかし、Cache StorageService WorkerhashHttpCache Storageなどに依存しているため、互換性があまり良くないという欠点がある.
    後の話
    本明細書では、Service Workerの基本的な使用とクライアントキャッシュとしてのService Workerの使用を簡単にまとめただけの簡単な方法であるが、fetch APIの役割は、例えば、Promiseを介してオフラインアプリケーションを行い、ネットワークアプリケーションのプッシュ(push−notificationsを参照することができる)などにとどまらない.Cache Storageを借りて、インタフェースをキャッシュしてもいいです.私のプロジェクトの中では、そんなに複雑なことはしません.しかし、インターフェースキャッシュをするメリットはオフラインアクセスをサポートし、オフライン状態でも正常にアクセスできるService Workerアプリケーションです.Service WorkerService Workerはいつも切り離せません.Service Workerの最適な使い方は、実はService Workerに協力してオフラインキャッシュをすることである.Webにより、ネットワーク要求に対する制御が容易に実現され、異なるネットワーク要求に対して異なるポリシーが実行される.例えば、Cache Storageのポリシーについても、様々な場合がある.例えば、ネットワーク要求を優先的に利用しても良いし、ネットワーク要求が失敗した時にキャッシュを再利用しても良いし、キャッシュとネットワーク要求を同時に利用しても良いし、一方ではチェック要求があり、一方ではキャッシュをチェックして、二人のどちらが速いかを見て、誰を使用しても良い.