渐进式 Web 应用 (PWA)
渐进式 Web 应用 (PWA) 结合了 Web 应用的覆盖范围和可访问性,以及原生移动应用的功能和用户体验。使用 Next.js,你可以创建提供无缝、类应用体验的 PWA,而无需维护多个代码库或等待应用商店审核。
PWA 让你可以:
- 无需等待应用商店审核即可立即部署更新
- 使用单一代码库创建跨平台应用
- 提供类似原生应用的功能,如主屏幕安装和推送通知
Next.js 通过 App Router 为创建 web app manifest 提供了内置支持。你可以创建静态或动态的清单文件:
例如,创建 app/manifest.ts
或 app/manifest.json
文件:
该文件应包含应用的名称、图标以及如何在用户设备上显示为图标的相关信息。这将允许用户将 PWA 安装到主屏幕,提供类似原生应用的体验。
你可以使用 favicon 生成器 等工具创建不同的图标集,并将生成的文件放在 public/
文件夹中。
Web 推送通知支持所有现代浏览器,包括:
- 安装到主屏幕的 iOS 16.4+ 应用
- macOS 13 或更高版本的 Safari 16
- 基于 Chromium 的浏览器
- Firefox
这使得 PWA 成为原生应用的可行替代方案。值得注意的是,你可以在不需要离线支持的情况下触发安装提示。
Web 推送通知允许你在用户不主动使用应用时重新吸引他们。以下是在 Next.js 应用中实现推送通知的方法:
首先,让我们在 app/page.tsx
中创建主页组件。我们将其分解成更小的部分以便更好地理解。首先,我们添加一些需要的导入和工具函数。暂时不用担心引用的 Server Actions 还不存在:
现在让我们添加一个组件来管理订阅、取消订阅和发送推送通知。
最后,让我们创建一个组件,向 iOS 设备显示一条消息,指导用户将应用安装到主屏幕,并且仅在应用尚未安装时显示该消息。
现在,让我们创建该文件调用的 Server Actions。
创建一个新文件 app/actions.ts
来包含你的 actions。这个文件将处理创建订阅、删除订阅和发送通知。
发送通知将由我们在第 5 步创建的 service worker 来处理。
在生产环境中,你需要将订阅信息存储在数据库中,以便在服务器重启后持久保存数据,并管理多个用户的订阅。
要使用 Web Push API,你需要生成 VAPID 密钥。
创建一个脚本文件,例如 generate-vapid-keys.js
:
使用 Node.js 运行这个脚本来生成你的 VAPID 密钥:
复制输出结果并粘贴到你的 .env
文件中。
创建 public/sw.js
文件作为你的 service worker:
这个 service worker 支持自定义图片和通知。它处理传入的推送事件和通知点击事件。
- 你可以使用
icon
和 badge
属性为通知设置自定义图标。
- 可以调整
vibrate
模式以在支持的设备上创建自定义振动提醒。
- 可以使用
data
属性将额外数据附加到通知中。
记得要彻底测试你的 service worker,确保它在不同的设备和浏览器上都能按预期工作。另外,确保将 notificationclick
事件监听器中的 'https://your-website.com'
链接更新为你应用的适当 URL。
在第 2 步中定义的 InstallPrompt
组件向 iOS 设备显示一条消息,指导用户将应用安装到主屏幕。
要确保你的应用可以被安装到移动设备主屏幕,你必须具备:
- 有效的 web app manifest(在第 1 步创建)
- 通过 HTTPS 提供网站服务
当满足这些条件时,现代浏览器会自动向用户显示安装提示。你可以使用 beforeinstallprompt
提供自定义安装按钮,但我们不推荐这样做,因为它不能跨浏览器和平台使用(在 Safari iOS 上不起作用)。
要确保你能在本地查看通知,请确保:
- 你正在 使用 HTTPS 运行本地环境
- 使用
next dev --experimental-https
进行测试
- 你的浏览器(Chrome、Safari、Firefox)已启用通知
- 在本地提示时接受使用通知的权限
- 确保通知没有被整个浏览器全局禁用
- 如果你仍然看不到通知,请尝试使用其他浏览器进行调试
安全性是任何 Web 应用的重要方面,特别是对于 PWA。Next.js 允许你使用 next.config.js
文件配置安全头信息。例如:
让我们来看看每个选项:
- 全局 Headers(应用于所有路由):
X-Content-Type-Options: nosniff
:防止 MIME 类型嗅探,降低恶意文件上传的风险。
X-Frame-Options: DENY
:通过防止你的网站被嵌入到 iframe 中来防止点击劫持攻击。
Referrer-Policy: strict-origin-when-cross-origin
:控制随请求发送的引用信息量,在安全性和功能性之间取得平衡。
- Service Worker 特定 Headers:
Content-Type: application/javascript; charset=utf-8
:确保 service worker 被正确解释为 JavaScript。
Cache-Control: no-cache, no-store, must-revalidate
:防止缓存 service worker,确保用户始终获取最新版本。
Content-Security-Policy: default-src 'self'; script-src 'self'
:为 service worker 实现严格的内容安全策略,只允许来自同一源的脚本。
了解更多关于在 Next.js 中定义 内容安全策略 的信息。
- 探索 PWA 功能:PWA 可以利用各种 web API 提供高级功能。考虑探索后台同步、周期性后台同步或文件系统访问 API 等功能来增强你的应用。要获取灵感和了解 PWA 功能的最新信息,你可以参考 What PWA Can Do Today 等资源。
- 静态导出:如果你的应用不需要运行服务器,而是使用静态文件导出,你可以更新 Next.js 配置来启用此更改。在 Next.js 静态导出文档 中了解更多信息。但是,你需要从 Server Actions 转移到调用外部 API,并将定义的 headers 移到你的代理。
- 离线支持:要提供离线功能,一个选项是在 Next.js 中使用 Serwist。你可以在他们的 文档 中找到如何将 Serwist 与 Next.js 集成的示例。注意: 该插件目前需要 webpack 配置。
- 安全注意事项:确保你的 service worker 得到适当的安全保护。这包括使用 HTTPS、验证推送消息的来源以及实现适当的错误处理。
- 用户体验:考虑实现渐进增强技术,以确保你的应用在用户的浏览器不支持某些 PWA 功能时也能正常工作。