К основному контенту

Паттерн · TypeScript

PWA на Next.js: Serwist, manifest и офлайн-страница

Паттерн подключения Progressive Web App в App Router: @serwist/next, web app manifest, precache и fallback offline.

Уровень: среднийОценка времени: ~1 день

Serwist интегрируется в Next.js 15+ без eject: manifest в public, SW через @serwist/next, офлайн-fallback и install UI на клиенте.

  • HTTPS обязателен
  • manifest и иконки в public
  • precache только критичных URL
  • push требует VAPID и отдельного API
  • на iOS push только в standalone

Фрагмент описывает минимальный контур PWA для маркетингового сайта на Next.js: manifest, service worker через Serwist, офлайн-страница и опционально Web Push. Полная услуга с приёмкой и ценами — на странице PWA.

Структура файлов

public/
  manifest.webmanifest   # или app/manifest.ts (Metadata API)
  icons/icon-192.png
  icons/icon-512.png
src/
  app/sw.ts              # Serwist SW entry
  app/offline/page.tsx   # fallback при отсутствии сети
  components/pwa/PwaInstallGuide.tsx
  lib/push/              # VAPID, subscribe API, client helpers

Manifest (минимум)

{
  "name": "Название компании",
  "short_name": "Бренд",
  "start_url": "/",
  "scope": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#0f172a",
  "icons": [
    { "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any maskable" },
    { "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }
  ]
}

Свяжите manifest в layout.tsx через metadata.manifest или <link rel="manifest" href="/manifest.webmanifest" />.

Serwist в next.config

import withSerwistInit from '@serwist/next'

const withSerwist = withSerwistInit({
  swSrc: 'src/app/sw.ts',
  swDest: 'public/sw.js',
  disable: process.env.NODE_ENV === 'development',
})

export default withSerwist(nextConfig)

В src/app/sw.ts — precache критичных маршрутов и navigationPreload, fallback на /offline/ для document-запросов.

Install UI

Блок с табами iOS / Android / Desktop (см. PwaInstallGuide) показывает пошаговую установку. На iOS нельзя программно вызвать install — только инструкция для Safari.

Push (опционально)

  1. Сгенерировать VAPID: node scripts/tooling/generate-vapid-keys.mjs
  2. Сервер: VAPID_PRIVATE_KEY, публичный ключ — NEXT_PUBLIC_VAPID_PUBLIC_KEY при сборке или VAPID_PUBLIC_KEY в .env + runtime /api/push/config/
  3. Клиент: Notification.requestPermission()pushManager.subscribe() → POST /api/push/subscribe/
  4. Smoke-тест на сервере: node scripts/push-smoke-test.mjs и с рассылкой PUSH_BROADCAST_SECRET=... node scripts/push-smoke-test.mjs --send

Приёмка

  • Lighthouse PWA-блок (не единственный критерий, но полезный ориентир).
  • Установка на реальном iPhone и Android.
  • Офлайн после первого визита.
  • display-mode: standalone в DevTools → Application.
  • Заявки из PWA помечаются отдельно в CRM/Telegram (см. detect-client-install).

Связанные материалы

Нужно внедрить под ваш домен и стек?

Короткая форма: имя, телефон и сайт. После отправки — ответ с порядком работ и ориентиром по этапам; задачу уточняют при контакте.

Дмитрий МануйловДмитрий МануйловЗаявку читает лично, не менеджер
Написать в Telegram
  • Смета с границами этапов
  • Без спама и навязчивых звонков