概要
先日の Google I/O 2018 などで更に勢いがました PWA ですがその基本的な知識として Service Worker があります
全く触ったことがなかったので今回はローカルキャッシュ機能を試してみました
環境
- macOS 10.13.4
- Google Chrome 66.0.3359.181
事前準備
今回は localhost を使います
実際に運用するときは Service Worker は https でないと動作しないようです
またページをホストするミドルウェアを用意しておいてください
特に指定はないので Apache Httpd なり nginx なりお好きなものを使ってください
ちなみに自分は Sinatra で動かしています
以下では http://localhost:9292/sw_test
で動いているページを Service Worker 化します
HTML ファイルの準備
今回はオフラインキャッシュ機能を使います
簡単に言うと http://localhost:9292/sw_test
にオフライン状態でもアクセスできるようにします
「localhost なんだからオフラインでもアクセスできるだろ」と思いますがローカルホストのプロセスを停止していてもアクセスできるようになります
<html>
<head>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service_worker.js', { scope: '/sw_test' }).then(function(reg) {
if(reg.installing) {
console.log('Service worker installing');
} else if(reg.waiting) {
console.log('Service worker installed');
} else if(reg.active) {
console.log('Service worker active');
}
}).catch(function(error) {
console.log('Registration failed with ' + error);
});
}
</script>
</head>
<body>
test page
</body>
言わずもがなポイントは <script>
タグ内の内容です
やっていることは /service_worker.js
の登録になります
この専用の JavaScript を登録することでオフラインでもページが描画できるようにします
navigator.serviceWorker.register
することで登録でき、それぞれのイベントに応じてログを出力しています
あと大事な概念としては「スコープ」があります
これも簡単に説明すると
Service Worker 化するページの範囲
を指定します
今回であれば /sw_test
のページのみを Service Worker 化するのでそれを指定しています
サイト全体を対象にする場合は /
と指定します
service_worker.js の作成
キモの部分となる Service Worker に処理させる内容をこの service_worker.js
に記載します
service_worker.js
は今回であれば http://localhost:9292/service_worker.js
で見えるようにしておいてください
ちなみに JavaScript だから http://localhost:9292/js/service_worker.js
という感じで配信したいという人もいると思いますがこれだと動きません (今回の場合は)
なぜかというと service_worker.js
が /sw_test
の親もしくは子の範囲にいないからです
もう少し説明すると /sw_test/service_worker.js
で配信するなら動作しますが、/sw_test2/service_worker.js
だと動作しません
特にこだわりがないのであればルートに配置しておくのが無難だと思います
今回はオフライン時にキャッシュしたページを表示させるだけの処理を記載します
まず全体は以下のとおりです
let version = '0.1';
self.addEventListener('install', e => {
let timeStamp = Date.now();
e.waitUntil(
caches.open('mismith').then(cache => {
return cache.addAll([
`/sw_test`
])
.then(() => self.skipWaiting());
})
)
});
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim());
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request, {ignoreSearch:true}).then(response => {
console.log('fetching');
return response || fetch(event.request);
})
);
});
やっている処理を大きく 3 つです
- インストール時に Service Worker がキャッシュするページを指定
- Service Worker が
activate
したら直ちに起動 - 対象のページにリクエスト (
fetch
) があったときにキャッシュしたページをレスポンスとして返却
になります
ポイントですがまずキャッシュするページは cache.addAll
に配列してパスを指定します
今回であれば HTML だけなので /sw_test
だけで OK です
感が良ければここで気づくと思いますが CSS や JS も必要なページの場合はそれらもキャッシュしなければなりません
例えば http://localhost:9292/js/custom.js
という JavaScript が必要な場合は /js/custom.js
を配列に追加してください
activate
と fetch
のイベントに関してはとりあえずそのまま使えば OK です
動作確認
では動作確認してみましょう
ちなみに Chrome で確認する場合は開発ツールの「Application」->「Service Workers」で登録した Service Worker の一覧や現在の状態を確認することができます
chrome://serviceworker-internals/
に Chrome でアクセスしても登録済みの Service Worker の一覧を確認することができます
まず普通にページアクセスします
すると Service Worker の登録が行われます
かつ今回の場合であればページのキャッシュも同時に行われています
次にオフラインにして確認してみましょう
先程の Chrome 開発ツールのところに「Offline」ボタンがあるのでこれを使って擬似的にオフライン状態を再現します
ちなみに本当にオフラインかどうか一度 Youtube にアクセスを試みています
こんな感じでキャッシュしたページであればアクセスしてもエラーのページとはならないのがわかると思います
最後に
噂の Service Worker に入門してみました
今回はかなり基本的な機能しか試していません
Service Worker を使えばブラウザプッシュなどもできるようになります
使っていてポイントだなと感じたのはキャッシュするページの量が多いと大変だなと思いました
最近だと WebPack や browserify などを使って 1 つのファイルにまとめることができるのでそういった仕組みを使うと相性が良いかと思います
また、どうしても外部のサイトの JS を参照しなければいけない場合にはそれえらを外す必要があります
例えば Google Analytics ですが解析のための JavaScript コードが入っていると Service Worker がエラーを吐き続けてしまいます
Google Analytics に限って言えば解析のためのコードなのでページ自体は動作すると思いますがエラーが出続けてしまうというのが気になるところです
Service Worker 用の JavaScript を用意するだけで簡単に対応できるのでやっておいて損はないような気がします
というのもオフラインキャッシュがすごいというよりかは PWA 対応できるのでスマホアプリ化できると考えると損はないかなと思います
ただ、冒頭簡単に説明しましたが https
が必須なので注意が必要です
0 件のコメント:
コメントを投稿