--2021年10月21日追記--
本記事は create-react-app v3 での方法を述べています。v4 から仕組みが変わり service-worker.js
は生成されるものではなくデフォルトの実装が提供され自分で管理するようになりました。本記事で述べるようなパッチの必要はありません。
TL;DR
create-react-app がビルド時に生成するファイルをカスタマイズするために diff
でパッチを作成しておいてビルド時に patch
コマンドで適用しました。
create-react-app 利用時に service worker をカスタマイズする
create-react-app では service worker の実体が service-worker.js
としてビルド時に生成されます。たまに(しょっちゅう?)カスタマイズしたくなるのですが生成されるものだから少し工夫が必要です。
※ 非 eject 環境です
service-worker.js
はこういう内容のファイルです。今回は最後の blacklist
を変更したいと思います。このままだともし /blog
などでこの SPA ではない別のアプリケーションを動かしていても service worker が全部 index.html
を返してしまうんですよね。
/**
* Welcome to your Workbox-powered service worker!
*
* You'll need to register this file in your web app and you should
* disable HTTP caching for this file too.
* See https://goo.gl/nhQhGp
*
* The rest of the code is auto-generated. Please don't update this file
* directly; instead, make changes to your Workbox build configuration
* and re-run your build process.
* See https://goo.gl/2aRDsh
*/
importScripts(
'https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js'
);
importScripts('/precache-manifest.25289e9c0db09d014e37a8aef0a48861.js');
self.addEventListener('message', event => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
workbox.core.clientsClaim();
/**
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
* requests for URLs in the manifest.
* See https://goo.gl/S9QRab
*/
self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
workbox.routing.registerNavigationRoute(
workbox.precaching.getCacheKeyForURL('/index.html'),
{
blacklist: [/^\/_/, /\/[^\/]+\.[^\/]+$/],
}
);
このファイルを変更したものをビルド後に差し替えたら簡単そうですが中盤の /precatch-manifest.<hash>.js
のハッシュ部分がビルドのたびに変わるのでそうはいきません。
service-worker.js
をカスタマイズしたいという要求はよくあるらしくググるといくつか方法が見つかります。ここでは create-react-app のものをなるべく利用しつつ少しだけ変更するための方法を考えてみました。
簡単に言うとこんな手順です。
- 事前にパッチを作る
- ビルド時にパッチを適用する
事前にパッチを作る
まずビルドします。
npm run build
ファイルをコピーして変更します。
cd build
cp service-worker.js service-worker.js.new
service-worker.js.new
を好きなように変更します。
パッチを作ります。
diff -u service-worker.js service-worker.js.new > ../patch/service-worker.js.patch
ビルド時にパッチを適用する
package.json
の scripts
に次のように patch
コマンドを登録しておきます。
"scripts": {
"start": "react-scripts start",
...
"patch": "cd build && patch < ../patch/service-worker.js.patch"
},
実行
これで npm run build
してから npm run patch
でパッチが適用されます。
blacklist を利用する別の方法
今回のように blacklist を設定したいのであれば、デフォルトで /_
から始まる URL が設定されているのでそれを利用してもよいかもしれません。その場合は /blog
ではなく /_blog
としてアクセスできるようにサーバー側を変更します。
バージョン
- create-react-app 3.0.1