Next.js と TypeScript で、PWAを構築する

TwitterFacebookHatena

TL;DR

この記事では、Next.js と TypeScript による Progressive Web Apps (PWA) の構築方法を深掘りします。PWA の基礎的な考え方から、具体的なソースコードによる実装例、そして Emotion を活用したスタイリングまでを一挙に解説します。

開発環境 バージョン
Next.js 13.4.4
TypeScript 5.0.4
Emotion 11.11.0
React 18.2.0

PWA とは?

PWA(Progressive Web Apps)とは、「進歩的なウェブアプリ」のことを指します。…いや、進歩的ってなんのことやねんって感じかと思いますので、おもちゃのロボットを例に出して、PWA について考えてみましょう。

例えば、ロボットのおもちゃがあるとします。

ただのおもちゃとして遊ぶこともできますが、バッテリーを入れると動き出すように、新たな機能が追加されるともっと楽しくなりますよね。さらに、リモコンを使って操作することができたら、その楽しさはもっと増すでしょう。

PWA も同じです。ウェブサイトは、そのままでも情報を見ることができます。それが「おもちゃ」です。しかし、特殊な技術を使って「バッテリー」を入れることで、ウェブサイトは「動き出し」、いくつかの特別な機能を持つようになります。例えば、インターネットに接続していない時でもウェブサイトの内容を見ることができるようになったり、スマートフォンのホーム画面にウェブサイトのアイコンを追加して、アプリのように直接開けるようになったりします。

このように、PWA はウェブサイトをより便利で使いやすくするための技術なんですね。これが「進歩的なウェブアプリ」、つまり PWA と呼ばれる理由です。

Progressive Web Apps (PWA) は、ウェブアプリケーションをモバイルアプリのように振る舞わせるための技術です。この考え方では、ウェブアプリケーションはインターネット接続がなくても動作し、ユーザーに高速で滑らかな体験を提供します。

PWA の主な特徴は以下の通りです。

  • リアルタイム性:PWA は最新の情報を提供します。
  • レスポンシブ:PWA は任意のデバイス(デスクトップ、モバイル、タブレット)で動作します。
  • オフライン対応:Service Workers の利用により、オフライン時でも動作します。

PWA のメリット

PWA の具体的なメリットは、以下の通りです。

オフライン対応

Service Worker を用いることで、インターネット接続がない状況でもウェブページを表示することが可能です。キャッシュを利用することで、アプリの一部あるいは全部の機能をオフラインでも使用できます。

ホーム画面への追加

ユーザーは PWA をスマートフォンやタブレットのホーム画面に追加できます。これにより、ネイティブアプリケーションのようにアプリを起動でき、より簡単にアクセスできます。

プッシュ通知

PWA はプッシュ通知をサポートしています。これにより、ユーザーエンゲージメントを高め、ユーザーに最新情報を直接伝えることができます。

レスポンシブ

PWA はデバイスの種類や画面サイズに関係なく最適な表示がされます。これにより、スマートフォン、タブレット、デスクトップなど、あらゆるデバイスで一貫したユーザーエクスペリエンスを提供できます。

アップデートの簡単さ

PWA はウェブベースのアプリケーションなので、アップデートを行う際にユーザーに何も手間をかけさせる必要がありません。新しい内容はユーザーがアプリを開くたびに自動的に提供されます。

コスト効率

PWA は一つの基盤で複数のプラットフォームに対応できます。iOS と Android の両方に対応するネイティブアプリをそれぞれ作るよりも、開発・メンテナンスのコストと時間を大幅に節約できます。

検索エンジン対策(SEO)

PWA はウェブベースのため、SEO 対策が可能です。これにより検索エンジンからの流入を得やすくなります。

manifest.json

Next.js を使って PWA を構築する際の主なステップは、manifest.json の作成と Service Worker の設定です。

manifest.jsonとは、ウェブアプリケーションの設定を記述するためのファイルです。これは PWA(Progressive Web Apps)の一部として使用され、ウェブサイトがスマートフォンやタブレットなどのデバイスでどのように表示されるべきかを定義します。

たとえば、ウェブサイトの名前やアイコン、テーマ色、スタート URL(アプリが開いた時に最初に表示するページ)などを指定できます。また、ウェブアプリケーションが全画面で表示されるべきか、ブラウザのナビゲーションバーを表示するべきかなど、表示モードも定義できます。

以下に、manifest.jsonの例を示します:

{
  "short_name": "MyApp",
  "name": "My Awesome App",
  "icons": [
    {
      "src": "/favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    }
  ],
  "start_url": "/",
  "background_color": "#ffffff",
  "display": "standalone",
  "theme_color": "#000000"
}

これにより、ウェブサイトはユーザーのデバイスにインストールされ、ネイティブアプリケーションのように動作するようになります。これが PWA の大きな特徴で、その実現にはmanifest.jsonが欠かせません。

PWA Manifest のジェネレーターは次のようなものがあります。

PWABuilder は、Microsoft が提供するこのツールで、ウェブサイトの URL を入力するだけで、自動的に manifest.json を作成します。また、提供されたマニフェストをカスタマイズして、必要な情報を追加したり編集したりすることもできます。

Manifest Generator は、手動でウェブアプリマニフェストを作成するのに役立ちます。必要な情報をフォームに入力すると、それに基づいて manifest.json が生成されます。

これらのツールを使うことで、manifest.json の作成がより簡単になります。しかし、自分で作成することで、必要な設定を自由に調整できるという利点もあります。

Next.js で、PWA を実装

それでは Next.js で実装してみましょう。まず、public/ ディレクトリに manifest.json を作成します。

// public/manifest.json

{
  "name": "Next.js PWA",
  "short_name": "NextPWA",
  "description": "An example of a PWA using Next.js and TypeScript",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#0070f3",
  "icons": [
    {
      "src": "/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

次に、Service Worker を設定します。Service Worker

を活用するためには、Next.js プロジェクトに next-pwa パッケージを導入します。

npm install next-pwa

next.config.js ファイルに次の設定を追加します。

// next.config.js

const withPWA = require('next-pwa')

module.exports = withPWA({
  pwa: {
    dest: 'public',
    register: true,
    skipWaiting: true,
  },
})

これで、Next.js と TypeScript で PWA を実装できました。ブラウザの DevTools を使って、PWA が正しく機能していることを確認できます。

PWA を更に進化させる

ここからは、さらにテクニカルな観点から PWA を改良する方法を見ていきます。例えば、ユーザーのオフライン時の体験を向上させるために、特定のページを事前にキャッシュしておくことがあります。

// next.config.js

const withPWA = require('next-pwa')

module.exports = withPWA({
  pwa: {
    dest: 'public',
    register: true,
    skipWaiting: true,
    runtimeCaching: [
      {
        urlPattern: /^https:\/\/example.com\/api\/.*/,
        handler: 'NetworkFirst',
        options: {
          cacheName: 'api-cache',
          expiration: {
            maxEntries: 10,
            maxAgeSeconds: 24 * 60 * 60, // 24 hours
          },
          networkTimeoutSeconds: 10,
        },
      },
    ],
  },
})

この設定により、https://example.com/api/ から始まるリクエストはすべてキャッシュされます。また、10 秒以内にネットワークからの応答がない場合、Service Worker はキャッシュからの応答を返します。

以上のコードでは、css 関数を使って CSS プロパティを JavaScript オブジェクトとして記述し、その後にテンプレートリテラルを使って CSS スタイルを直接記述しています。

以上が、Next.js と TypeScript を用いて PWA を実装し、Emotion を使用してスタイリングする方法についての解説でした。

Next.js と TypeScript で、PWAを構築する