Next.jsで作ったブログをAMPとPWAに対応させる
TL;DR
Next.jsのPWA対応というとnext-offlineとかnext-pwaが有名かと思います。しかし、AMPページのキャッシュはこれらがデフォルトで対応していないので、自前でやる必要があります(参考issue)。自分はこの2つのパッケージを使って色々やってて永遠にPWA対応できなかったので、AMPと同時に対応しようとしている人は注意が必要です。
とはいえ、やることはほとんどexample/amp-firstをコピペするだけなのですが...。
publicフォルダの準備
manifest.json
まず、manifest.jsonを用意します。何で用意してもいいですが、必要なものとして以下が挙げられます(参考)。iconとか用意するのはめんどうなので、PWA manifest generatorを使いました。
start_url
name
orshortname
icons
(192 - 512 px)display
また、このiconはmaskableである必要があるので、Maskable.app Editorで変換した後、"purpose": "any maskable"
をiconのプロパティに足します。
とりあえずこのサイトのmanifest.jsonは以下のような感じです。
manifest.json
{
"name": "illumination-k dev",
"theme_color": "#f69435",
"background_color": "#f69435",
"display": "standalone",
"start_url": "/",
"icons": [
{
"src": "/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/icons/icon-256x256.png",
"sizes": "256x256",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
],
"short_name": "ik.dev",
"description": "Homepage of illumination-k"
}
apple touch icon
ここを見てもらったほうが早いですが、PWA対応したいページのヘッダーに
<link rel="apple-touch-icon" href="/icons/icon-192x192.png" />;
を加えておきます。アイコンのサイズは192x192か180x180である必要があります。
serviceworker.js
examples/amp-first/public/serviceworker.jsをコピペしてpublic
に置きます。たぶん、だいたいamp-swです。
serviceworker.js
/* global importScripts, AMP_SW */
importScripts('https://cdn.ampproject.org/sw/amp-sw.js')
/*
This configures the AMP service worker to enhance network resiliency and
optimizes asset caching. This configuration will:
- Cache AMP scripts with a stale-while-revalidate strategy for a longer duration
than the default http response headers indicate.
- Cache valid visited AMP documents, and serve only in case of flaky network conditions.
- Cache and serve an offline page.
- Serve static assets with a cache first strategy.
Checkout https://github.com/ampproject/amp-sw/ to learn more about how to configure
asset caching and link prefetching.
*/
AMP_SW.init({
assetCachingOptions: [
{
regexp: /\.(png|jpg|woff2|woff|css|js)/,
cachingStrategy: 'CACHE_FIRST', // options are NETWORK_FIRST | CACHE_FIRST | STALE_WHILE_REVALIDATE
},
],
offlinePageOptions: {
url: '/offline',
assets: [],
},
})
serviceworkerのregister
examples/amp-first/public/install-serviceworker.htmlをコピペしてpublicに置きます。
install-serviceworker.html
<!DOCTYPE html>
<title>installing service worker</title>
<script type="text/javascript">
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/serviceworker.js')
}
</script>
PWA対応したいページでserviceworkerをインストールする
ampではserviceworkerのインストールはamp-install-serviceworkerで行えます。
PWA対応したいコンポーネントのbodyに以下を入れます。
<amp-install-serviceworker
src="/serviceworker.js"
data-iframe-src="/install-serviceworker.html"
layout="nodisplay"
/>;
offlineページの作成
これよくわかってないので後で調べるかもしれませんが、amp-firstの例ではofflineページが準備されています。コピペして置いておきましょう。serviceworkerのofflinePageOptionなんでしょう。
offline.js
import Layout from '../components/Layout'
export const config = { amp: true }
const Home = () => (
<Layout>
<h1>Offline</h1>
<p>Please try again later.</p>
</Layout>
)
export default Home
結果
以上でPWA対応は完了です。当サイトtopの2020/09/30現在のlighthouse performanceです。
ちなみにWordpress時代はこんなんなので、非常に成長していると言えるでしょう。all 100は難しいですね...。