coiai Logo
Featured

Next.js で PWA を実装する方法【Vercel × Serwist】

この記事ではNext.js(App Router)で PWA を実装する方法のメモを残しておきます。

Meditationアプリに実装してみた知見です。

https://just-meditation.com


Serwist を使う理由(Workbox の後継)

Serwist は Workbox の設計をベースにした最新 PWA ライブラリで、

  • Next.js App Router 対応
  • Precache の自動注入
  • ランタイムキャッシュの柔軟な設定
  • Workbox より軽量

という特徴があります。


導入手順

個人的にpnpm にはまっているので、pnpm を使っていますが、なんでもいいです。

Serwist のインストール

pnpm add @serwist/next serwist

next.config.ts

next.config.ts が以下のようになっているか確認してください。

// next.config.ts
import type { NextConfig } from "next";
import withSerwistInit from "@serwist/next";

const withSerwist = withSerwistInit({
  swSrc: "app/sw.ts",
  swDest: "public/sw.js",
  disable: process.env.NODE_ENV !== "production",
});

const nextConfig: NextConfig = {
  reactStrictMode: true,
  turbopack: {}, // dev は Turbopack
};

export default withSerwist(nextConfig);

app/manifest.json

{
  "name": "Just Meditation",
  "short_name": "Meditation",
  "start_url": "https://hogehoge.com",
  "display": "standalone",
  "background_color": "#000000",
  "theme_color": "#000000",
  "icons": [
    { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
  ]
}

app/sw.ts

/// <reference lib="webworker" />

import { defaultCache } from "@serwist/next/worker";
import {
  Serwist,
  CacheFirst,
  type PrecacheEntry,
  type SerwistGlobalConfig,
  type RuntimeCaching,
} from "serwist";

declare global {
  interface WorkerGlobalScope extends SerwistGlobalConfig {
    __SW_MANIFEST: (PrecacheEntry | string)[] | undefined;
  }
}
declare const self: ServiceWorkerGlobalScope;

const extraRuntimeCaching: RuntimeCaching[] = [
  {
    matcher: ({ request }) => request.destination === "audio",
    handler: new CacheFirst({ cacheName: "audio-cache" }),
  },
];

const serwist = new Serwist({
  precacheEntries: self.__SW_MANIFEST,
  skipWaiting: true,
  clientsClaim: true,
  navigationPreload: true,
  runtimeCaching: [...defaultCache, ...extraRuntimeCaching],
});

serwist.addEventListeners();

app/layout.tsx

メタデータに記述が必要です

// app/layout.tsx
import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "Just Meditation",
  manifest: "/manifest.json",
  icons: [
    { rel: "icon", url: "/icon-192.png" },
    { rel: "apple-touch-icon", url: "/icon-192.png" }
  ],
};

おまけ インストールボタンの実装

インストールボタンのコンポーネントを作成して、Headerに置きました。

// components/InstallPWAButton.tsx
"use client";
import { useEffect, useState } from "react";
import { Button } from "@mui/material";

export default function InstallPWAButton() {
  const [promptEvent, setPromptEvent] = useState<any>(null);

  useEffect(() => {
    window.addEventListener("beforeinstallprompt", (e) => {
      e.preventDefault();
      setPromptEvent(e);
    });
  }, []);

  if (!promptEvent) return null;

  return (
    <Button
      variant="outlined"
      onClick={() => {
        promptEvent.prompt();
      }}
    >
      Install App
    </Button>
  );
}

インストール可能なブラウザでのみ表示されます。

投稿日: 2025年11月23日
カテゴリ: React
タグ: プログラミング
coiai

coiai

この記事もおすすめ

ポッドキャストを取った後Auditionですべきこと

ポッドキャストを取った後Auditionですべきこと

この記事はポッドキャストなどの音声コンテンツを取った後にAuditionで編集する方法について解説しています。 環境 やること 基本的に以下の4つの工程をすると、かなりクオリティアップにつながります! ノイズリダクション 無音部分を選択します。開始地点をi, 終わりをo キーを押すと選択できます。選択できたらエフェクト→ノイズリダクション/リストア→ノイズプリントをキャプチャを押します。 続いて、全体を選択します。cmd, a で全選択になります。エフェクト→ノイズリダクション/リストア→ノイズリダクションを選択します。 以下のようなパネルが表示されうので、ノイズのみをきたりして、削減ちを調整して、良い感じになったら適応ボタンを押します。 シングルバンドコンプレッサ 左のパネルのエフェクトトラックから▶️ボタンを押し、振幅と圧縮→シングルバンドコンプレッッサを選択します。 選択すると下記のようなパネルが開きます。それぞれ、 といった意味があります。設定値は下記画像のようにしています。 設定がめんどくさい場合はプリセットからラジオレベラーを選択してください。 EQ(声をクリアにする) パラメトリックイコライザーを使用します。エフェクト→フィルターとイコライザ→パラメトリックイコライザーを選択します。 私の場合は下記のように設定しています。 無音カット エフェクト→診断→無音をカットをすると左パネルに診断が表示されます。 効果を無音を削除、プリセットをポッドキャストにするとちょうどよくなると思います。設定したら、スキャンボタンを教えて、全て削除で無音がカットされます。 かなりカットされてしまうので、短いCM等に使うのはありかなという感じです。 参考 Adobe 無音カット https://helpx.adobe.com/jp/audition/using/strip-silence.html

この記事を書いた会社

株式会社coiaiは、「想像できることを美しく実現」を掲げ、XR・Web・アプリ・システム開発およびDX支援を行う会社です。 創業2022年、東京都練馬区に本社を置き、要件のヒアリングからPoC(概念実証)、本番運用まで一貫して伴走します。 まずはお気軽にご相談ください。

商号株式会社 coiai創業2022年1月設立2025年1月23日資本金1,500,000円(設立時点)本社所在地東京都練馬区関町北 3-6-9代表者代表取締役 竹村 啓佑 / 代表取締役 服部 陽良

主なご相談内容

会社概要・役員紹介を見る

詳しい会社情報は会社概要ページでご覧いただけます。

資料請求・無料相談

導入要件のヒアリングからPoC、本番運用まで伴走します。まずはお気軽にご相談ください。

お問い合わせの前に 個人情報保護方針 をご確認ください。