create-react-appで作ったReact SPAにWorkbox-CLIでService Workerをねじ込む

create-react-appにService Workerついてるんですよね。一応。 ただしランタイムキャッシュの設定とかしたいなぁってなった時に、npm run ejectしろってなるのであまり使いたくない感があり […]

広告ここから
広告ここまで

目次

    create-react-appにService Workerついてるんですよね。一応。

    ただしランタイムキャッシュの設定とかしたいなぁってなった時に、npm run ejectしろってなるのであまり使いたくない感がありまして。

    「だったらWorkbox-cliで手動で入れるか」という試みです。

    $  workbox --version
    3.0.0

    対話形式でセットアップ

    対話形式でセットアップします。ここは基本的にデフォルトでOKです。root of your web appbuildになりますので、sw.jsの配置場所などはそこにしておきましょう。あとはworkbox-config.jsは.gitignoreしないように気をつけてください。sw.jsはこのファイルから生成するものなので省略しちゃってOKです。

    $ workbox wizard
    ? What is the root of your web app (i.e. which directory do you deploy)? build/
    ? Which file types would you like to precache? json, png, ico, html, js, xml, css
    ? Where would you like your service worker file to be saved? build/sw.js
    ? Where would you like to save these configuration options? workbox-config.js
    To build your service worker, run
    
      workbox generateSW workbox-config.js
    
    as part of a build process. See https://goo.gl/fdTQBf for details.
    You can further customize your service worker by making changes to workbox-config.js. See https://goo.gl/gVo87N for details.

    変更後はこうなります。

    $ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
    	workbox-config.js
    
    $ cat workbox-config.js
    module.exports = {
      "globDirectory": "build/",
      "globPatterns": [
        "**/*.{json,png,ico,html,js,xml,css}"
      ],
      "swDest": "build/sw.js"
    };
    

    Service Workerの設定を書く

    先ほど作ったworkbox-config.jsに設定を書いていきます。runtimeCachingに外部から持ってくるもののキャッシュ設定を書いていきましょう。あと、navigateFallbackを設定し忘れると、react-routerなどでルーティングさせてる場合にオフラインで事故ります。

    module.exports = {
      "globDirectory": "build/",
      "globPatterns": [
        "**/*.{json,png,ico,html,js,xml,css}"
      ],
      "swDest": "build/sw.js",
      "navigateFallback": '/index.html',
      "runtimeCaching": [
        {
          urlPattern: /^https:\/\/cdnjs\.cloudflare\.com\/ajax\/libs\/slick-carousel\/1\.6\.0\/slick\.min\.css/,
          handler: 'cacheFirst',
          options: {
            cacheName: 'slick-min',
            expiration: {
              maxEntries: 80,
              maxAgeSeconds: 60 * 60 * 24
            }
          }
        },
    ...

    最後に変換して終わりです。

    $  workbox generateSW workbox-config.js
    $ cat build/sw.js
    /**
     * 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/3.0.0/workbox-sw.js");
    
    /**
     * The workboxSW.precacheAndRoute() method efficiently caches and responds to
     * requests for URLs in the manifest.
     * See https://goo.gl/S9QRab
     */
    self.__precacheManifest = [
      {
        "url": "asset-manifest.json",
        "revision": "083db5510bccc5483174e3dff8b7ac6d"
      },
      {
        "url": "assets/favicon/favicon-16x16.png",
        "revision": "6e1b9c138332350d1bc8c4df3048d339"
      },
      {
        "url": "assets/favicon/favicon-32x32.png",
        "revision": "458476695d9f85b8a006de9dc0266ed8"
      },
      {
        "url": "assets/favicon/favicon.ico",
        "revision": "6679c88c1fc7f22dc32f0b2558b3653b"
      },
      {
        "url": "assets/favicon/manifest.json",
        "revision": "f16d818905bcd39ebaab1f7dd1a37eed"
      },
      {
        "url": "favicon.ico",
        "revision": "c92b85a5b907c70211f4ec25e29a8c4a"
      },
      {
        "url": "index.html",
        "revision": "099c9063f8e1839296cba3b204b1c533"
      },
      {
        "url": "manifest.json",
        "revision": "730915ec2725cf6721080a6516b23f15"
      },
      {
        "url": "service-worker.js",
        "revision": "ed22c798cbc34f7c29d6effda7ddc65e"
      },
      {
        "url": "sitemap.xml",
        "revision": "281e5a319b915b53a51f8372a2c0db9d"
      },
      {
        "url": "static/css/main.4de8d704.css",
        "revision": "1af8ae00d038c10b786769159200fc48"
      },
      {
        "url": "static/js/main.f8977b6b.js",
        "revision": "9bfb5bf61040ab2d9852303cef585b24"
      }
    ].concat(self.__precacheManifest || []);
    workbox.precaching.suppressWarnings();
    workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
    workbox.routing.registerRoute(/^https:\/\/cdnjs\.cloudflare\.com\/ajax\/libs\/slick-carousel\/1\.6\.0\/slick\.min\.css/, workbox.strategies.cacheFirst({ cacheName: "bootstrap", plugins: [new workbox.expiration.Plugin({"maxEntries":80,"maxAgeSeconds":86400})] }), 'GET');
    
    ...

    React SPAで読み込ませる

    このままindex.htmlに書いてもいいのですが、create-react-appが用意しているregister関数がそこそこ優秀(localhostやdevビルドを除外・解除用ヘルパーもある)なので、そっちを使います。

    src/registerServiceWorker.jsに設定が書かれているので、service-worker.jsというファイル名の記述をWorkbox-cliで作ったものに書き換えておきましょう。

    ビルドコマンドに追加する

    最後にCDパイプラインにのせても動くようにしておきましょう。

    $ npm i -d workbox-cli
    $ vim package.json
    ...
      "scripts": {
        "build": "react-scripts build && ./node_modules/.bin/workbox generateSW workbox-config.js ",
    ...

    workbox-cliをグローバルに入れてもいいのですが、それだとコマンド増えるのでdevDependenciesに入れてそっちでやっちゃいます。

    あとreact-scripts buildより先にworkbox generateSWを実行してしまうと、ビルド時に生成されるJSファイル名にハッシュが入っている関係上やはり事故ります。

    取り急ぎ以上です。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark