ฉันชอบสร้างเครื่องมือที่ไม่เพียง แต่ทํางาน ทีมงานของฉันได้อยู่ในโครงสร้างของ Next.js เป็นเวลานานพอที่จะรู้ว่าสิ่งที่เจ็บปวด หนึ่งในสิ่งล่าสุดที่ฉันวางไว้เป็น — แพคเกจ drop-in ที่เชื่อมต่อการสนับสนุน PWA เต็มรูปแบบในแอป Next.js ของคุณโดยไม่ต้องตัดผมของคุณ เอาออกจากเส้นทางของคุณ next-pwa-pack The Backstory (aka: ทําไมฉันเขียนสิ่งนี้) ทุกครั้งที่ลูกค้าพูดถึง “การสนับสนุน PWA” ฉันขัดขวางตัวเอง ฉันได้ทดสอบห้องสมุดที่มีอยู่ มากเกินไป Magic Tons of config หรือไม่เข้ากันได้กับ — ซึ่งในทางกลับกันเราได้นํามาใช้อย่างเต็มที่ ฉันต้องการ: App Router การฟื้นฟู cache ของเซิร์ฟเวอร์ การบูรณาการ App Router ง่ายต่อการซิงค์ระหว่างแท็บ ทําความสะอาด API สําหรับการจัดการแคชจากด้านหลัง แทนที่ฉันจบลงการเขียนพนักงานบริการด้วยมือ Tuning TTLs cache การจัดการกับกลยุทธ์การอัปเดต การจัดการลูกค้าคงที่ ลบแคชด้วยตนเองทุกครั้งที่เราจัดส่ง และไม่ให้ฉันเริ่มต้นกับผู้ใช้ที่ไม่เห็นการอัปเดตจนกว่าพวกเขาจะรีเฟรชอย่างหนักพอ ฉันต้องการบางสิ่งบางอย่างที่เรียบง่ายที่คาดการณ์ได้และทดสอบการต่อสู้ ดังนั้นฉันจึงสร้าง อาคาร : สิ่งที่เข้ามาในมัน next-pwa-pack ถัดไปแพคเกจ ขั้นตอนหนึ่งคือการเขียนพนักงานบริการขั้นต่ํา: Caches HTML ด้วย TTL การจัดการสินทรัพย์แบบคงที่ ทํางานออฟไลน์เช่นเดียวกับ PWA จริงควร จากนั้นฉันเพิ่มระบบการส่งข้อความเพื่อให้ลูกค้าสามารถพูดคุยกับพนักงานบริการได้เช่นการทําลายแคชหรือปิดใช้งานแคชอย่างสมบูรณ์ ต่อไปฉันเขียนสคริปต์ไม่กี่รายการ: คัดลอก sw.js, manifest.json และ offline.html ในโครงการของคุณโดยอัตโนมัติ ฉีดการกระทําเซิร์ฟเวอร์ที่เรียกว่า revalidatePWA ที่คุณสามารถใช้ได้ทุกที่ (เส้นทาง API, การกระทําเซิร์ฟเวอร์, ส่วนประกอบเซิร์ฟเวอร์ - เลือกของคุณ) สําหรับการสนับสนุน App Router และ SSR / Edge เต็มรูปแบบฉันได้บรรจุทุกอย่างในฟังก์ชั่นที่มีลําดับสูงขึ้น: One import, one call – ทํา withPWA ฉันยังสร้างในแท็บซิงโครไนซ์ เพราะผู้ใช้ เปิดแอปของคุณใน 3 แท็บและคาดหวังว่าพวกเขาจะอัปเดตด้วยมนตร์ในการซิงค์ ฉันแก้ไขว่าผ่านทาง + ออนไลน์ เหตุการณ์ ทารก localStorage storage ผลลัพธ์? แพคเกจที่ทํางานเพียงแค่ ไม่มีการกําหนดค่า Magic สีดํา ไม่มีการเขียนใหม่ส่วนหลักของแอปของคุณ สิ่งที่คุณได้รับกับ next-pwa-pack ถัดไปแพคเกจ เมื่อติดตั้งแล้วคุณจะได้รับ: การลงทะเบียนพนักงานบริการออกจากกล่อง - ไม่มีหม้อไอน้ํา Fallback ออฟไลน์ด้วยแบบกําหนดเอง offline.html ไฟล์อัตโนมัติที่คุณสามารถปรับแต่ง ( Manifest, SW ฯลฯ ) API การควบคุมแคช - ทําความสะอาดอัปเดตปิดใช้งานทุกอย่างโดยโปรแกรม การซิงค์ระหว่างแท็บ — ไม่มีเนื้อหาคงที่ในการตั้งค่าแท็บหลายแท็บ แผงพัฒนาสําหรับสถานะ PWA ในเวลาจริงในระหว่างการพัฒนาในท้องถิ่น สนับสนุนการยืนยันใหม่ทางเซิร์ฟเวอร์ผ่านการกระทําเซิร์ฟเวอร์เส้นทาง API หรือการบูรณาการ Webhook ภายนอก คุณสามารถบันทึกแพคเกจได้ที่นี่: 👉 https://github.com/dev-family/next-pwa-pack สิ่งที่เกิดขึ้นเมื่อคุณติดตั้ง การติดตั้งสคริปต์อัตโนมัติคัดลอก PWA boilerplate ไปยัง : /public sw.js – ผู้ทํางานบริการของคุณด้วยกลยุทธ์แคช offline.html – หน้าล็อคสําหรับโหมดออฟไลน์ manifest.json – ปรับแต่งเพื่อให้เหมาะกับแอปของคุณ ⚠️ไฟล์ที่มีอยู่จะไม่ถูกเขียนเกินไป - มันเคารพการตั้งค่าของคุณ หากคุณต้องการเปิดใช้งานการคัดลอกด้วยตนเอง: node node_modules/next-pwa-pack/scripts/copy-pwa-files.mjs # or npx next-pwa-pack/scripts/copy-pwa-files.mjs การกระทําเซิร์ฟเวอร์ นอกจากนี้ยังเพิ่มในของคุณ หรือ ไฟล์ขึ้นอยู่กับโครงสร้างโฟลเดอร์ของคุณ: 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(); } หากไฟล์นั้นไม่ปรากฏคุณสามารถเรียกใช้: node node_modules/next-pwa-pack/scripts/copy-pwa-server-actions.mjs การกําหนดค่าของคุณ manifest.json manifest.json หลังจากติดตั้งอย่าลืมปรับแต่ง : /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" } ] } ลบไอคอนของคุณลงใน , หรือ tweak the paths above. ไม่มีอะไรน่ารัก public/icons/ เริ่มต้นอย่างรวดเร็ว: Wire It Up Wrap layout ของคุณใน และ Magic Kicks ใน: PWAProvider import { PWAProvider } from "next-pwa-pack"; export default function layout({ children }) { return <PWAProvider>{children}</PWAProvider>; } หากคุณต้องการ revalidation เพื่อทํางานจากด้านเซิร์ฟเวอร์คุณยังต้องอัปเดต 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*"], }; ตัวเลือก HOC: OriginalMiddleware: middleware ฐานของคุณ (เช่นสําหรับ i18n หรือ auth) revalidationSecret: รหัสผ่านลับเพื่อล็อคการยืนยันใหม่ของแคช sseEndpoint: SSE stream path (เปลี่ยนถ้ามันขัดแย้ง) webhookPath: Endpoint to hit สําหรับการกระตุ้นการฟื้นฟูแคช (ใช้โดย revalidatePWA) ภายใน PWAProvider ผู้ให้บริการ PWAP โซ แพคเกจชิ้นส่วนภายใต้ฝาครอบ - และคุณสามารถเลือกชิ้นส่วนเชอร์รี่ได้เช่นกัน: PWAProvider RegisterSW โดยอัตโนมัติลงทะเบียนพนักงานบริการ ( ). จัดการข้อผิดพลาดอย่างมีเสน่ห์ คุณสามารถเปลี่ยนเส้นทางได้หากจําเป็น: /sw.js <PWAProvider swPath="/custom/sw.js">{children}</PWAProvider> CacheCurrentPage ระงับการนําทาง (รวมถึงการเปลี่ยนแปลงสไตล์ SPA) ระงับ HTML ของหน้าปัจจุบัน SWRevalidateListener นาฬิกาสําหรับเหตุการณ์ localStorage และเปิดใช้งานการปรับปรุงแคชผ่านแท็บ SSERevalidateListener Listens ไปยัง เซิร์ฟเวอร์ส่งเหตุการณ์จาก เมื่อ backend ของคุณบอกว่า“ revalidate URLs เหล่านี้” listener นี้ทําให้แน่ใจว่าลูกค้าทําเช่นนั้น sseEndpoint DevPWAStatus แผง Dev-only คุณสามารถเปิดใช้งานได้ดังนี้: <PWAProvider devMode>{children}</PWAProvider> การแสดง: สถานะออนไลน์ / ออฟไลน์ เวอร์ชัน Cache การปรับปรุงความพร้อมใช้งาน เครื่องมือคลิกเดียว: Clear Cache, unregister SW, refresh, disable / enable cache สิ่งที่พนักงานบริการจริงทํา หลัก มือรูดควย: sw.js HTML แคช Pages cached with TTL (Default: 10 min — tweakable ใน sw.js) การยืนยันอัตโนมัติเมื่อ TTL หมดอายุ ออฟไลน์ fallback หากไม่มี HTML สถิติทรัพย์สิน JS, CSS, รูปภาพจะถูกเก็บไว้ในแคชตลอดไป Cache เท่านั้น GET requests ข้อความสนับสนุน สนับสนุนการกระทําเหล่านี้จากลูกค้า: CACHE_CURRENT_HTML รหัสผ่าน _ URL DISABLE_CACHE / ENABLE_CACHE เรือ - การรอ CLEAR_STATIC_CACHE ออฟไลน์แฟชั่น บริการ offline.html ถ้าเครือข่ายและแคชทั้งสองล้มเหลว พยายามที่จะสดชื่นเมื่อกลับออนไลน์ การใช้ ใน Middleware withPWA เคล็ดลับ นี่คือที่ มันนําการยืนยัน cache ไปยัง SSR และ Edge Middleware - ด้วยการสนับสนุน SSE และทุกอย่าง next-pwa-pack export default withPWA(originalMiddleware, { revalidationSecret: process.env.REVALIDATION_SECRET!, sseEndpoint: "/api/pwa/cache-events", webhookPath: "/api/pwa/revalidate", }); Params: OriginalMiddleware: โลจิสติกส์ middleware ที่มีอยู่ของคุณ (auth, i18n ฯลฯ) revalidationSecret: เพื่อให้ไม่มีใครสามารถ poke cache ของคุณ sseEndpoint: override ถ้ามีสิ่งอื่นที่ใช้เส้นทางนี้ webhookPath: ใช้โดยเซิร์ฟเวอร์หรือระบบภายนอกเพื่อยืนยัน URL เฉพาะ กรณีการใช้งานในโลกจริง การอัปเดตแคชหลังจากเปลี่ยนแปลงข้อมูล import { updateSWCache } from "next-pwa-pack"; // After creating a blog post: const handleCreatePost = async (data) => { await createPost(data); updateSWCache(["/blog", "/dashboard"]); }; การอัปเดตแคชจากเซิร์ฟเวอร์ import { revalidatePWA } from "../actions"; await createPost(data); await revalidatePWA(["/my-page"]); การทําความสะอาด Cache บน Logout import { clearAllCache } from "next-pwa-pack"; const handleLogout = async () => { await logout(); await clearAllCache(); router.push("/login"); }; การกระทํา Cache ของลูกค้าทั้งหมด 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(); เส้นทาง API สําหรับตัวกระตุ้นแคชภายนอก หากคุณต้องการเปิดใช้งานการอัปเดตแคชจากภายนอก (เช่นจากแผงผู้ดูแลระบบ) นี่คือเส้นทาง API ที่คุณสามารถใช้: // 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 }); } } สับมันด้วย: POST https://your-app.com/api/webhook/revalidate { "tags": ["faq"], "secret": "1234567890", "urls": ["/ru/question-answer"] } Debugging & DevTools นี่คือสิ่งที่คุณสามารถตรวจสอบเมื่อ debugging: ไปที่ DevTools → แอปพลิเคชัน → พนักงานบริการ ตรวจสอบให้แน่ใจว่าพนักงานได้รับการลงทะเบียน ตรวจสอบ Cache Storage → html-cache-v2 เพื่อดูว่าหน้าเว็บถูกแคชหรือไม่ การจําลองแบบออฟไลน์ในเครือข่าย → ออฟไลน์และโหลดใหม่ คุณควรดู offline.html Console logs from the service worker help too: [PWA] Service Worker registered [SW] Cached: /about [SW] Revalidated and updated cache for: /blog Gotchas & หมายเลข บางสิ่งที่คุณควรรู้ก่อนที่จะจัดส่ง: ความปลอดภัย PWA ต้องใช้ HTTPS ในการผลิต GET เท่านั้นคําขอจะถูก cached อย่าซ่อนข้อมูลที่ละเอียดอ่อน ประสิทธิภาพ แพคเกจไม่ได้สัมผัสกับขั้นตอนพื้นฐานประสิทธิภาพของแอปของคุณ มันปรับปรุงการโหลดซ้ําอย่างมีนัยสําคัญ การเชื่อมต่อ TTL ถูกตั้งค่าใน sw.js (ค่าเริ่มต้น: 10 นาที) คุณสามารถยกเลิก URL จาก caching โดยใช้ CACHE_EXCLUDE manifest.json ต้องปรับแต่งให้เหมาะกับแอปของคุณ การกระทํา revalidatePWA สามารถแก้ไขได้ - ปรับแต่งตามความต้องการ withPWA และ PWAProvider ทั้งสองยอมรับตัวเลือก: export default function PWAProvider({ children, swPath, devMode = false, serverRevalidation = { enabled: true, sseEndpoint: "/api/pwa/cache-events" }, }: PWAProviderProps) { สิ่งที่ถัดไป เขียนสําหรับ มันควรทํางานบน ยัง - เพียงแค่ไม่ได้ทดสอบอย่างกว้างขวาง next-pwa-pack Next.js 15 Next.js 13 App Router ลักษณะที่วางแผน: การกําหนดค่า TTL ผ่านตัวเลือก (ไม่มีการแก้ไข sw.js) Push การแจ้งเตือน การควบคุมแคชตามรูปแบบ เมตริกประสิทธิภาพสําหรับประสิทธิภาพแคช นี่คือ หากคุณเหนื่อยกับการต่อสู้กับพนักงานบริการด้วยตนเองให้ คุณจะไปจาก zero ไปยังการสนับสนุน PWA เต็มรูปแบบในระยะเวลาหนึ่งครั้ง next-pwa-pack คําถามข้อผิดพลาดหรือความคิดเห็น? เปิดปัญหาหรือสัมผัสเรา github.com/dev-family/next-pwa-pack