オフラインのWebアプリケーション。 ServiceWorkerとCacheStorage

私たちは何について話しているのですか?



ますます、オフラインで動作するようにフロントエンドアプリケーションを教えるという課題が生じています。 つまり、Webアプリケーションにモバイルまたはデスクトッププログラムのプロパティを与えることを意味します。これは、インターネット接続がない場合や、サーバーに障害が発生した場合にも機能します。



目標は、デバイス上の接続の問題からユーザーを保護することです。 最寄りのファーストフードでwi-fiが失われるため、Googleドキュメントで作成されたテーブルを保存しないのは残念です。



これを行うには、ブラウザでアプリケーションを初期化し、機能するために最低限必要なリソースをキャッシュする必要があります。 その後、サーバーが利用できない場合、キャッシュからアプリケーションを起動できます。



問題の解決策は次のとおりです。



  1. Webページに初めてアクセスするとき、html-、css-、js-files、スプライトなどの形式でサーバーから「静的」リソースを取得します。
  2. ブラウザツールを使用してクライアント側でリソースをキャッシュします。
  3. 後で、同じファイルを要求するときに、サーバーへの接続がない場合はキャッシュからそれらを返します。
  4. キャッシュ内の変更されたリソースを更新します。


これについてはすでに素晴らしい記事がありますが、それ以来何かが変わっています。 以前は、ApplicationCacheテクノロジーが一般的でし 。詳細については、 こちらをご覧ください 。 ApplicationCacheには多くの問題がありましたが、このテクノロジーには柔軟性がなく、現在は時代遅れであり、使用を推奨していません。



CacheStorageがアリーナに入り、ServiceWorkerで作業できるようになります。



サービスワーカー



ServiceWorkerは、オペレーティングシステムのサービスに相当する、バックグラウンドでブラウザーでJavaScriptコードを実行できる新しいテクノロジーです。 ServiceWorkerはWebリソースから開始し、それを初期化したアプリケーションに関係なくブラウザーで引き続き動作します。



多くの場合、ServiceWorkerを使用する目的は、ブラウザーでプッシュ通知を受信し、キャッシュされたリソースを制御することです。後者は単なるケースです。



キャッシュストレージ



CacheStorageは、ネットワークリソースキャッシュを格納するためのコンテナです。 グローバルCacheStorageオブジェクトには、名前キャッシュからアクセスできます。 そのコンポーネントはCache型のオブジェクトです。



キャッシュは、ペアの名前付きストアです:要求オブジェクト-応答オブジェクト。 キャッシュされたリソースごとに、Cacheインスタンスはフェッチ機能によって生成されたリクエストとレスポンスを保存します。



実際にはどのように見えますか?



次に、これらすべてを小さなテストアプリケーションで分析します。 ファイルがlocalhost / test_serviceworkerのローカルサーバーにあるとします。 タスクを設定します。 キャッシングを管理するには、次のことを行う必要があります。



  1. ネットワークへのアクセスの有無に関係なく、ブラウザーで動作するserviceWorkerを作成します。
  2. キャッシュにキャッシュされるリソースを追加します。
  3. serviceWorkerコードで、フェッチイベント(ネットワークリソースが要求されたときに発生するイベント)でハンドラーをハングさせます。
  4. キャッシュを発行および更新するロジックをハンドラーに組み込みます。


ServiceWorkerを開始するには、最初に登録する必要があります。 このアプリケーションでは、次のコンテンツのコードを追加する必要があります。



workerLoader.js



//     js-   serviceWorker' //  Promise  navigator.serviceWorker.register( '/test_serviceworker/appCache.js' ).then(function(registration) { //       ServiceWorkerRegistration console.log('ServiceWorker registration', registration); //      serviceWorker' //registration.unregister(); }).catch(function(err) { throw new Error('ServiceWorker error: ' + err); });
      
      





次のステップは、簡単なServiceWorkerコードを書くことです。



appCache.js



 self.addEventListener('install', function(event) { //  console.log('install', event); }); self.addEventListener('activate', function(event) { //  console.log('activate', event); });
      
      





serviceWorkerは、それが登録されたアプリケーションのグローバルスコープに関連付けられておらず、ウィンドウオブジェクトをまったく持っていないことに留意することが重要です。 自分自身には、ServiceWorkerGlobalScope型のオブジェクトがあり、そのオブジェクトにイベントハンドラーがインストールされます。



手順を実行し、 chrome:// inspect /#service-workerschromeのページを更新すると、次のように表示されます。







このスクリーンショットでは、ブラウザはバックグラウンドで3つのjsファイルを実行します。最初のファイルは、この例のキャッシングサービスです。



次に、serviceWorkerコードのインストール段階で、必要なリソースから初期キャッシュを作成します。



appCache.js



 //      var CACHE_NAME = 'app_serviceworker_v_1', //     cacheUrls = [ '/test_serviceworker/', '/test_serviceworker/index.html', '/test_serviceworker/css/custom.css', '/test_serviceworker/images/icon.png', '/test_serviceworker/js/main.js' ]; self.addEventListener('install', function(event) { //    //   , serviceWorker   event.waitUntil( //     Cache-    //    ,     caches.open(CACHE_NAME).then(function(cache) { //    cache   return cache.addAll(cacheUrls); }) ); });
      
      





すべてのリンクはルートに関連していることに注意してください。 また、キャッシュされたリソースの中には、serviceWorkerが登録するworkerLoader.jsファイルはありません。 キャッシュすることはお勧めできません。 オフラインモードでは、アプリケーションはオフラインモードで動作します。 しかし、serviceWorkerを無効にすることが緊急の場合、問題が発生する可能性があります。 ユーザーは(内容を比較して)serviceWorkerが更新されるまで待つ必要があります。



次に、フェッチイベントハンドラーをserviceWorkerコードに追加します。 そして、リソースのリクエストで、キャッシュからそれを発行します。



appCache.js



 self.addEventListener('fetch', function(event) { event.respondWith( //       caches.match(event.request).then(function(cachedResponse) { //  ,    if (cachedResponse) { return cachedResponse; } //       return fetch(event.request); }) ); });
      
      







しかし、必ずしもそれほど単純ではありません。 サーバー上で静的ファイルが変更されたとしましょう。 コードを複雑にしましょう。 HTTPヘッダーからlast-modifiedパラメーターを取得して、リソースの最終更新日を確認します。 また、必要に応じて、ファイルの最新バージョンをアップロードし、キャッシュを更新します。



appCache.js



 //    -   var MAX_AGE = 86400000; self.addEventListener('fetch', function(event) { event.respondWith( //      caches.match(event.request).then(function(cachedResponse) { var lastModified, fetchRequest; //      if (cachedResponse) { //     lastModified = new Date(cachedResponse.headers.get('last-modified')); //       if (lastModified && (Date.now() - lastModified.getTime()) > MAX_AGE) { fetchRequest = event.request.clone(); //    return fetch(fetchRequest).then(function(response) { //         if (!response || response.status !== 200) { return cachedResponse; } //   caches.open(CACHE_NAME).then(function(cache) { cache.put(event.request, response.clone()); }); //    return response; }).catch(function() { return cachedResponse; }); } return cachedResponse; } //      return fetch(event.request); }) ); });
      
      





再リクエストにはリクエストとレスポンスのクローンが使用されることに注意してください。 要求を送信できるのは1回だけで、応答を読み取ることができるのは1回だけです。 この制限のため、これらのオブジェクトのコピーを作成します。



同様に、キャッシュプロセスを制御できます。 宣言型のスタイルでは、appcacheマニフェストよりも明確な利点があります。 開発者には、HTTPヘッダー、ステータスコード、コンテンツを操作し、個々のリソースのロジックを実装する機会があります。



結論





オフラインWebアプリケーションのトピックは長い間存在していました。 おそらく、ServiceWorkerとCacheStorageは単なる一時的なソリューションです。 ただし、使用することはすでに理にかなっています。 これらの技術が時代遅れになったとしても、ブラウザメーカーは代替品として何かを作成します。 この方向で進行状況を追うだけです!



この記事を書くのに最適な資料は次のとおりです。



http://www.html5rocks.com/en/tutorials/service-worker/introduction/

https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers 。 入手可能にもかかわらず、私はロシア語で情報を共有することにしました。



All Articles