Next.js14でPWA構築してみた

# 概要
~~Next.js13でNextPWAを使用しPWA環境の導入を順を追って紹介していきます。~~
（2024/9/3追記）
Next.js14に対応しました。
今回は初期環境構築とインストールができるところまでです。
（今後プッシュ通知機能の実装も別記事で書くかも？）

# PWA(Progressive Web App)とは
> PWAとは、新しいウェブ API と伝統的なプログレッシブな拡張戦略を使用し、クロスプラットフォームのウェブアプリケーションにネイティブアプリと同様の使い勝手をもたらすウェブアプリのことです。

https://developer.mozilla.org/ja/docs/Web/Progressive_web_apps

簡単に説明するとWebアプリでありながらネイティブアプリの利点を取り入れてネイティブアプリっぽいアプリの開発を実現する技術のことです。
Webアプリと同様にHTML、CSS、Javascriptで構成されているためWebエンジニアにはなじみのある技術での開発が可能です。
この技術を使用している有名なアプリケーションにX（旧Twitter）やYoutubeなどがあります。（QiitaもPWAに対応してます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707793/733c4b81-a190-5255-1b44-75003052690b.png)
ブラウザからだとこんな感じでアプリがインストールできます。

その他にネイティブアプリの利点として下記のような技術を実現しています。
- スマホやデスクトップにインストール可能
- ブラウザやハードの環境の違いに左右されない
- オフラインでも閲覧可能
- プッシュ通知の送信/受け取り
- ブラウザを経由しないシームレスなアクセス

# Next.js13環境でPWA構築
それではNext.js13にPWAを導入してみましょう。
## 1. プロジェクトの作成
いつものようにCreateNextAppして移動する。
今回はsrcディレクトリもappルータも両方使います
```powershell
npx create-next-app pwa-practice --typescript

cd .\pwa-practice\
```
## 2. next-pwaのインストール
npmかyarnを使用してnext-pwaをインストールする。
```powershell
# npm
npm install next-pwa

# yarn
yarn add next-pwa
```

## 3. manifestファイルの作成
手動で作成してもいいのですが、既存に便利な生成ツールがあるので今回はそれをお借りします。

https://progressier.com/pwa-manifest-generator

上記のサイトでアプリのマニフェスト設定を行うことができます。
![スクリーンショット 2024-09-03 12.00.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707793/45df103b-7397-26a3-c709-37197566a807.png)


| 項目 | 概要 |
| :--- | :------------------------ |
| Name | アプリ名                   |
|ShortName | nameが表示しきれない端末で表示するための短いアプリ名<br>（基本上と一緒でいい） |
|Display | 表示モードの設定。指定したモードに対応していない場合<br>代替のモードが自動的に設定される<ul><li>fullscreen：全画面表示（代替表示：standalone）</li><li>standalone：ネイティブアプリと同等の外見（代替表示：minimal-ui）</li><li>minimal-ui：アプリのような見た目に加え、ブラウザと近いUIを表示（代替表示：browser）</li><li>browser：アプリ判定ではなくなりインストールもできなくなる</li></ul>|
|Description|ブラウザ検索時などに表示されるアプリの概要|
|Scope|アプリを構成するページの範囲を指定する<br>通常`/<プロジェクト名>/`とするのが良いらしい|
|StartUrl|アプリ起動時に最初に表示されるページのURL|
|Theme|アプリのテーマカラーの指定|
|Background|アプリ起動時のスプラッシュ画面の背景色|
|Icons|アプリに設定するアイコン（アップロードした画像から自動的にリサイズしてくれる）|

上記のサイトで生成されたもので最低限構築はできます。
他にもいろいろ設定できますが詳しくは下記のサイトで説明されているので参考までに。

https://developer.mozilla.org/ja/docs/Web/Manifest

下の画像のようにアイコン画像4つとmanifestファイルがダウンロードできれば大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707793/749f0518-eee0-6ec4-80ea-8e859aca2025.png)

## 4. プロジェクトにmanifestファイルを導入
導入する前に生成された`manifest.webmanifest`を`manifest.json`に書き換える必要がある。
ファイルの中身すべてを`public`ディレクトリに移す。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707793/8cc76a50-5763-00d8-6ee9-898c4f1df6ef.png)

次に`src>app>layout.tsx`の中身を下記のように編集し`manifest.json`をインポートする
```layout.tsx
  return (
    <html lang="en">
      {/* headタグとその中にアイコンやテーマカラー、manifestを記述する */}
      <head>
        <link rel="manifest" href="/manifest.json" />
        <link rel="apple-touch-icon" href="/icon.png"></link>
        <meta name="theme-color" content="#b8e986" />
      </head>
      <body className={inter.className}>{children}</body>
    </html>
  )
```

## 5. next.config.jsを設定する
下記のように`next.config.js`にnext-pwaモジュールの設定を追記する
```next.config.js
import nextPWA from 'next-pwa';

const withPWA = nextPWA({
  dest: 'public',
  register: true,
  skipWaiting: true,
});

const nextConfig = withPWA({
  reactStrictMode: true,
});

export default nextConfig;
```

## 6. 起動して確認してみよう
```bash
npm run dev
```

いつものようにサーバーを起動するとURLの欄にアプリインストールボタンが追加されているはずです![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707793/1cc8b05f-59f2-79af-4088-dff02ac7434e.png)
インストールが完了するとデスクトップにショートカットが作成されデスクトップアプリとして実行されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707793/64ad5ad7-1c3d-21b2-3fd4-377bf05d3af0.png)
これでPWAの導入が完了しました。

## 7. gitignoreの設定
アプリを実行したときに気づいた人もいるかもしれませんが、PWAが実行されると下記の4つのファイルが生成されます。
- sw.js
- sw.js.map
- workbox-***.js
- workbox-***.js.map

これらはPWA実行時に毎度更新されてしまうのでプッシュする前にあらかじめ`.gitignore`で取り除いておきましょう。
下記のように追記してあげればignored filesに追加されるはずです
```.gitignore
# next-pwa
**/public/sw.js
**/public/sw.js.map
**/public/workbox-*.js
**/public/workbox-*.js.map
```

## 8. developmentでPWAを無効にする
next.jsの開発環境では開発中にPWAを実行すると下記のようなwarningがログに流れるはずです。
```terminal
⚠ GenerateSW has been called multiple times,
perhaps due to running webpack in --watch mode.
The precache manifest generated after the first call may be inaccurate!
Please see https://github.com/GoogleChrome/workbox/issues/1790 for more information.
```
これは開発中にのみ発生するエラーになるので`next.config.js`に下記のように追記してあげると解消することができます。
```next.config.js
/** @type {import('next').NextConfig} */

const withPWA = require('next-pwa')({
  dest: 'public',
  register: true,
  skipWaiting: true,
  // ↓ここ
  disable: process.env.NODE_ENV === "development",
})

module.exports = withPWA({
  //next.js config
  reactStrictMode: true,
})
```

# あとがき
今回はNext.js14でPWAを導入する方法を解説しました。
意外と参考文献が少なかったのと、自分としても今後の個人開発で作品のPWA対応を進めていきたいと考えていたのでメモ代わりにまとめれてよかったです。
導入自体もとっても簡単なのでWEBアプリのレスポンシブ対応させる意義が増し、今後の開発やWEBデザインのモチベーションにもつながるんじゃないでしょうか？