強力かつ柔軟なクライアントサイドキャッシュを適用できるService Workerですが、ブラウザ内で動くJavaScriptである以上、クロスドメインによる制約がかかってきます。
クロスドメインなソースからWorkerの登録
Service Workerはnavigator.serviceWorker.register(pathToJs)
で登録しますが、このpathToJs
にはクロスドメインなURLは渡せません。
ただ、アセットだけ別サーバに置いているような場合など、クロスドメインで登録したくなることがあるかもしれません。このような場合、
- 同じドメインあるいは
Blob
の形で、「importScripts()
するだけのService Worker」を登録する -
importScripts()
はクロスドメインでも問題なし
という2段階を踏むことで、クロスドメインに置いたJavaScriptのコードをService Workerとして登録することが可能となります。
クロスドメインなリクエストのキャッシュ
ワーカーを導入できれば、キャッシュ管理も可能です…が、やはりクロスドメインには注意点が多々あります。
opaqueなレスポンス
CORSに対応していないサーバに対してfetch(url)
としても失敗するだけですが、専用のモードがあって、fetch(url, {mode: 'no-cors'})
とすればfetch
自体は成功します。
ただし、CORS外で情報が漏れないように、fetch(url, {mode: 'no-cors'}).then(request => ...)
で返ってくるrequest
オブジェクトは、opaque(不透明)になっていて、リクエストしたURL以外、ほとんど情報が得られません。
-
cache.add('https://crossdomain.example/some-asset')
のようにした場合、内部的にはfetch
を実行していますが、成功/失敗すら情報が得られないので、キャッシュには追加されません。 - opaqueなレスポンスを
cache.put()
した場合、キャッシュに追加はされますが、リクエスト失敗でも問答無用で追加されてしまいます。
ということで、CORS非対応なリソースをキャッシュさせる場合は、時折破棄するなどしないと、たまたま踏んづけたエラーが残り続けるというまずい事態も発生しかねないので要注意です。