サービスワーカーを使用してJekyllブログをオフラインで動作させる方法

公開: 2017-01-26

ショートバイト:サービスワーカーの登場により、Webサイトをオフラインで機能させることができることをご存知でしたかこのようなWebアプリはPWA(プログレッシブWebアプリ)と呼ばれます。 このハウツーでは、サービスワーカーを使用して、Jekyllベースのブログ/Webサイトをオフラインで動作させ、それに付随するいくつかの優れた機能を提供するお手伝いをします。

(注記事のコードスニペットは、私のブログのコードリポジトリから取得されています。必要に応じて参照できます。Jekyllを初めて使用する場合は、CSSトリックに関する3シリーズの記事を読むことができます。)

バックグラウンド

以前は、yukYAMLファイルベースのAppCacheがありましたが、これは本質的に非常にハードコーディングされており、アセットやWebページを動的にキャッシュするために使用することはできませんでした。 入って、サービスワーカー。 アセットを格納するために動的なServiceWorkerキャッシングを実行する単純なプレーンイベントベースのJavascriptAPI。これにより、ネットワークがない場合にWebページを提供するためにアセットを使用できます。

サービスワーカーは2014年にChromeCanaryに上陸しましたが、その仕様はまだ改訂/追加され、設計されています。 2015年と2016年に、GoogleのChromeチームは、この新しいテクノロジーをブラウザに広めました。 Appleだけが(この記事を書いている時点でも)デバイスでこれをサポートしていません(理由は不明です)[彼らはサービスワーカーに関する仕様の議論にも積極的に参加していません]。

サービスワーカーとは何ですか? 基本的に、それはステロイドのウェブワーカーです。 Webワーカーの特徴の1つは、WebワーカーのすべてのタスクがメインのJavaScript実行スレッド(イベントループ)とは別に(非同期に)実行されることです。 この機能は、Webアプリのユーザーインターフェイスのパフォーマンスを損なうことなく、複雑な計算など、CPUまたはメモリを大量に消費するタスクを実行するのに役立ちます。

Service Workerを使用すると、JavaScript、CSS、HTML、画像、フォントファイルなどのアセットをブラウザのService Workerキャッシュにキャッシュ(長期間保存)できるため、ユーザーが次にそのページを読み込むときに、ほぼ瞬時に読み込まれます。 。 また、このキャッシュ戦略では、ブラウザーは最初にService Workerキャッシュからアセットの可用性を探すため、オフラインの場合でもWebページが提供されます。 キャッシュにアセットがない場合は、それをフェッチするためのネットワークリクエストが送信されます。

Service Workerを使用すると、Facebook、Web上のWhatsapp、Twitterなどの最近の多くのWebサイトで一般的に見られるプッシュ通知も有効になります。 主にオフライン機能について説明します。 このハウツーはJekyllに固有のものですが、ほとんどのServiceWorkerコードは一般的にどのWebサイトにも適用できます。

Jekyllは静的コンテンツを提供するため(静的サイトジェネレーターです!)、ServiceWorkerのコードは非常に基本的で理解しやすいものになります。

レッツ・ロール:

関連するすべてのページで、次のスクリプトが実行されます。 それは次のことをしています:

  1. ブラウザにServiceWorkerAPIが存在するかどうかを確認し、ServiceWorkerを登録します。
  2. Service Workerがアクティブ化されたら、Webサイトをオフラインで使用する準備ができたことを示す小さなトースト/チップメッセージをユーザーに送信します。
 関数showOfflineToast(){
  offsetToast = document.querySelector('。offline-ready');とします。
  offsetToast.classList.add('active');
  setTimeout(function(){ 
    offsetToast.className = offsetToast.className.replace( "active"、 "").trim();
  }、5500);
}

//(1)
if(navigator.serviceWorker){
  navigator.serviceWorker.register('/ sw.js')。then(function(reg){
      if(!reg.installing)return;
      console.log( "[*] ServiceWorkerがインストールしています...");

      var worker = reg.installing;

      worker.addEventListener('statechange'、function(){
          if(worker.state =='冗長'){
              console.log('[*]インストールに失敗しました');
          }
          if(worker.state =='インストール済み'){
              console.log('[*]インストールに成功しました!');
          }
          //(2)
          if(worker.state =='アクティブ化'&&!navigator.serviceWorker.controller){
            showOfflineToast();
          }
      });
  });
} 

gdad-s-river.github.io-(iPhone 6)

このコードをJekyllコードのincludesディレクトリ内のserviceWorker.htmlなどのファイルに追加し、Jekyllの液体テンプレートエンジンを使用してdefault.htmlに含めることができます。

 <!DOCTYPE html>
<html>

  {%include head.html%}

  <本体>
    {%include header.html%}

    <div class = "page-content">
      <div class = "wrapper">
        {{ コンテンツ }}
      </ div>
    </ div>

    {%include footer.html%}

    <!-上記のコードがスクリプトタグに含まれています->
    {%include serviceWorker.html%} 

    <divclass="offline-ready">サイトはオフラインで使用できます</div>
  </ body>

</ html>

次に、魔法を実行する実際のServiceWorkerコードについて説明します。 このコードは、Jekyllコードのルートのsw.jsにあります。

 //sw.js
---
レイアウト:null
---

const staticCacheName = "gdad-s-river-static-v61";

console.log( "Service Workerのインストール");

const filesToCache = [
  「/」、
  {site.html_pages%のページの%}
    '{{page.url}}'、
  {%endfor%}
  {site.postsの投稿の%%}
    '{{post.url}}'、
  {%endfor%}

  //手動入力ではなく自動化可能
  "/assets/images/bhavri-github-callbacks.png"、
  "/assets/images/bhavri-github-issues.png"、
  "/assets/images/jakethecake-svg-line-anime.png"、
  "/assets/images/svg-animated-mast-text-shapes-tweet.png"、
  "css / main.css"、
  "/だいたい/"、
  "/index.html"
];

staticCacheNameは、キャッシュされた応答に変更を加えるたびに更新されるキャッシュバージョンです(たとえば、CSSファイルやブログ投稿に変更を加えるなど)。 そして、インターセプトして配列にキャッシュするリクエストを定義しているだけです(次のスニペットで使用)。

 //sw.js

self.addEventListener( "install"、function(e){
  self.skipWaiting();
  e.waitUntil(
    caches.open(staticCacheName).then(function(cache){
      cache.addAll(filesToCache);を返します。
    })
  )。
});

self.skipWaitingは、このsw.jsファイルが変更されるたびに、新しいバージョンのService Workerをキューに入れるのではなく、すぐにアクティブにする必要があることを意味します(ユーザープロンプトでページを更新して、次のようなメッセージを表示することができます。ウェブページが更新/変更されました。[更新]をクリックして新しい投稿などを読み込みます。 )、古いバージョンを破棄します。

java-and-android-square-ad-1

e.waitUntil MDN Webサイトからの引用:

ExtendableEvent.waitUntil()メソッドは、イベントの存続期間を延長します。 サービスワーカーでは、イベントの存続期間を延長すると、イベント内の非同期操作が完了する前にブラウザーがサービスワーカーを終了するのを防ぐことができます。」

gdad-s-river-static-v61という名前のキャッシュを開き、キャッシュ名でpromiseを返します。次に、 cache.addAll (バックグラウンドでフェッチAPIを使用)を呼び出します。これにより、提供された配列とそれらをキャッシュします。

次のスニペットへ!

 //sw.js

self.addEventListener( "activate"、function(e){
  e.waitUntil(
    caches.keys()。then(function(cacheNames){
      Promise.all(を返す
        cacheNames.filter(function(cacheName){
          cacheName.startsWith( "gdad-s-river-static-")を返します
            && cacheName!= staticCacheName;
        })。map(function(cacheName){
          cache.delete(cacheName);を返します。
        })
      )ß
    })
  )。
});

Service Workerがアクティブになると、最新バージョンではないServiceWorkerが確実に削除されます。 たとえば、私の最新のキャッシュバージョンがgdad-s-river-static-v61であり、誰かがまだgdad-s-river-static-v58を使用している場合、次回の訪問時に、そのクライアントは気にしないでください。一度に1つのバージョンをポンピングしますが、最新のものをインストールするためにそのバージョンを率直に削除します。

 //sw.js

self.addEventListener( "fetch"、function(e){
  e.respondWith(
     caches.match(e.request).then(function(response){
       応答を返す|| fetch(e.request);
     })
   )。
});

フェッチイベントでは、サービスワーカーに、行われた特定の要求に応答する方法を指示しているだけです(応答を与えるパワーをハイジャックしているため、サービスワーカーは安全な別名httpsオリジンWebサイトでのみ動作します)。 リクエストをブラウザにキャッシュされているものと一致させるように指示し、リクエストに対する特定の応答が見つからない場合は、ネットワーク経由でフェッチするか、キャッシュから提供します。

多田! サービスワーカーがJekyllを利用したブログをオフラインにしました!

サプライズ! クールなもの:

バマー:これはiOSデバイスでは機能しません。

次のように、プロジェクトのルートにWebアプリmanifest.jsonファイルを追加する場合:

 {{
  "名前": "gdad-s-river"、
  "short_name": "gdad-s-river"、
  "theme_color": "#2196f3"、
  "background_color": "#2196f3"、
  「ディスプレイ」:「スタンドアロン」、
  "スコープ": "/"、
  "start_url": "/"、
  「アイコン」:[
    {{
     "src": "assets / images / favicon_images / android-icon-36x36.png"、
     「サイズ」:「36x36」、
     "タイプ": "image \ / png"、
     「密度」:「0.75」
    }、
    {{
     "src": "assets / images / favicon_images / android-icon-48x48.png"、
     「サイズ」:「48x48」、
     "タイプ": "image \ / png"、
     「密度」:「1.0」
    }、
    {{
     "src": "assets / images / favicon_images / android-icon-72x72.png"、
     「サイズ」:「72x72」、
     "タイプ": "image \ / png"、
     「密度」:「1.5」
    }、
    {{
     "src": "assets / images / favicon_images / android-icon-96x96.png"、
     「サイズ」:「96x96」、
     "タイプ": "image \ / png"、
     「密度」:「2.0」
    }、
    {{
     "src": "assets / images / favicon_images / android-icon-144x144.png"、
     "サイズ": "144x144"、
     "タイプ": "image \ / png"、
     「密度」:「3.0」
    }、
    {{
     "src": "assets / images / favicon_images / android-icon-192x192.png"、
     "サイズ": "192x192"、
     "タイプ": "image \ / png"、
     「密度」:「4.0」
    }
  ]
}

それをheadタグ内のhead.htmlファイルに追加します。

 <頭>
 <!-いくつかのもの->
	<link rel = "manifest" href = "/manifest.json">
 <!-いくつかのもの->
</ head>

次に、2回目のWebサイトへのアクセス(5分以内)で、ユーザーにWebサイトをホーム画面に追加するように求めます(他のネイティブアプリと同じようにアイコンを表示します)。アプリ。

スクリーンショット_20170123-232947

資力

  • Service Workerのオフライン機能とキャッシュ戦略の詳細は、この素晴らしいJakeArchibaldのオフラインクックブックに記載されています。
  • サービスワーカーとIndexDBについて知る必要があるすべてについての非常に詳細な無料のUdacityコース。

Jekyllブログのこの記事は面白くて役に立ちましたか? あなたの意見やフィードバックを共有することを忘れないでください。

また読む:Ecosia —木を植える検索エンジン