PWAスキャフォールドにオフラインフォールバックページを追加
RailsのPWAスキャフォールドに、オフライン時のフォールバックページが追加されました。app/views/pwa/offline.html.erb テンプレート、Rails::PwaController#offline アクション、およびコメントアウトされたルートと Service Worker のサンプルコードが一式提供され、PWAの基本構成が完結します。
背景
RailsのPWAスキャフォールドは manifest.json.erb と service-worker.js を生成しますが、オフラインフォールバックページは含まれていませんでした。ユーザーがネットワーク接続を失った際、ブラウザには表示するものが何もなく、開発者がゼロからオフラインページを実装する必要がありました。
PWAの標準的なパターンは3つの要素で構成されます。マニフェストがアプリを定義し、Service Workerがナビゲーションリクエストのインターセプトを担い、オフラインページがネットワーク障害時の表示を提供します。この3点セットはweb.devやMDNのPWAガイドでも推奨されているアプローチであり、今回の変更はRailsのスキャフォールドをこの標準パターンに対応させるものです。
技術的な変更
今回の変更は、コントローラ・ビュー・ルーティング・Service Workerテンプレートの4ファイルにわたる一貫した追加です。
railties/lib/rails/pwa_controller.rb に offline アクションが追加されました。
def offline
render template: "pwa/offline", layout: false
end
layout: false でレンダリングする既存の manifest および service_worker アクションと同じパターンを踏襲しています。
app/views/pwa/offline.html.erb は外部依存ゼロの自己完結型HTMLです。インラインCSSで中央配置のレイアウトと @media (prefers-color-scheme: dark) によるダークモード対応を実装し、<form action="." method="get"> を使ったリトライボタンを含みます。外部アセットを一切参照しないため、ネットワーク接続がない状況でも確実に表示されます。
config/routes.rb.tt には、既存のPWAルートに並んでコメントアウト済みのルートが追加されています。
# get "manifest" => "rails/pwa#manifest", as: :pwa_manifest
# get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker
# get "offline" => "rails/pwa#offline", as: :pwa_offline
service-worker.js には、オフラインページをキャッシュして提供するサンプルコードがコメントとして追加されました。install イベントで /offline をCache APIに登録し、fetch イベントのナビゲーションリクエストが失敗した際にキャッシュから返すという標準的なパターンが示されています。
// Cache the offline fallback page on install:
//
// self.addEventListener("install", (event) => {
// event.waitUntil(
// caches.open("offline").then((cache) => cache.add("/offline"))
// )
// self.skipWaiting()
// })
//
// Serve the offline fallback page when a navigation request fails:
//
// self.addEventListener("fetch", (event) => {
// if (event.request.mode === "navigate") {
// event.respondWith(
// fetch(event.request).catch(() => caches.match("/offline"))
// )
// }
// })
テストも app_generator_test.rb と plugin_generator_test.rb の両方で app/views/pwa/offline.html.erb が生成ファイル一覧に追加されています。
設計判断
オプトイン方式が一貫して採用されています。オフラインルートは manifest・service_worker と同様にコメントアウトされた状態で生成されるため、開発者が明示的に有効化するまで動作しません。既存のPWA機能との設計の一貫性を保ちつつ、不要な副作用を避けています。
Service Workerのサンプルコードもコメントとして提供されている点が重要です。オフラインフォールバックはルートとテンプレートを追加するだけでは機能せず、Service Workerによるキャッシュ制御が必要です。コメント形式でサンプルを同梱することで、開発者が実装に必要な3つの要素(ルート・テンプレート・Service Worker)を同じ場所で確認できます。
なお、APIモードではPWAテンプレート全体と同様に app/views/pwa/ が除外されるため、オフラインページも生成されません。
まとめ
今回の変更は、manifest・Service Worker・オフラインページという3要素をRailsのスキャフォールドで揃え、PWAの基本構成を完結させるものです。各コンポーネントはコメントアウト済みのオプトイン方式で提供されており、開発者は必要な部分だけを有効化しながら、標準的なPWA実装パターンをスキャフォールドコードから直接学ぶことができます。