Tôi thích xây dựng các công cụ không chỉ làm việc - họ Đội ngũ của tôi đã ở trong các khe hở của Next.js đủ lâu để biết chính xác những gì làm tổn thương. - một gói drop-in kết nối hỗ trợ PWA đầy đủ trong ứng dụng Next.js của bạn mà không làm rách tóc. Hãy ra khỏi con đường của bạn next-pwa-pack Lời bài hát: Why I Wrote This Thing (The Backstory) Bất cứ khi nào một khách hàng đề cập đến “hỗ trợ PWA”, tôi tự nhủ. Tôi đã thử các thư viện hiện có. Quá nhiều phép thuật. Tons of config. Hoặc chỉ hoàn toàn không tương thích với - mà, bằng cách này, chúng tôi đã hoàn toàn thông qua. tôi muốn: App Router Server-side cache phục hồi. Tích hợp App Router - Dễ dàng đồng bộ giữa các tab. Clean API để quản lý bộ nhớ cache từ backend. Thay vào đó, tôi kết thúc bằng cách viết nhân viên dịch vụ bằng tay. Tuning bộ nhớ cache TTLs. Đối phó với logic cập nhật. Quản lý khách hàng cố định. Xóa bộ nhớ cache bằng tay mỗi khi chúng tôi vận chuyển. Và thậm chí không bắt đầu tôi trên người dùng không thấy cập nhật cho đến khi họ làm mới. Tôi cần một cái gì đó chết đơn giản, có thể dự đoán, và thử nghiệm chiến đấu. Xây dựng * What went into it (Cái gì đi vào nó) Trang chủ / PWA-PACK Trang chủ / PWA-PACK Bước một là viết một nhân viên dịch vụ tối thiểu: Cache HTML với TTL. Quản lý tài sản tĩnh Hoạt động ngoại tuyến, như một PWA thực sự nên. Sau đó, tôi thêm một hệ thống nhắn tin để khách hàng có thể nói chuyện với nhân viên dịch vụ - ví dụ, để phá vỡ bộ nhớ cache hoặc vô hiệu hóa bộ nhớ cache hoàn toàn. Sau đó, tôi viết một vài kịch bản: Tự động sao chép sw.js, manifest.json và offline.html vào dự án của bạn. Nhúng một hành động máy chủ được gọi là revalidatePWA mà bạn có thể sử dụng bất cứ nơi nào (các tuyến API, hành động máy chủ, các thành phần máy chủ - chọn lựa của bạn). Để hỗ trợ đầy đủ App Router và SSR / Edge, tôi đã đóng gói mọi thứ trong một hàm thứ tự cao hơn: One import, one call – đã hoàn thành. withPWA Tôi cũng đã xây dựng trong tab đồng bộ hóa. bởi vì người dùng mở ứng dụng của bạn trong 3 tab và mong đợi chúng cập nhật ma thuật trong sync. + Đánh giá Các sự kiện sẽ localStorage storage Kết quả? Một gói mà chỉ làm việc. Không cấu hình ma thuật đen. Không viết lại các phần cốt lõi của ứng dụng của bạn. Những gì bạn nhận được với next-pwa-pack Trang chủ / PWA-PACK Sau khi cài đặt, bạn sẽ nhận được: Đăng ký nhân viên dịch vụ ra khỏi hộp - không có boilerplate. Offline fallback với tùy chỉnh offline.html. Tự động sao chép các tập tin bạn có thể chỉnh sửa (manifest, SW, v.v.). API kiểm soát bộ nhớ cache - rõ ràng, cập nhật, vô hiệu hóa, tất cả theo chương trình. Đồng bộ giữa các tab — không có nội dung cố định trong các thiết lập đa tab. Panel phát triển cho trạng thái PWA thời gian thực trong quá trình phát triển địa phương. Hỗ trợ tái xác thực bên máy chủ thông qua các hành động máy chủ, đường API hoặc tích hợp webhook bên ngoài. Bạn có thể tham khảo gói tại đây: https://github.com/dev-family/next-pwa-pack Điều gì xảy ra khi bạn cài đặt nó Script cài đặt tự động sao chép boilerplate PWA vào : /public sw.js – nhân viên dịch vụ của bạn với logic bộ nhớ cache. offline.html – Fallback page cho chế độ ngoại tuyến. manifest.json – điều chỉnh nó để phù hợp với ứng dụng của bạn. ⚠️ Các tệp hiện có sẽ không được viết quá mức - nó tôn trọng thiết lập của bạn. Nếu bạn muốn kích hoạt bản sao theo cách thủ công: node node_modules/next-pwa-pack/scripts/copy-pwa-files.mjs # or npx next-pwa-pack/scripts/copy-pwa-files.mjs Server hành động Nó cũng được thêm vào của bạn hoặc Tùy thuộc vào cấu trúc thư mục của bạn: 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(); } Nếu tập tin đó không xuất hiện, bạn có thể chạy: node node_modules/next-pwa-pack/scripts/copy-pwa-server-actions.mjs Configuring của bạn Lời bài hát: Jason Lời bài hát: Jason Sau khi cài đặt, đừng quên tùy chỉnh : /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" } ] } Thả icon của bạn vào , hoặc tweak các con đường ở trên. không có gì tuyệt vời. public/icons/ Lời bài hát: Wire It Up Wrap layout của bạn trong Và sự kỳ diệu nhảy vào: PWAProvider import { PWAProvider } from "next-pwa-pack"; export default function layout({ children }) { return <PWAProvider>{children}</PWAProvider>; } Nếu bạn muốn tái xác thực để làm việc từ phía máy chủ, bạn cũng sẽ cần cập nhật middleware của bạn: // /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*"], }; Các lựa chọn của HOC: Middleware gốc: middleware cơ bản của bạn (ví dụ, cho i18n hoặc auth). revalidationSecret: token bí mật để khóa cache revalidation. sseEndpoint: SSE stream path (thay đổi nếu nó mâu thuẫn). webhookPath: endpoint to hit để kích hoạt bộ nhớ cache refresh (được sử dụng bởi revalidatePWA). Bên trong PWAProvider nhà cung cấp Các gói một loạt các thứ dưới nắp - và bạn cũng có thể chọn các thành phần anh đào: PWAProvider RegisterSW Tự động đăng ký nhân viên dịch vụ ( ) Xử lý lỗi một cách lịch sự. Bạn có thể bỏ qua con đường nếu cần thiết: /sw.js <PWAProvider swPath="/custom/sw.js">{children}</PWAProvider> CacheCurrentPage Chặn điều hướng (bao gồm cả chuyển đổi kiểu SPA), lưu trữ HTML của trang hiện tại. SWRevalidateListener Đồng hồ cho localStorage sự kiện và kích hoạt bộ nhớ cache làm mới trên các tab. SSERevalidateListener Listens to server-sent events from the Khi backend của bạn nói "xác minh lại các URL này", người nghe này đảm bảo khách hàng làm điều đó. sseEndpoint DevPWAStatus Dev-only panel bạn có thể kích hoạt như thế này: <PWAProvider devMode>{children}</PWAProvider> Các chương trình: Trực tuyến / Offline Cache phiên bản Cập nhật Availability Công cụ một cú nhấp chuột: clear cache, unregister SW, refresh, disable/enable cache Những gì nhân viên dịch vụ thực sự làm Cốt lõi tay cầm : sw.js HTML Caching Pages cached with TTL (default: 10 min — tweakable in sw.js) Tự động xác nhận khi TTL hết hạn Offline fallback nếu HTML bị thiếu Tài sản static JS, CSS, hình ảnh được lưu trữ vĩnh viễn Chỉ có cache nhận yêu cầu Thông điệp hỗ trợ Hỗ trợ các hành động này từ khách hàng: Cache_Current_HTML Cache_Current_HTML Đánh giá_URL DISABLE_CACHE / ENABLE_CACHE / Hạn chế Đang chờ / Waiting CLEAR_STATIC_CACHE - Khóa Thời trang Offline Dịch vụ offline.html nếu cả mạng và bộ nhớ cache đều thất bại Cố gắng làm mới khi trở lại trực tuyến Sử dụng Tại Middleware withPWA Khánh Hòa Đây là nơi Nó mang lại tái xác thực bộ nhớ cache cho SSR và Edge Middleware - với hỗ trợ SSE và tất cả. next-pwa-pack export default withPWA(originalMiddleware, { revalidationSecret: process.env.REVALIDATION_SECRET!, sseEndpoint: "/api/pwa/cache-events", webhookPath: "/api/pwa/revalidate", }); Params: gốcMiddleware: logic middleware hiện có của bạn (auth, i18n, v.v.) revalidationSecret: để không ai khác có thể poke bộ nhớ cache của bạn sseEndpoint: Override nếu một cái gì đó khác đang sử dụng tuyến đường này webhookPath: được sử dụng bởi máy chủ hoặc các hệ thống bên ngoài để xác thực lại các URL cụ thể trường hợp sử dụng thế giới thực Cập nhật cache sau khi thay đổi dữ liệu import { updateSWCache } from "next-pwa-pack"; // After creating a blog post: const handleCreatePost = async (data) => { await createPost(data); updateSWCache(["/blog", "/dashboard"]); }; Cập nhật cache từ server import { revalidatePWA } from "../actions"; await createPost(data); await revalidatePWA(["/my-page"]); Làm sạch Cache trên Logout import { clearAllCache } from "next-pwa-pack"; const handleLogout = async () => { await logout(); await clearAllCache(); router.push("/login"); }; Tất cả Client Cache Actions 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 Route cho Trigger bộ nhớ cache bên ngoài Nếu bạn muốn kích hoạt các bản cập nhật bộ nhớ cache từ bên ngoài (ví dụ, từ bảng quản trị), đây là một lộ trình API bạn có thể sử dụng: // 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 }); } } Đánh nó với: POST https://your-app.com/api/webhook/revalidate { "tags": ["faq"], "secret": "1234567890", "urls": ["/ru/question-answer"] } Debugging và DevTools Đây là những gì bạn có thể kiểm tra khi debugging: Đi tới DevTools → Application → Service Workers. Xác nhận nhân viên đã đăng ký. Kiểm tra Cache Storage → html-cache-v2 để xem các trang có được lưu trữ trong bộ nhớ cache hay không. Simulate offline in Network → Offline and reload. Bạn nên xem 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 & Đánh giá Một số điều bạn nên biết trước khi đi thuyền: an ninh PWA yêu cầu HTTPS trong sản xuất. Chỉ có yêu cầu GET được lưu trữ. Đừng che giấu dữ liệu nhạy cảm Hiệu suất Gói này không ảnh hưởng đến hiệu suất cơ bản của ứng dụng của bạn. Nó cải thiện đáng kể tải lặp đi lặp lại. Config TTL được đặt trong sw.js (mặc định: 10 phút). Bạn có thể loại trừ URL khỏi bộ nhớ đệm qua CACHE_EXCLUDE. manifest.json cần phải được tùy chỉnh cho ứng dụng của bạn. revalidatePWA hành động có thể chỉnh sửa - tùy chỉnh nó khi cần thiết. withPWA và PWAProvider đều chấp nhận các tùy chọn: export default function PWAProvider({ children, swPath, devMode = false, serverRevalidation = { enabled: true, sseEndpoint: "/api/pwa/cache-events" }, }: PWAProviderProps) { Điều gì tiếp theo được viết cho Nó nên làm việc trên cũng - chỉ không được thử nghiệm rộng rãi. next-pwa-pack Next.js 15 Next.js 13 App Router Các tính năng được lên kế hoạch: TTL config via options (không chỉnh sửa sw.js) Push thông báo Kiểm soát cache dựa trên Pattern Kích thước hiệu suất cho hiệu quả cache Đó là nó. Nếu bạn mệt mỏi với việc đánh nhau với nhân viên dịch vụ theo cách thủ công, hãy Bạn sẽ đi từ zero đến hỗ trợ PWA đầy đủ trong một thời gian nghỉ cà phê. next-pwa-pack Câu hỏi, lỗi, hoặc phản hồi? Mở một vấn đề hoặc nhấn chúng tôi lên. ✔️ github.com/dev-family/ tiếp theo-pwa-pack