为 Web 框架添加 PWA 支持
发布于
本指南为 Next.js、Nuxt、SvelteKit 或 Angular 项目添加 Web App Manifest 与 Service Worker,各框架保留自己的构建集成,浏览器端产物则使用相同的 Manifest 和 Service Worker API。
MDN 把 Service Worker API 标为广泛可用。注册要求安全上下文,浏览器把 localhost 视为本地开发所需的安全上下文,因此示例会在无法注册或注册失败时让应用继续通过网络使用。
请先选择负责应用构建的框架小节,再使用最后一个小节,在浏览器无法注册时保留联网路径。
在 Next.js App Router 中添加 manifest 路由
链接到“在 Next.js App Router 中添加 manifest 路由”一节Next.js 通过 app/manifest.ts 提供带类型的 manifest 路由。其 PWA 指南在 lib/service-worker.js 创建自定义 Service Worker,并从客户端组件使用 new URL("../lib/service-worker.js", import.meta.url) 注册。
用应用实际使用的字段创建 manifest,并把引用的图标文件放入 public/。
import type { MetadataRoute } from "next";
export default function manifest(): MetadataRoute.Manifest { return { name: "Field Notes", short_name: "Notes", start_url: "/", display: "standalone", background_color: "#ffffff", theme_color: "#12372a", icons: [ { src: "/icon-192.png", sizes: "192x192", type: "image/png" }, { src: "/icon-512.png", sizes: "512x512", type: "image/png" }, ], };}添加 lib/service-worker.js,再使用下方 Next.js 注册示例进行能力检测和失败处理。
配置 Nuxt 模块
链接到“配置 Nuxt 模块”一节Nuxt 模块目录为 Nuxt 3 提供 @vite-pwa/nuxt,添加模块后,把 manifest 数据放在 pwa 下。
运行 npx nuxi@latest module add @vite-pwa/nuxt 安装,然后在 nuxt.config.ts 中保存配置。
export default defineNuxtConfig({ modules: ["@vite-pwa/nuxt"], pwa: { registerType: "autoUpdate", manifest: { name: "Field Notes", short_name: "Notes", start_url: "/", display: "standalone", theme_color: "#12372a", icons: [ { src: "/icon-192.png", sizes: "192x192", type: "image/png" }, { src: "/icon-512.png", sizes: "512x512", type: "image/png" }, ], }, },});该模块依据此配置生成 Service Worker 并注入 Web App Manifest。
配置 SvelteKit 插件
链接到“配置 SvelteKit 插件”一节Vite PWA 的 SvelteKit 集成提供 SvelteKitPWA。其文档在 vite.config.ts 中配置插件,并通过 virtual:pwa-info 暴露 manifest 标记。
把 @vite-pwa/sveltekit 安装为开发依赖,再把插件放在 sveltekit() 之后。
import { sveltekit } from "@sveltejs/kit/vite";import { SvelteKitPWA } from "@vite-pwa/sveltekit";import { defineConfig } from "vite";
export default defineConfig({ plugins: [ sveltekit(), SvelteKitPWA({ manifest: { name: "Field Notes", short_name: "Notes", start_url: "/", display: "standalone", theme_color: "#12372a", icons: [ { src: "/icon-192.png", sizes: "192x192", type: "image/png" }, { src: "/icon-512.png", sizes: "512x512", type: "image/png" }, ], }, }), ],});按照插件文档,把生成的 manifest 链接加入根布局。
<script> import { pwaInfo } from "virtual:pwa-info"; $: webManifestLink = pwaInfo ? pwaInfo.webManifest.linkTag : "";</script>
<svelte:head> {@html webManifestLink}</svelte:head>虚拟模块没有 manifest 信息时,空字符串回退让布局保持有效。
运行 Angular schematic
链接到“运行 Angular schematic”一节Angular 的 @angular/pwa schematic 会添加 Service Worker 包、构建支持、注册代码、manifest 链接、图标以及 ngsw-config.json。
在项目目录应用 schematic,再创建生产构建。
ng add @angular/pwang build检查生成的 manifest.webmanifest、图标与 ngsw-config.json,不要把起始值直接当成应用元数据;Angular 指南在本地演示 Service Worker 时使用生产配置。
注册 Next.js worker 并保留联网路径
链接到“注册 Next.js worker 并保留联网路径”一节框架插件自动生成构建产物,但浏览器仍通过 navigator.serviceWorker 暴露 Service Worker 能力。下面的 Next.js 客户端组件采用框架指南中的 worker URL。
不支持或注册失败时,普通网络导航保持可用。
把组件保存为 app/service-worker-registration.tsx,与上文指定的 lib/service-worker.js 配合使用,再从布局或页面渲染 <ServiceWorkerRegistration />。
"use client";
import { useEffect, useState } from "react";
export default function ServiceWorkerRegistration() { const [status, setStatus] = useState("正在检查 Service Worker 支持…");
useEffect(() => { if (!("serviceWorker" in navigator)) { setStatus("Service Worker 注册不可用;应用仍可联网使用。"); return; }
let cancelled = false;
navigator.serviceWorker .register( new URL("../lib/service-worker.js", import.meta.url), { scope: "/", updateViaCache: "none" }, ) .then(() => { if (!cancelled) setStatus("Service Worker 注册已就绪。"); }) .catch((error) => { if (!cancelled) { setStatus("Service Worker 注册失败;应用仍可联网使用。"); } console.error(error); });
return () => { cancelled = true; }; }, []);
return <p role="status">{status}</p>;}Next.js 自定义 worker 使用上述直接注册。Nuxt 与 SvelteKit 插件及 Angular schematic 会提供自己的注册路径;在它们初始化的界面中保留相同的支持与错误状态。
另请参阅
链接到“另请参阅”一节- 入门
- 离线支持
- 更新策略
- How to build a Progressive Web Application with Next.js(nextjs.org)
- Getting started with Angular service workers(angular.dev)