TL;DR
-
create-react-app
のPWAテンプレートなしプロジェクト -
eject
なし - Webpackの設定オーバーライドなし
でWorkboxを導入してPWAを有効にできる。
はじめに
create-react-app
でPWA対応のReactプロジェクトを作るには --template cra-template-pwa
というオプションでPWA対応のテンプレートを読み込む方法が見つかります。
しかし、プロジェクトの立ち上げから携わることができないケースもあります。その場合PWA対応のテンプレートを使わなかった状態から「後ほどPWA対応にする方法を探す」としても見つかりづらかったです(2021/08/18現在)
また、 create-react-app
で作成したプロジェクトは eject
コマンドを使って設定ファイルを抽出しないとWebpackの設定を変更するのが難しくなります。一度ejectするとその前の状態に戻せないのでejectを選択しない場合もあります。
ejectせずにWebpackの設定をオーバーライドする方法(react-app-rewiredなど)を試しましたが正しく設定することができませんでした。
そこで、PWA未対応のReactプロジェクトに導入する方法としてWorkboxをインストールする方法が正しく動作したので、導入手順を残そうと思います。
環境
$ node --version
v14.17.3
$ npm --version
6.14.13
$ yarn --version
1.22.11
Workbox パッケージのインストール
workbox wizard
を使ってWorkboxに必要なファイルを生成します。使うのはこの1回限りになりますが、 npx
が使えないためworkbox-cliをグローバルでインストールする必要があります。
npm i -g workbox-cli
次に、Reactのプロジェクトディレクトリ内でwizardを実行します。
workbox wizard
いくつか質問があるので答えていきます。
? What is the root of your web app (i.e. which directory do you deploy)?
そのうち、Workboxが生成するService Workerの出力先を尋ねられます。 ここではpublic
を選択します。
「デプロイ先」ということで build
を選択しそうですが、これではReactが読み込んでくれないので public
に設定します。
この設定にするとdevelopmentビルドで確認することができ、productionビルドの場合はあとで yarn build
コマンドを実行すると build
にService Workerのファイルも配置されます。
そのほかのオプションは特に変更しません。
$ workbox wizard
? What is the root of your web app (i.e. which directory do you deploy)? public/
? Which file types would you like to precache? ico, html, png, json, txt
? Where would you like your service worker file to be saved? public/sw.js
? Where would you like to save these configuration options? workbox-config.js
? Does your web app manifest include search parameter(s) in the 'start_url', other than 'utm_' or 'fbclid' (like '?source=pwa')? No
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.
Workboxのインストール(プロジェクト, devDependencies)
workbox wizard
で生成したWorkboxの設定ファイルからService Workerを生成するにはプロジェクト側にWorkboxを導入します。
PWA対応のテンプレートを使ったReactプロジェクト (--template cra-template-pwa
オプションありでプロジェクトを立ち上げた場合)を参考にしています。不要なパッケージがあるかもしれません。
$ yarn add -D workbox-background-sync workbox-broadcast-update workbox-cacheable-response workbox-core workbox-expiration workbox-google-analytics workbox-navigation-preload workbox-precaching workbox-range-requests workbox-routing workbox-strategies workbox-streams
serviceWorkerRegistration.js の移植
PWA対応のテンプレートを使ったReactプロジェクトにある serviceWorkerRegistration.jsを src
ディレクトリに配置します。
Service Workerの設定
serviceWorkerRegistration.js
で読み込むService Workerのファイル名が異なるのでここで変更します。
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/sw.js`;
index.js
で serviceWorkerRegistration.js
を読み込んでService Workerをregisterするように設定します。
先頭にファイルを読み込むコードを追加します。
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
読み込んだ serviceWorkerRegistration.js
を使ってService Workerを登録するように次のコードを末尾に追加します。
serviceWorkerRegistration.register();
Service Workerの生成
こちらはWorkboxのコマンドを用います。 デフォルトではソースマップも出力されるため 設定を変更するなどでproductionビルドに混入しないよう注意する必要があります(回避方法は未確認)
$ workbox generateSW workbox-config.js
動作確認(localhostで可能)
serviceWorkerRegistration.js
はデフォルトでdevelopmentビルドのPWAを無効にする設定があるため、developmentで確認したい場合はそれを外します。
productionコードであるかどうかの条件分岐があるのでそこを外します。
export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
export function register(config) {
if ('serviceWorker' in navigator) {
そして、devサーバーを起動してブラウザで開発者ツールを開き、ApplicationのService Workersか、LighthouseでProgressive Web Appのチェックを入れて確認できます。
$ yarn start
PWAになりましたね!
本記事ではPWA化までを説明したので、この後は足りない部分を修正したり、実際にホスティングサービスへ公開したりしましょう。
参考
create-react-appで作ったReact SPAにWorkbox-CLIでService Workerをねじ込む | WP Kyoto
https://wp-kyoto.net/replace-workbox-cli-into-create-react-app-app/