PWAスキャフォールドにオフラインフォールバックページを追加

rails/rails

RailsのPWAスキャフォールドに、オフライン時のフォールバックページが追加されました。app/views/pwa/offline.html.erb テンプレート、Rails::PwaController#offline アクション、およびコメントアウトされたルートと Service Worker のサンプルコードが一式提供され、PWAの基本構成が完結します。

背景

RailsのPWAスキャフォールドは manifest.json.erbservice-worker.js を生成しますが、オフラインフォールバックページは含まれていませんでした。ユーザーがネットワーク接続を失った際、ブラウザには表示するものが何もなく、開発者がゼロからオフラインページを実装する必要がありました。

PWAの標準的なパターンは3つの要素で構成されます。マニフェストがアプリを定義し、Service Workerがナビゲーションリクエストのインターセプトを担い、オフラインページがネットワーク障害時の表示を提供します。この3点セットはweb.devやMDNのPWAガイドでも推奨されているアプローチであり、今回の変更はRailsのスキャフォールドをこの標準パターンに対応させるものです。

技術的な変更

今回の変更は、コントローラ・ビュー・ルーティング・Service Workerテンプレートの4ファイルにわたる一貫した追加です。

railties/lib/rails/pwa_controller.rboffline アクションが追加されました。

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.rbplugin_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実装パターンをスキャフォールドコードから直接学ぶことができます。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
8b36222b

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的な変更、設計判断、まとめがすべて含まれており、「総論→各論→結論」の構成が明確です。PWAの基本構成を完結させるという変更の意義が、結論でリード文とは異なる表現で述べられています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きのシンタックスハイライト(`言語:ファイルパス`)およびGitHubのPRリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

PWA、Service Worker、Railsのスキャフォールドに関する知識を前提としており、専門知識を持つエンジニアという対象読者に適合した内容です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論から各論へ展開し、各段落がトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が守られており、非常に読みやすい構造になっています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているコードブロック(PwaController、routes.rb.tt、service-worker.js)は、提供されたDiffの内容とファイル名を正確に反映しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「PWAスキャフォールド」「オフラインフォールバック」「オプトイン」などの技術用語が、PRの文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

「layout: false の採用理由」「オフラインページの自己完結性」「オプトイン方式の採用」など、技術的な説明がすべてPR情報とDiff内容によって裏付けられており、正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(例:web.devやMDNでの推奨、APIモードでの除外など)は、PRのDescriptionで直接言及されており、ハルシネーションは見られません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#57184)が正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトルはPRのタイトル「Add offline fallback page to the PWA scaffold」を忠実に反映しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事に含まれる情報はすべてPR内で提供されたものであり、サポート状況やリリース日程といったPR外の知識は含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

「含まれていませんでした」「追加されました」といった時間表現が、PRがもたらした変更の前後関係を正確に記述しています。