plyrs / plyrs.github.io

Today I Learned.
https://log.plyrs.net
1 stars 2 forks source link

Workbox #123

Open hiz8 opened 6 years ago

hiz8 commented 6 years ago

Webアプリをオフライン対応させる為に Service worker を導入する事自体は、実はそれほど難しくない。 やはり難儀なのはその後で、いわゆるキャッシュマネジメントである。

僕はネイティブアプリっぽいWebアプリ (またはサイト) の構築を近年は目指してきたのだが、作ってきたものの性質上オフライン化は特に意識せずにいた。 いわゆるインストールバナーの表示がまず第一で、その後にパフォーマンス向上を目的としてキャッシュを図るべく、少し意識低めでServiceWorkerとは付き合ってきた。

しかし、今作っている作品はまさにオフライン化するべきものであり、また比較的それが容易な内容である事から、少し本腰を入れて Service Worker を用いたオフライン化を行う事とした。

そこでまず考えるべきと思われるのが、冒頭のキャッシュマネジメントの問題であろう。 Webアプリのコードを修正するたびにキャッシュファイルの更新を促すよう、SW自身も更新しなけらばならず、これを手動で行うのは面倒だ。

そこで Google Chrome チームが開発している Workbox を試してみた。 主な参考文献は以下。

また、Webpack 環境の下での導入であったので、以下の記事も参考になった。

公式ドキュメント以外の、いずれの文献にも言えることであるが、現在 Workbox 自身の開発は活発に進んでおり、内容の相違が発生するスパンは短めであると見える。 現にほとんどの日本語文献には、現時点での仕様との違いがみられた。

幸い公式ドキュメントはしっかり更新されており、内容も充実しているので基本的にはそれを参考に進めるのがよさそうである。

webpack-plugin を介した導入には、二つの方法が容易されている。generateSW と injectManifest である。

まずは手軽にキャッシュを導入したい…というケースでは generateSW が適しているとの事。これは設定を適切に行えば、自動でServiceWorkerファイル自身を生成してくれる。

もう一方の injectManifest はひな型はユーザー自身で用意し、そこにキャッシュ更新のロジックを導入するといったものだ。キャッシュ以外の Service Worker の機能を利用したい場合はこちらを使用する。

また、キャッシュのみでもちょっとでも凝ったことを行おうと思うと、injectManifest を利用する必要がありそうだ。generateSW は手軽さと引き換えに柔軟性を犠牲にしている部分があり、僕も今回それが理由で injectManifest を選択せざるをえなかった。

さて、今回 webpack.config へ追記した内容は以下のようになった。

const { InjectManifest } = require('workbox-webpack-plugin');

module.exports = {
    plugins: [
        new InjectManifest({
            swSrc: './src/js/sw.js',
            swDest: 'sw.js',
            globDirectory: __dirname + '/dist',
            globPatterns: [
                '*.html',
                'fonts/**/*.{ttf,woff,woff2}',
                'img/**/*.png'
            ],
            importsDirectory: 'js/wb-assets'
        }),
    ],
};

そしてひな型となった sw.js は、最低限の機能導入となると以下のようになりそうだ。

workbox.skipWaiting();
workbox.clientsClaim();
workbox.precaching.precacheAndRoute(self.__precacheManifest);

これで webpack でビルドを行う際に、globでマッチするファイルをキャッシュするSWを生成してくれる。そしてファイルに更新が発生するたびに、マニフェストを書き換えキャッシュの更新を促してくれるというものだ。

そして実際に導入して感じたのは、generateSW と InjectManifest の導入方法にそれほど違いを感じなかった…という事だ。 なので今後のスケールを考えると基本的に InjectManifest での導入を考え、完全にキャッシュオンリーのシンプルな構成であるならば generateSW を選択するほうがよさそうである。