📲

【Next.js App Router × PWA】「屁」を記録する専用端末? アプリをネイティブ化する

に公開2件

0. はじめに - なぜ「屁」のアプリをネイティブ化したのか?

本記事では、このWebアプリをPWA(Progressive Web App)として「専用端末化」する技術的な軌跡を解説します。

技術的なモチベーション

He-koitaが目指すのは、「ハイテク計器」 としての世界観です。
ブラウザのURLバーが表示されている状態では、どうしても「Webサイトを見ている」という感覚が拭えません。
「ホーム画面からワンタップで起動し、全画面で地図と計器が表示される。これは、観測員がまるで専用の観測端末を手にしたような没入感を得るための、システム必須要件でした。」

結論

Next.js App Router環境で @ducanh2912/next-pwa を採用し、PWA(Progressive Web App)化に成功しました。
本記事では、その実装過程と、特にiOSにおける「専用端末化(display: standalone)」のハマりどころについて解説します。


1. PWAとは? - Webアプリをネイティブアプリのように

PWA(Progressive Web App)は、Web技術を使ってネイティブアプリのようなユーザー体験を提供する仕組みです。

  • ホーム画面に追加可能: アプリストアを経由せず、ブラウザから直接インストールできます。
  • URLバー非表示: display: standalone モードにより、ブラウザのUIを排除して全画面表示が可能です。
  • オフライン動作: Service Workerによるキャッシュ制御で、ネットワークが不安定でも動作します(今回はリアルタイム性が重要なのであまり重視していませんが)。

2. 技術選定 - @ducanh2912/next-pwa の採用

Next.js App Router環境でPWAを実装するためのライブラリはいくつか存在しますが、今回は @ducanh2912/next-pwa を選定しました。

選定理由

  1. App Router 完全対応: 従来の next-pwa はメンテナンスが停滞しており、App Routerでの動作に不安がありましたが、このフォーク版はApp Routerを意識してメンテナンスされています。
  2. 設定の容易さ: next.config.ts をラップするだけで、Service Workerの生成やWorkboxの設定を自動化してくれます。

3. 実装のステップ - He-koita PWA化の軌跡

Step 1: ライブラリの導入と基本設定

まず、パッケージをインストールします。

pnpm add @ducanh2912/next-pwa

次に、next.config.ts (または .js, .mjs) を設定します。

next.config.ts
import type { NextConfig } from 'next';

const withPWA = require('@ducanh2912/next-pwa').default({
  dest: 'public',
  register: true,
  skipWaiting: true,
  disable: process.env.NODE_ENV === 'development', // 開発時は無効化
});

const nextConfig: NextConfig = {
  // ...その他の設定
};

export default withPWA(nextConfig);

これだけで、ビルド時に public/sw.js と public/workbox-*.js が自動生成されます。

Step 2: manifest.json の作成と最適化

PWAとして認識されるためには、Web App Manifestが必要です。
Next.js App Routerでは、src/app/manifest.ts を作成することで、TypeScriptを使って動的にマニフェストを生成できます。

ここで最も重要なのが、display: 'standalone' の設定です。

src/app/manifest.ts
import { MetadataRoute } from 'next';

export default function manifest(): MetadataRoute.Manifest {
  return {
    name: 'He-koita - へーこいた',
    short_name: 'He-koita',
    description: '解き放て。その衝撃を可視化せよ。',
    start_url: '/',
    display: 'standalone', // ← これが「専用端末」化の鍵!
    background_color: '#000000',
    theme_color: '#000000',
    icons: [
      {
        src: '/icons/logo_144.png',
        sizes: '144x144',
        type: 'image/png',
        purpose: 'any',
      },
      // ...その他のサイズ
    ],
  };
}

Step 3: メタデータの設定 (layout.tsx)

iOS Safariなど、一部のブラウザやOSではマニフェストだけでは不十分な場合があります。
src/app/layout.tsx のMetadata APIを使って、PWA関連のメタタグを出力します。

src/app/layout.tsx
import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'He-koita - 屁こいた',
  // ...
  manifest: '/manifest.json', // 自動生成されるパス
  appleWebApp: {
    capable: true, // iOSでPWAとして動作させる
    statusBarStyle: 'black-translucent', // ステータスバーを透過させる
    title: 'He-koita',
  },
};

export const viewport = {
  themeColor: '#000000', // アドレスバー等の色
};

4. ハマりどころと解決策 - 泥沼と狂気

ここからが本題です。設定は正しいはずなのに、期待通りに動かない。そんなPWAのハマりどころについて共有します。

ポイント①: display: standalone が効かない? - iOSの罠

課題: Androidでは期待通りURLバーが消えてアプリ化するのに、iOS (Safari) で「ホーム画面に追加」しても、起動するとただのSafariのブックマークとして開いてしまう(URLバーが消えない)。

原因:
iOSにおいて display: standalone を有効にするには、manifest.json だけでなく、<meta name="apple-mobile-web-app-capable" content="yes"> が必須級に重要です。
また、Safariのキャッシュ が強力すぎて、manifest.json の変更(displayモードの変更など)が反映されていないことが多々あります。

解決策:

  1. layout.tsx で appleWebApp: { capable: true } を確実に設定する。
  2. Safariのキャッシュを削除する。これに尽きます。「設定 > Safari > 履歴とWebサイトデータを消去」を行わないと、いつまで経っても古いマニフェストが使われ続けることがあります。
  3. 一度ホーム画面に追加したアイコンは削除し、再度追加し直す。

ポイント②: アイコンが反映されない

課題: ホーム画面に追加したアイコンが、指定したロゴではなく、サイトのスクリーンショットやデフォルトのファビコンになってしまう。

原因:

  • アイコンのパスが間違っている。
  • apple-touch-icon の指定がない(iOSの場合)。
  • 画像サイズが不適切。

解決策:
layout.tsx の icons プロパティで、apple 用のアイコンを明示的に指定します。

export const metadata: Metadata = {
  // ...
  icons: {
    icon: '/icons/logo_144_clear.png',
    apple: '/icons/logo_144_clear.png', // ← iOS用
  },
};

ポイント③: next-pwa 環境でのデバッグ

PWAのデバッグは、PCのChrome DevToolsが便利です。
「Application」タブを開き、「Manifest」セクションを確認します。
ここにエラーや警告が出ていないか、display が standalone になっているかをチェックしましょう。

また、「Service Workers」セクションで、SWが正しく登録され、Running状態になっているかも確認が必要です。


5. PWA化の成果 - 「専用アプリ」として稼働

苦労の末、He-koitaは無事に「専用アプリ」として稼働しました。

ホーム画面に追加されたアイコンをタップすると、スプラッシュ画面を経て、URLバーのない全画面でアプリが起動します。
黒を基調としたUIが画面の端まで広がり、まるで最初からインストールされていたネイティブアプリのような佇まいです。

これにより、「Webサイトを見ている」感覚は消え去り、「今、俺はガスを観測しているんだ」 という没入感が生まれました。


6. おわりに - 技術の無駄遣いの先へ

PWAは、Web技術だけでネイティブアプリに肉薄する体験を作れる強力な武器です。
特に、He-koitaのような「世界観」を重視するアプリにおいては、その効果は絶大です。

たかが「屁」を記録するアプリに、ここまでの技術と情熱を注ぎ込む。
これこそが、エンジニアの正しい技術の無駄遣いではないでしょうか。

He-koitaはこれからも、無駄に洗練された技術を追求し、進化し続けます。


観測要請: 「あなたの『放出』も、He-koita専用アプリで記録しませんか?」

📱 Webアプリ: https://he-koita.com/
⚡️ 燃料を供給する: Buy Me a Coffee

Discussion

masa5714masa5714

Androidに限り、Richer UIというものが使えます。

https://developer.chrome.com/blog/richer-pwa-installation?hl=ja

https://www.suzukikenichi.com/blog/richer-pwa-install-ui-displaying-scheenshots-and-description/

スクショを manifest.json に追加するだけで適用され、手軽にアプリインストール感が出るので、ぜひ取り入れてみてください!(Richer UI全然知られておらず Android勢 として布教したくコメントさせて頂きました。)

1
He-koitaHe-koita

貴重な情報ありがとうございます。参考にさせていただきます。