Next.js 製の Web アプリを PWA 化する
こんにちはsemiguraです。
TL;DR
yarn add next-pwa
で PWA 対応用プラグインを導入- manifest.json と各種 favicon を生成し public/ 以下に置く
- _document.jsx で呼び出す
- 確認は Chrome DevTools の Application タブで行う
環境
Next.js 12.0.10 + next-pwa 5.4.4
本題
next-pwa 導入
yarn add next-pwa
next.config.js を書き換え
next.config.js
const withPWA = require("next-pwa"); const runtimeCaching = require("next-pwa/cache"); const config = { pwa: { dest: "public", runtimeCaching, }, }; module.exports = withPWA(config);
注意点
module.exports が複数あると動かない
e.g.
const withPWA = require("next-pwa"); module.exports = { webpack: (config, { isServer }) => { if (!isServer) { config.resolve.fallback.fs = false; config.resolve.fallback.child_process = false; config.resolve.fallback.net = false; config.resolve.fallback.dns = false; config.resolve.fallback.tls = false; } return config; }, }; module.exports = withPWA({ pwa: { dest: "public", runtimeCaching: [] }, });
manifest.json 他を生成
以下2つを使う
- 様々なファビコンを一括生成。favicon generator
- favicon を生成する
- PWA Manifest Generator | SimiCart
- manifest.json を生成する
manifest.json 他を追加
public/manifest.json
{ "theme_color": "#f69435", "background_color": "#f69435", "display": "standalone", "scope": "/", "start_url": "/", "name": "example-app", "short_name": "example-app", "icons": [ { "src": "/android-chrome-36x36.png", "sizes": "36x36", "type": "image/png" }, { "src": "/android-chrome-48x48.png", "sizes": "48x48", "type": "image/png" }, { "src": "/android-chrome-72x72.png", "sizes": "72x72", "type": "image/png" }, { "src": "/android-chrome-96x96.png", "sizes": "96x96", "type": "image/png" }, { "src": "/android-chrome-128x128.png", "sizes": "128x128", "type": "image/png" }, { "src": "/android-chrome-144x144.png", "sizes": "144x144", "type": "image/png" }, { "src": "/android-chrome-152x152.png", "sizes": "152x152", "type": "image/png" }, { "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/android-chrome-256x256.png", "sizes": "256x256", "type": "image/png" }, { "src": "/android-chrome-384x384.png", "sizes": "384x384", "type": "image/png" }, { "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } ] }
_document.jsx を作成
import Document, { Html, Head, Main, NextScript, DocumentContext, DocumentInitialProps, } from "next/document"; class MyDocument extends Document { static async getInitialProps( ctx: DocumentContext ): Promise<DocumentInitialProps> { // eslint-disable-next-line no-return-await return await Document.getInitialProps(ctx); } render() { return ( <Html lang="ja-JP" dir="ltr"> <Head> <meta name="msapplication-square70x70logo" content="/site-tile-70x70.png" /> <meta name="msapplication-square150x150logo" content="/site-tile-150x150.png" /> <meta name="msapplication-wide310x150logo" content="/site-tile-310x150.png" /> <meta name="msapplication-square310x310logo" content="/site-tile-310x310.png" /> <meta name="msapplication-TileColor" content="#000" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="#000" /> <meta name="apple-mobile-web-app-title" content="myapp" /> <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png" /> <meta name="application-name" content="myapp" /> <meta name="theme-color" content="#000" /> <meta name="description" content="this is myapp" /> <link rel="icon" sizes="192x192" href="/icon-192x192.png" /> <link rel="icon" href="/favicon.ico" /> <link rel="manifest" href="/manifest.json" /> </Head> <body> <Main /> <NextScript /> </body> </Html> ); } } export default MyDocument;
確認
確認は Chrome DevTools の Application タブで行う。