はじめに
個人開発を進めていく中で、PWA化を進めたく、学習をしました。
実装の手順も踏まえつつ、備忘録として記載していこうと思います。
※誤りありましたら、ご指摘いただけますと幸いです。
PWAとは
PWAとは、Progressive Web App の略です。
簡単に説明するならば、ウェブアプリをまるでネイティブアプリかのように使用できるようにする技術や設計手法を指します。
例えば、スマートフォンのホームにアイコンを追加し、ネイティブアプリのように起動することができるようになります。
一部のコンテンツはキャッシュされるため、高速で表示をできるだけでなく、予めページを読み込んでおくと、オフラインでも利用可能になります。
また、ネイティブアプリと似てはいるものの、アプリケーションストア(App Store, Google Play)を介してインストールされるようなアプリとは異なり、OSの制限を受けないというメリットもあります。
AndroidやiPhoneそれぞれで異なる言語や開発手法を特別意識することなく、開発を進めることができます。
PWA導入に必要なステップ
主には下記の5ステップを踏むだけで、簡単に導入できるようになります。
①(前提)HTTPSでの提供確認
②manifest.json の作成
③PWA用ライブラリの導入(例:next-pwa)
④ Service Worker の登録(next.config.tsで設定)
⑤ブラウザへのPWA認識設定(_document.tsxのHeadタグなど)
上記のステップ説明の前に、PWAで重要となるService Workerについて軽く説明しておこうと思います。
chrome for developersでは下記のように説明があります。
Service Worker は、ウェブブラウザとウェブサーバー間のプロキシとして機能する特殊な JavaScript アセットです。オフラインアクセスを提供することで信頼性を高め、ページのパフォーマンスを向上させることを目的としています。
この説明で肝となるのが、ウェブブラウザとウェブサーバー間のプロキシとして機能するという部分。
これにより、通信のリクエストレスポンスに手を加えることができたり、キャッシュした内容を返したり、ということが可能となる訳です。
それでは元に戻って、上記の各ステップについて説明していきます。
①(前提)HTTPSでの提供確認
まず前提として、PWA対応させるには、HTTPSによる暗号化が必須となります。
これは、Service Worker がHTTPSを介して提供されるページでしか登録することができないことが理由です。
先述の通りService Workerはウェブブラウザとウェブサーバー間のプロキシとして機能します。
これは便利なように見えますが、裏を返せば通信が暗号化されていなかった場合、リクエストの改変が勝手にできてしまうという危険性が孕んでいるとも言えます。
つまり、暗号化されていない場合は、簡単に他人のページに悪意あるスクリプトを埋め込んだり、フィッシングやマルウェアへの誘導も可能となってしまいます。
そのため、HTTPSによる暗号化が施された安全なサイトでしか使用できない、というわけです。
②manifest.json の作成
そもそもmanifest.jsonとは、という話ですが、これはPWAアプリのプロフィール情報をまとめた設定ファイルになります。
今回設定したファイルの中身は下記のようになっています。
{
"name": "menkatsu",
"short_name": "menkatsu",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#facc15",
"icons": [
{
"src": "/icons/menkatsulogo_192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/menkatsulogo_512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
このように、例えばnameにはホーム画面に表示されるアプリの名称が、start_urlには起動時に開かれるURL(/はトップページ)が、という風に、PWAに関する諸設定がここでまとめられています。
特に、iconsには、正しくホーム画面に表示されるアイコンを指しており、今回は192×192と512×512の2サイズを設定しています。
192はスマホのホーム画面アイコン、512はLINEで画像を送信した時等の、インストール画面用のアイコンとなります。
③PWA用ライブラリの導入(例:next-pwa)
これは実にシンプルで、対象のライブラリをインストールするだけでOKです。
npm install next-pwa
これで、Next.jsでのPWA化が非常に容易になります。
先述のService Workerですが、自分でイチから実装することも可能なのですが、中々に骨の折れる作業ですので、ここはライブラリに頼ることにしましょう。
④ Service Worker の登録(next.config.tsで設定)
さて、PWAライブラリのインストールが完了したところで、Service Workerの登録に移ります。
登録は、next.config.tsに定義を追加する必要があります。
next.config.tsは、Next.js全体のビルド挙動や実行時の挙動を 1 か所でカスタマイズするルート設定ファイルのようなものになります。
ここにPWA設定も追加していきましょう。
実際に作成したnext.config.tsは下記になります。
import type { NextConfig } from 'next';
import nextPWA from 'next-pwa';
// Next.js設定を定義
const baseConfig: NextConfig = {
reactStrictMode: true,
};
// PWA設定を追加
export default nextPWA({
dest: 'public',
register: true,
skipWaiting: true,
})(baseConfig);
NextConfigはNext.jsの型情報であり、TypeScriptでの補完や型チェックを効かせることができるようになります。
加えて、読んで字のごとくですが、nextPWAはNext.jsのPWA化を行うプラグインになります。
続いてbaseConfigですが、ここでは開発モードで潜在的なバグを見つけやすいように、reactStrictModeを設定しています。
最後にnextPWAでPWA設定を追加しています。
ここでの書き方は通常の関数とは異なり少し複雑になっていますが、下記と同義になります。
const withPWA = nextPWA({
dest: 'public',
register: true,
skipWaiting: true,
});
export default withPWA(baseConfig);
withPWAという関数を作成し、作成したwithPWAに、引数としてbaseConfigを渡している、という流れですね。
nextPWAの引数のオブジェクトには今回3つプロパティを指定しています。
destでは生成されるキャッシュファイルの出力先を、registerではService Workerの自動登録を、skipWaitingでは、古いバージョンの Service Worker がある場合でも、待機状態をスキップし、新しいバージョンの Service Worker を有効にします。
今回は最小限の設定にとどめていますが、実際は他にも様々なカスタマイズが可能です。
⑤ブラウザへのPWA認識設定(_document.tsxのHeadタグなど)
さて、それでは最後に、PWAとして認識させるために、_document.tsxをカスタマイズします。
具体的には、_document.tsxはHTML全体の構造を設定する箇所なので、ここのHeadタグにPWA設定を適用させていきます。
実際の例は下記になります。
import { Html, Head, Main, NextScript } from 'next/document';
// HTML全体の構造をカスタマイズを行う
export default function Document() {
return (
<Html lang="en">
<Head>
<link rel="manifest" href="/manifest.json" />
<link rel="icon" href="/icons/menkatsulogo_192.png" />
<link rel="apple-touch-icon" href="/icons/menkatsulogo_192.png" />
<meta name="theme-color" content="#facc15" />
</Head>
<body className="antialiased">
<Main />
<NextScript />
</body>
</Html>
);
}
見ての通り、Headタグ内で様々指定をしています。
linkタグに関しては、manifestで設定ファイルの箇所を、iconでアイコンファイル指定を、apple-touch-iconでiPhone用のホーム画面アイコン(iOSはmanifestを読まないため必要)を指定しています。
metaタグではAndroidのタスクバーやスプラッシュ画面の背景色を指定します。
ここでの内容がブラウザに反映されることで、かなりネイティブアプリのようなUIになります。
実際に導入が成功すると
実際に導入した例を見てみましょう。
私が作成しているラーメン記録アプリ 「mankatsu」 に反映させた結果は下記のようになります。
そしてホーム画面の表示(スクリーンショット)が下記のようになります。
いかがでしょうか。
ホーム画面では、スマホでブラウザを使用した際に上部、ないしは下部に表示されるアドレスバーが表示されず、ネイティブアプリ感がグッと増したように見えます。
まとめ
さて、今回はアプリケーションのPWA化について、備忘録もかねて導入までの流れを説明してみました。
今回は簡易的に触れたPWAですが、かなり奥が深く、更に理解を深めたいと思った分野でもありました。
また今度触れていようかなと思います。
ご覧いただきありがとうございました。