スキップしてメイン コンテンツに移動

Application CacheからService Workerへ最速移行する! [10分で移行できます]

enter image description here

廃止予定の、Application Cacheを、Service Worker最速移行させる方法です。

2016/10/28 に、HTML5.1が勧告され、正式にApplication Cacheが仕様から削除されました。

2018/10現在の状況は、非推奨として、まだ ほとんどのブラウザで使用可能な状態です。
しかし、将来的には廃止される事が決まって、いつ使えなくなってもおかしくない状態です。
今のうちに移行しましょう!!

Application Cacheの代わりとして、より高機能な Service Workerの使用が推奨されています。
今回は、Application Cacheで作ったマニュフェストファイルをそのまま使って、最速でService Workerに対応する方法について、紹介します。

マニュフェストファイルを動的に作る外部のプログラムを別で作っていた場合、この方法であれば、外部プログラムの修正が不要で、移行がスムーズに進むと思います。

オフライン対応のイメージ

Service Workerでのオフライン対応イメージです。

下のイメージ通り、オンライン時に、Service Workerが必要なリソースをダウンロードし、Cacheストレージに溜めておきます。

オンライン時

オフラインになった時は、Cacheストレージに溜めてあるリソースをレスポンスとして返します。
これにより、オフラインても動作出来るWebアプリになります。

オフライン時

Application Cache → Service Workerに移行

マニュフェスト(manifest)の準備

Application Cacheで作った、マニュフェストファイルを、そのまま使います。
以下のように、必要なリソースのURLを、CACHE:セクションに書いておきます。

[site.appcache]

CACHE MANIFEST

CACHE:
index.html
css/common.css
scripts/jquery-1.10.2.min.js
css/images/back.png

NETWORK:

Service Workerの作成

Application Cacheでは、マニュフェストさへ用意しておけば、勝手にリソースをキャッシュしてくれる仕様ですた。
Service Workerの場合は、JavaScriptでキャッシュする処理を自前で書く必要があります。

以下が、キャッシュをサンプルコードとなるので、コピペで使ってください。

[service-worker.js]

const STATIC_CACHE_KEY = 'cache-key';
const MANIFEST_URL = "site.appcache";

var ORIGIN = location.protocol + '//' + 
            location.hostname + 
            (location.port ? ':' + location.port : '');

/*************************************************************************
 * インストール時の処理
*************************************************************************/
self.addEventListener('install', event => {

  //ワーカーをアクティブ状態に切り替える
  event.waitUntil(self.skipWaiting());

  //キャッシュするリソースをダウンロードする
  event.waitUntil(
    //マニュフェストファイルから、キャッシュ対象のリソースURLを取得
    load_manifest()
      //キャッシュ対象のリソースをダウンロードし、キャッシュストレージに保存する
      .then((list) => download_files(list))
  );
});

/*************************************************************************
 * マニュフェストファイルの読み込み
 * @description マニュフェストの :CACHEセクションに書かれているリソースURLを抽出
*************************************************************************/
function load_manifest() {

  return fetch(ORIGIN + "/" + MANIFEST_URL)
  .then(response => response.text())
  //マニュフェストから、キャッシュするURLのリストを取得する
  .then(content => {

    //マニュフェストファイルの中身を解析して、
    //キャッシュセクションに書かれているファイルリストを取り出す
    content = content.replace(
      new RegExp(
        "(NETWORK|FALLBACK):" +
        "((?!(NETWORK|FALLBACK|CACHE):)[\\w\\W]*)",
        "gi"
        ),
        ""
    );
    content = content.replace(
      new RegExp( "#[^\\r\\n]*(\\r\\n?|\\n)", "g" ),
        ""
    );
    content = content.replace(
      new RegExp( "CACHE MANIFEST\\s*|\\s*$", "g" ),
        ""
    );
    content = content.replace(
      new RegExp( "[\\r\\n]+", "g" ),
        "#"
    );

    //キャッシュ対象のURLを、リストで返す
    var fileList = content.split("#");
    //マニュフェスト変更チェックの為に、マニュフェストファイルもキャッシュしておく
    fileList.push(MANIFEST_URL);
     
    return fileList.map(function(url) {
      return ORIGIN + "/" + (url == "/" ? "": url);
    }).slice(1, fileList.length);
  });
}

/*************************************************************************
 * キャッシュ対象のリソースをダウンロードして、キャッシュストレージに保存する
 * @param {Array} cache_urls キャッシュするリソースのURLリスト
*************************************************************************/
function download_files(cache_urls) {

  return caches.open(STATIC_CACHE_KEY).then((cache) => {
    return Promise.all(
      cache_urls.map(url => {
        return fetch(new Request(url, { cache: 'no-cache', mode: 'no-cors' }))
         .then((response) => {
           return cache.put(url, response);
         });
      })
    );
  });
}

/*************************************************************************
 * fetchイベント発生時の処理 
 * @description ブラウザからのリクエストが、キャッシュ済みのリソースであれば、
 *              キャッシュストレージの内容でレスポンスを返します。
*************************************************************************/
self.addEventListener('fetch', function(event) {

  //マニュフェストファイルに対するリクエストの場合、変更チェックを行い、
  //マニュフェストに変更がある場合、リソースの再キャッシュを行う
  if (event.request.url == ORIGIN + "/" + MANIFEST_URL) {
    check_manifest();
  }
  
  //キャッシュ済みのリソースであれば、キャッシュストレージの内容でレスポンスを返します。
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

/*************************************************************************
 * マニュフェストファイルの変更チェック
 * @description マニュフェストファイルに差異があれば、リソースを再ダウンロード&再キャッシュする
*************************************************************************/
function check_manifest() {

  //キャッシュされているマニュフェストを格納する変数
  var cacheManifest = "";

  //キャッシュからマニュフェストファイルを取得する
  caches.match(new Request(ORIGIN + "/" + MANIFEST_URL))
    .then((response) => {
      if (response == null || typeof response === "undefined") {
        return "";
      }
      return response.text();
    })
    //最新版のマニュフェストファイルを Webサーバから取得する
    .then(content => {
      cacheManifest = content;
      return fetch(ORIGIN + "/" + MANIFEST_URL);
    })
    .then(response => response.text())
    //マニュフェストファイルに差異があれば、リソースを再キャッシュ
    .then(content => {
      if (content != cacheManifest) {
        console.log("マニュフェストファイルに変更があった為、リソースを再キャッシュします");
        //現在のキャッシュをクリア
        return caches.delete(STATIC_CACHE_KEY);
      } else {
        //変更がない場合h、処理を中断する為に、例外をスローする
        throw "NoChanged";
      }
    })
    .then(() => {
      return load_manifest()
        .then((list) => download_files(list));
    }).catch(err => {
      if (err === "NoChanged") return;
      throw err;
    });
}

HTMLファイルの修正

メインとなる HTMLファイルを修正していきます。

  • manifest 属性の削除

<html>タグの manifest属性は不要になるので、消します。

<html lang="ja" manifest="site.appcache">

↓↓↓↓↓↓

<html lang="ja">
  • Service Workerのインストール処理を追加

以下のJavascriptを、画面Load時に走るように追加します。

if (navigator.serviceWorker) {

  //(1)Service Workerのインストール
  navigator.serviceWorker.register('./service-worker.js', { scope: '.' });

  //(2)マニュフェストに変更があれば、Service Worker側でリソースの再キャッシュを行う
  if (navigator.onLine) {
    fetch("/site.appcache");
  }
}

動作確認

ちゃんとキャッシュされているか確認する

  1. 完成したWebページを立ち上げて、Chromeの開発者ツールを起動します。
  2. Cache -> Cache Storage -> cache-key を選択します。
  3. 右側の一覧に、マニュフェストファイルで書いたリソースがあれば、キャッシュ成功です。

キャッシュされている様子

オフラインでも動作するか確認する

次に、オフラインでも動作するか確認しましょう。
Chromeの開発者ツールで Offlineにチェックすれば、簡単にオフライン状態にする事ができます。

Chromeの開発者ツールで  Offlineにチェック

これで問題なく表示されれば、移行成功です。

最後に

いかがですか?
今回の方法であれば、すぐに移行が出来たと思います。
問題等あれば、極力直したいと思いますので、ご連絡をお願いします。

もうこれ以上、キャッシュAPIの仕様が変わらない事を祈って、まとめとさせてもらいます。

コメント

このブログの人気の投稿

axiosの使い方まとめ (GET/POST/例外処理)

axiosの使い方まとめ (GET/POST/例外処理)最近何かとよく使うJavaScriptでAJAX通信を行うaxiosについて、簡単に使い方をまとめました。GETリクエストをaxiosで送るまずはGETリクエストをaxiosで送る方法です。const res =await axios.get('/users') console.log(res.data)分割代入の記法を使うと、以下のようにも書けますconst{data}=await axios.get('/users') console.log(data)クエリパラメータ (URLパラメータ)を指定クエリパラメータを指定する方法は2つあります。1つ目は、axios.getに指定するURLに直接記述する方法です。axios.get('/user?id=123')2つめは、axios.getの第2引数に、オプション指定する方法です。axios.get('/user',{ params:{ id:123}})POSTリクエストをaxiosで送る次はPOSTリクエストをaxiosで送る方法です。JSON形式でPOSTするJSON形式でPOSTする場合は、axios.postの第2引数に、送信するデータをJavaScriptオブジェクトで指定します。const res =await axios.post('/user',{ id:123, name:'Yamada Tarou'})application/x-www-form-urlencoded形式でPOSTするapplication/x-www-form-urlencoded形式でPOSTする場合は、URLSearchParamsを使います。var params =newURLSearchParams() params.append('id',123) params.append('name','Yamada Tarou')const res =await axios.post('/user', params)スポンサーリンク axios でファイルをアップロードする画像などのファイルを、…

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決する

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決するタイトルの通りですが、Windows 8 以降では Windows Form アプリケーションで、コントロールの ImeMode に Katakana や KatakanaHalf を設定しても、カタカナになってくれません。なぜ ImeMode が効かないのか?Windows 8 以降、IME Mode の切り替えは、ユーザー単位で切り替わるようになった為、アプリから IME Mode 制御が出来ないようになりました。
(IME をON にした場合、常に ひらがな モードになます)※ Windows 7までは、IME Modeの切り替えはアプリ単位で行われていた為、問題なくアプリから IME制御が行えました。スポンサーリンク 対処方法Windows 8 以降、IMEの制御は、InputScope クラスの利用が推奨されています。
しかし、InputScope クラスは、WPF、Windows ストアアプリでしか使えない為、Windows Formアプリでは使用できません。
(Windows Form はもう使うな!という事でしょうか (涙) )結論としては、コントールパネルの設定で、IMEの制御をユーザ単位から アプリ単位に変更する事ができます。
これで、Windows Formアプリでも 従来通りIMEの制御を行う事が出来ます。おわりにこの方法だと、アプリをインストールする端末すべてに設定が必要となり、とっても面倒です。。。
しかし、今の所これしか方法がない状態です。
これからは Windows Formではなく、WPFや Windows ストアアプリで作れという事ですかね (^^;)

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]MailKitを使ってメールを送るサンプルコードです。(C#)UTF8/iso-2022-jpのエンコーディング指定、GMail/YahooのSMTPサーバで送るなど、4つのサンプルコードでMailKitの使い方を紹介します。MailKitって何?2017年に.NET標準のSystem.Net.Mail.SmtpClientが廃止予定となり、Microsoftより今後はオープンソースライブラリである、MailKitに置き換えるとアナウンスがありました。既にSmtpClientは非推奨になっており、今後は廃止されていきます。現在、SmtpClientを使用したソースコードには、Visual StudioからMailKitを使うよう警告が出るようになっています。さっそく、MailKitを使ってメールを送信するサンプルコードを作っていきます。UTF8でメールを送信文字エンコーディングを、UTF8でメールを送信するサンプルコードです。
MailKitは、デフォルトの文字エンコーディングがUTF8なっている為、シンプルなコードでメールを送信する事ができます。var host ="<smtp server name>"; var port =25;// or 587using(var smtp =new MailKit.Net.Smtp.SmtpClient()){//SMTPサーバに接続する smtp.Connect(host, port, MailKit.Security.SecureSocketOptions.Auto);//認証が必要な場合は、以下のコメントを解除//smtp.Authenticate("<id>", "<password>");//送信するメールを作成する var mail =new MimeKit.MimeMessage(); var builder =new MimeKit.BodyBuilder(); mail.From.Add(new MimeKit.MailboxAddress("",&quo…