Me gusta construir herramientas que no solo funcionan - ellos Mi equipo ha estado en las trincheras de Next.js lo suficiente para saber exactamente lo que duele. - un paquete drop-in que conecta el soporte completo de PWA en tu aplicación Next.js sin que te rompas el cabello. Sal de tu camino next-pwa-pack The Backstory (aka: Por qué escribí esta cosa) Cada vez que un cliente mencionaba “suporte PWA”, me abrazaba. He probado las bibliotecas existentes. demasiada magia. tonos de config. o simplemente completamente incompatible con — que, por cierto, hemos adoptado plenamente. App Router Revalidación del servidor cache. Integración de App Router. Fácil sincronización entre tabs. API limpia para administrar la caché desde el backend. En lugar de eso, terminé escribiendo trabajadores de servicio a mano. Tuning cache TTLs. Tratando con la lógica de actualización. Gestionar clientes estables. Limpiando manualmente las cachés cada vez que enviamos. Y ni siquiera me ponga en marcha en los usuarios que no ven las actualizaciones hasta que se refresquen. Necesitaba algo simple, predecible y probado en batalla, así que lo construí. Edificio Lo que entró en ella Nuevo paquete Nuevo paquete Paso uno estaba escribiendo un trabajador de servicio mínimo: Caches HTML con TTL. Gestión de activos estáticos. Funciona fuera de línea, como un verdadero PWA debería. Luego agregé un sistema de mensajería para que el cliente pudiera hablar con el trabajador del servicio, por ejemplo, para romper una caché o deshabilitar completamente la caché. Luego escribí algunos guiones: Copie automáticamente sw.js, manifest.json y offline.html en su proyecto. Injecte una acción del servidor llamada revalidatePWA que puede usar en cualquier lugar (rutas de API, acciones del servidor, componentes del servidor - tome su elección). Para el soporte completo de App Router y SSR/Edge, he envuelto todo en una función de orden superior: Una importación, una llamada – hecho. withPWA También he construido en la pestaña de sincronización. porque los usuarios abrir su aplicación en 3 pestañas y esperar que se actualicen mágicamente en sincronía. + de los acontecimientos . Will localStorage storage El resultado? Un paquete que sólo funciona. No config magia negra. No reescribir las partes centrales de su aplicación. Lo que obtendrás con Nuevo paquete Nuevo paquete Una vez instalado, obtendrá: Registro del trabajador del servicio fuera de la caja - sin boilerplate. Fallback fuera de línea con un personalizable offline.html. Los archivos de copia automática que puede ajustar (manifest, SW, etc.). API de control de caché: limpio, actualización, deshabilitación, todo de forma programática. Sincronización entre pestañas: no hay contenido estancado en las configuraciones de pestañas múltiples. Panel de desarrollo para el estado PWA en tiempo real durante el desarrollo local. Soporte de revalidación del lado del servidor a través de acciones del servidor, rutas de API o integraciones de webhook externas. Puedes descargar el paquete aquí: https://github.com/dev-family/next-pwa-pack Qué sucede cuando lo instalamos El script de instalación copia automáticamente el boilerplate de PWA en : /public sw.js – su trabajador de servicio con lógica de caché. offline.html – página de retroceso para el modo offline. manifest.json – ajusta para ajustarte a tu aplicación. ⚠️ Los archivos existentes no se sobreescribirán - respeta su configuración. Si desea activar la copia de forma manual: node node_modules/next-pwa-pack/scripts/copy-pwa-files.mjs # or npx next-pwa-pack/scripts/copy-pwa-files.mjs Acción del servidor También se añade a su o Dependiendo de la estructura de su archivo: revalidatePWA app/actions.ts src/app/actions.ts "use server"; export async function revalidatePWA(urls: string[]) { const baseUrl = process.env.NEXT_PUBLIC_HOST || "http://localhost:3000"; const res = await fetch(`${baseUrl}/api/pwa/revalidate`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ urls, secret: process.env.REVALIDATION_SECRET, }), }); return res.json(); } Si ese archivo no aparece, puede ejecutarlo: node node_modules/next-pwa-pack/scripts/copy-pwa-server-actions.mjs Configurando su Manifiesto.json Manifiesto.json Después de instalar, no olvide personalizar : /public/manifest.json { "name": "My App", "short_name": "App", "description": "My amazing PWA app", "start_url": "/", "display": "standalone", "background_color": "#ffffff", "theme_color": "#000000", "icons": [ { "src": "/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" } ] } Descarga tus iconos en o tweak los caminos arriba. nada fantástico. public/icons/ Inicio > Wire It Up Envuelva su layout en el Y la magia se mueve en: PWAProvider import { PWAProvider } from "next-pwa-pack"; export default function layout({ children }) { return <PWAProvider>{children}</PWAProvider>; } Si desea que la revalidación funcione desde el lado del servidor, también tendrá que actualizar su middleware: // /middleware.ts import { withPWA } from "next-pwa-pack/hoc/withPWA"; function originalMiddleware(request) { // your logic here return response; } export default withPWA(originalMiddleware, { revalidationSecret: process.env.REVALIDATION_SECRET!, sseEndpoint: "/api/pwa/cache-events", webhookPath: "/api/pwa/revalidate", }); export const config = { matcher: ["/", "/(ru|en)/:path*", "/api/pwa/:path*"], }; Las opciones de HOC: originalMiddleware: su middleware base (por ejemplo, para i18n o auth). revalidacionSecret: token secreto para bloquear la revalidación de caché. sseEndpoint: SSE stream path (cambiar si es conflictivo). webhookPath: endpoint to hit para desencadenar la actualización de caché (utilizado por revalidatePWA). Dentro de la Proveedores Proveedores El pega un montón de cosas debajo del capó, y también puedes recoger los componentes de la cereza: PWAProvider RegisterSW Registro automático del trabajador del servicio ( Gestiona los errores de forma graciosa.Puede recortar el camino si es necesario: /sw.js <PWAProvider swPath="/custom/sw.js">{children}</PWAProvider> CacheCurrentPage Intercepta la navegación (incluidas las transiciones de estilo SPA), cachea el HTML de la página actual. SWRevalidateListener Relojes para eventos de localStorage y desencadena la actualización de caché en todas las pestañas. SSERevalidateListener Escribe a los eventos enviados por el servidor desde el Cuando tu backend dice “revalidar estas URLs”, este escuchador asegura que los clientes lo hagan. sseEndpoint DevPWAStatus El panel Dev-only puede activarse de esta manera: <PWAProvider devMode>{children}</PWAProvider> Los espectáculos: En línea / Offline Versión Cache Actualización de disponibilidad Herramientas de un solo clic: limpia la caché, desregistra SW, refresca, desactiva / habilita la caché Lo que realmente hace el trabajador El núcleo Las manos: sw.js HTML Caché Páginas almacenadas en caché con TTL (default: 10 min — tweakable en sw.js) Revalida automáticamente cuando expira TTL Fallback Offline si el HTML está faltando Activos estáticos JS, CSS, imágenes son almacenadas en caché para siempre Sólo cachés reciben solicitudes Mensajes de soporte Apoya estas acciones del cliente: CACHE_CURRENT_HTML en línea Página oficial_URL DISABLE_CACHE / ENABLE_CACHE Navegación - Esperando CLEAR_STATIC_CACHE Caché Modo Offline Se sirve offline.html si la red y la caché fallan Trata de refrescarse cuando vuelve en línea Uso En el medio conspiración conspiración Aquí es donde Trae revalidación de caché a SSR y Edge Middleware - con soporte de SSE y todo. next-pwa-pack export default withPWA(originalMiddleware, { revalidationSecret: process.env.REVALIDATION_SECRET!, sseEndpoint: "/api/pwa/cache-events", webhookPath: "/api/pwa/revalidate", }); Params: originalMiddleware: la lógica del middleware existente (auth, i18n, etc.) revalidacionSecret: para que nadie más pueda poke tu cache sseEndpoint: sobrecargar si otra cosa está utilizando esta ruta webhookPath: utilizado por el servidor o sistemas externos para revalidar URLs específicas Casos de uso del mundo real Actualización de la caché después de cambios de datos import { updateSWCache } from "next-pwa-pack"; // After creating a blog post: const handleCreatePost = async (data) => { await createPost(data); updateSWCache(["/blog", "/dashboard"]); }; Actualizar el cache desde el servidor import { revalidatePWA } from "../actions"; await createPost(data); await revalidatePWA(["/my-page"]); Limpiar el cache en Logout import { clearAllCache } from "next-pwa-pack"; const handleLogout = async () => { await logout(); await clearAllCache(); router.push("/login"); }; Todas las acciones de cache del cliente import { clearAllCache, reloadServiceWorker, updatePageCache, unregisterServiceWorkerAndClearCache, updateSWCache, disablePWACache, enablePWACache, clearStaticCache, usePWAStatus, } from "next-pwa-pack"; // Examples: await clearAllCache(); await reloadServiceWorker(); await updatePageCache("/about"); await unregisterServiceWorkerAndClearCache(); await clearStaticCache(); updateSWCache(["/page1", "/page2"]); disablePWACache(); enablePWACache(); const { online, hasUpdate, swInstalled, update } = usePWAStatus(); Ruta de API para triggers de caché externos Si desea desencadenar actualizaciones de caché externamente (por ejemplo, desde un panel de administrador), aquí está una ruta de la API que puede usar: // app/api/webhook/revalidate/route.ts import { NextRequest, NextResponse } from "next/server"; import { revalidatePWA } from "@/app/actions"; import { revalidateTag } from "next/cache"; import { FetchTags } from "@/app/api/endpoints/backend"; export async function POST(request: NextRequest) { try { const { tags, secret, urls } = await request.json(); if (secret !== process.env.REVALIDATION_SECRET) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const validTags = Object.values(FetchTags); const invalidTags = tags?.filter((tag) => !validTags.includes(tag)) || []; if (invalidTags.length > 0) { return NextResponse.json( { error: `Invalid tags: ${invalidTags.join(", ")}` }, { status: 400 } ); } let successful = 0; let failed = 0; if (tags?.length) { const tagResults = await Promise.allSettled( tags.map((tag) => revalidateTag(tag)) ); successful = tagResults.filter((r) => r.status === "fulfilled").length; failed = tagResults.filter((r) => r.status === "rejected").length; } if (urls?.length) { await revalidatePWA(urls); } return NextResponse.json({ success: true, message: "Cache revalidation completed", tags, urls, successful, failed, timestamp: new Date().toISOString(), }); } catch (error) { console.error("Webhook revalidation error:", error); return NextResponse.json({ error: "Internal server error" }, { status: 500 }); } } Haga lo mismo con: POST https://your-app.com/api/webhook/revalidate { "tags": ["faq"], "secret": "1234567890", "urls": ["/ru/question-answer"] } Debugging y DevTools Aquí está lo que puedes comprobar al debutar: Vaya a DevTools → Aplicaciones → Trabajadores de servicio. Confirmar que el trabajador está registrado. Compruebe Cache Storage → html-cache-v2 para ver si las páginas están almacenadas en caché. Simular offline en Red → Offline y cargar de nuevo. Console logs from the service worker help too: [PWA] Service Worker registered [SW] Cached: /about [SW] Revalidated and updated cache for: /blog GOTCHAS y NOTES Algunas cosas que debes saber antes de embarcar: Seguridad PWA requiere HTTPS en la producción. Sólo se almacenan las solicitudes. No almacenes datos sensibles. El desempeño El paquete no toca la base de rendimiento de su aplicación. Mejora significativamente las cargas repetidas. Config TTL se establece en sw.js (por defecto: 10 minutos). Puede excluir URLs de la caché a través de CACHE_EXCLUDE. manifest.json debe adaptarse a su aplicación. revalidatePWA acción es editable - personaliza según sea necesario. conPWA y PWAProvider ambos aceptan opciones: export default function PWAProvider({ children, swPath, devMode = false, serverRevalidation = { enabled: true, sseEndpoint: "/api/pwa/cache-events" }, }: PWAProviderProps) { ¿Qué es lo siguiente Está escrito para Debería trabajar en También - sólo no probado extensivamente. next-pwa-pack Next.js 15 Next.js 13 App Router Características previstas : Configurar TTL a través de opciones (sin editar sw.js) Push Notificaciones Control de cache basado en patrones Metricas de rendimiento para la eficiencia del cache Eso es eso. Si estás cansado de pelear con los trabajadores del servicio manualmente, da Irás de cero al soporte completo de PWA en una pausa de café. next-pwa-pack ¿Preguntas, errores o comentarios? abrir un problema o pegarnos. en github.com/dev-family/next-pwa-pack