mirror of
https://github.com/wuzf/2fa.git
synced 2026-09-03 07:17:09 +08:00
- Refactor monolithic worker into layered modules (api, otp, ui, utils) - Add Vitest test suite with 598 tests across 17 files - Set up GitHub Actions CI/CD, Dependabot - Add community files (CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, templates) - Add comprehensive documentation (API reference, architecture, deployment) - Configure ESLint, Prettier, and Husky pre-commit hooks - Implement PWA frontend with modular scripts, styles, and service worker
571 lines
15 KiB
Markdown
571 lines
15 KiB
Markdown
# 📱 PWA 功能指南
|
||
|
||
## 📋 目录
|
||
|
||
- [什么是 PWA](#什么是-pwa)
|
||
- [功能特性](#功能特性)
|
||
- [安装指南](#安装指南)
|
||
- [Service Worker](#service-worker)
|
||
- [故障排查](#故障排查)
|
||
|
||
---
|
||
|
||
## 什么是 PWA
|
||
|
||
PWA (Progressive Web App) 是一种结合网页和原生应用优点的应用技术。
|
||
|
||
### PWA 优势
|
||
|
||
| 特性 | 说明 |
|
||
| --------------- | -------------------------------- |
|
||
| **📥 可安装** | 添加到主屏幕,像原生应用一样启动 |
|
||
| **⚡ 快速** | Service Worker 缓存,秒开应用 |
|
||
| **🔄 离线** | 基础功能可离线访问 |
|
||
| **🔄 自动更新** | 无需应用商店,自动更新 |
|
||
| **💾 小体积** | 无需下载大型安装包 |
|
||
|
||
### WebAPK 支持 (Android)
|
||
|
||
在 Android 平台,Chrome 和 Edge 会生成真正的 **WebAPK**:
|
||
|
||
- ✅ 出现在应用抽屉中
|
||
- ✅ 可在系统设置中管理
|
||
- ✅ 完整的全屏体验
|
||
- ✅ 与原生应用无异
|
||
|
||
---
|
||
|
||
## 功能特性
|
||
|
||
### ✅ 已实现功能
|
||
|
||
#### 1. Web App Manifest (`/manifest.json`)
|
||
|
||
- 应用名称、图标、主题色
|
||
- 独立显示模式(无浏览器UI)
|
||
- 快捷方式(快速添加密钥、扫描二维码)
|
||
- 协议处理器(otpauth:// 链接)
|
||
|
||
#### 2. Service Worker (`/sw.js`)
|
||
|
||
- **静态资源缓存**: HTML、CSS、JS
|
||
- **CDN 资源缓存**: jsQR、qrcode-generator
|
||
- **智能缓存策略**: Cache First 优先
|
||
- **自动更新**: 检测新版本并自动应用
|
||
- **清理旧缓存**: 保持存储空间整洁
|
||
- **📴 离线数据修改**: 支持离线添加、修改、删除密钥(v2.1 新功能)
|
||
- **🔄 后台同步**: 网络恢复时自动同步离线操作(Background Sync API)
|
||
|
||
#### 3. PWA 体验优化(v2.2 新功能)
|
||
|
||
- **📱 智能安装提示**: 自动显示漂亮的安装横幅,引导用户安装应用
|
||
- **📡 离线状态指示器**: 实时显示在线/离线状态,离线时显示醒目的状态标识
|
||
- **🔄 状态同步反馈**: 离线操作和同步状态实时反馈给用户
|
||
|
||
#### 4. PWA Meta 标签
|
||
|
||
- iOS Safari 完整支持
|
||
- Android Chrome/Edge 完整支持
|
||
- Windows 桌面支持
|
||
- macOS 支持
|
||
|
||
### 📴 离线功能详解(v2.1 新功能)
|
||
|
||
#### 支持的离线操作
|
||
|
||
- ✅ **查看已加载的密钥列表**
|
||
- ✅ **生成 OTP 验证码**(本地计算,无需网络)
|
||
- ✅ **添加新密钥**(离线时保存,网络恢复后自动同步)
|
||
- ✅ **修改现有密钥**(离线时保存,网络恢复后自动同步)
|
||
- ✅ **删除密钥**(离线时保存,网络恢复后自动同步)
|
||
- ✅ **批量导入**(离线时保存,网络恢复后自动同步)
|
||
|
||
#### 离线操作流程
|
||
|
||
1. **离线时的操作**
|
||
|
||
```
|
||
用户操作 → Service Worker 拦截
|
||
↓
|
||
保存到 IndexedDB 离线队列
|
||
↓
|
||
返回"操作已保存"提示(202 状态码)
|
||
↓
|
||
显示"您处于离线状态,操作已保存,网络恢复后将自动同步"
|
||
```
|
||
|
||
2. **网络恢复时的同步**
|
||
```
|
||
网络连接恢复 → 触发 Background Sync
|
||
↓
|
||
Service Worker 按时间顺序同步所有操作
|
||
↓
|
||
成功:删除队列中的操作,刷新页面数据
|
||
失败:重试(最多 5 次),超过后标记为失败
|
||
↓
|
||
显示同步结果:"已同步 X 个离线操作"
|
||
```
|
||
|
||
#### 技术实现
|
||
|
||
| 组件 | 说明 |
|
||
| ----------------------- | ------------------------------ |
|
||
| **IndexedDB** | 存储待同步的离线操作 |
|
||
| **Background Sync API** | 网络恢复时自动触发同步 |
|
||
| **Service Worker** | 拦截 API 请求,管理离线队列 |
|
||
| **重试机制** | 失败操作最多重试 5 次 |
|
||
| **冲突检测** | 按时间戳顺序同步,避免数据冲突 |
|
||
|
||
#### 注意事项
|
||
|
||
⚠️ **离线限制**:
|
||
|
||
- 离线时无法获取最新的服务器数据(密钥列表不会更新)
|
||
- 如果多设备同时离线修改同一密钥,后同步的操作会覆盖先同步的
|
||
- 建议单设备使用,或避免在离线时修改相同的密钥
|
||
|
||
✅ **数据安全**:
|
||
|
||
- 离线操作存储在浏览器 IndexedDB 中,不会丢失
|
||
- 即使关闭浏览器,待同步操作仍然保留
|
||
- 网络恢复后会自动同步,无需手动操作
|
||
|
||
#### 浏览器兼容性
|
||
|
||
| 浏览器 | Background Sync | IndexedDB | 离线功能 |
|
||
| ------------ | --------------- | --------- | ----------------- |
|
||
| Chrome 49+ | ✅ | ✅ | ✅ 完整支持 |
|
||
| Edge 79+ | ✅ | ✅ | ✅ 完整支持 |
|
||
| Firefox 117+ | ⚠️ 部分支持 | ✅ | ⚠️ 需手动刷新同步 |
|
||
| Safari 14+ | ❌ 不支持 | ✅ | ⚠️ 需手动刷新同步 |
|
||
|
||
**说明**:
|
||
|
||
- ✅ 完整支持:网络恢复时自动同步
|
||
- ⚠️ 部分支持:需要手动刷新页面触发同步
|
||
- ❌ 不支持:离线操作会保存,但需手动刷新
|
||
|
||
---
|
||
|
||
## 安装指南
|
||
|
||
### 📱 Android(推荐 - 支持 WebAPK)
|
||
|
||
#### Chrome / Edge(推荐)
|
||
|
||
1. **访问应用**
|
||
|
||
```
|
||
https://2fa-dev.guts.eu.org/
|
||
```
|
||
|
||
2. **安装方式**:
|
||
|
||
**方式 1**: 自动提示(推荐)✨
|
||
- 页面底部会自动弹出精美的「安装到桌面」横幅(v2.2 新功能)
|
||
- 横幅会在首次访问后短暂延迟显示
|
||
- 点击横幅上的「安装」按钮即可
|
||
- 如果不想安装,点击「×」关闭横幅
|
||
|
||
**方式 2**: 浏览器原生提示
|
||
- 浏览器地址栏可能会显示安装图标
|
||
- 点击「添加」或「安装」
|
||
|
||
**方式 3**: 手动安装
|
||
- 点击浏览器菜单(右上角 ⋮)
|
||
- 选择「添加到主屏幕」或「安装应用」
|
||
- 点击「安装」
|
||
|
||
3. **验证安装**
|
||
- 应用图标出现在桌面和应用抽屉
|
||
- 从应用抽屉打开,享受全屏体验
|
||
- 在系统设置 → 应用中可以找到「2FA」
|
||
|
||
**特别说明**: Chrome 和 Edge 会生成真正的 WebAPK,提供完整的原生应用体验。
|
||
|
||
---
|
||
|
||
### 🍎 iOS / iPadOS
|
||
|
||
#### Safari(唯一方式)
|
||
|
||
1. **访问应用**
|
||
|
||
```
|
||
https://2fa-dev.guts.eu.org/
|
||
```
|
||
|
||
2. **安装步骤**:
|
||
- 点击顶部工具栏的 **分享按钮** (↑)
|
||
- 向下滚动,找到「**添加到主屏幕**」
|
||
- 点击「添加」
|
||
- 自定义应用名称(可选)
|
||
|
||
3. **启动应用**
|
||
- 从主屏幕点击图标启动
|
||
- 应用以全屏模式运行
|
||
|
||
**注意**: iOS 的 PWA 支持有限:
|
||
|
||
- ✅ 基础离线功能可用
|
||
- ❌ 后台同步受限
|
||
|
||
---
|
||
|
||
### 💻 桌面平台(Windows / macOS / Linux)
|
||
|
||
#### Chrome / Edge / Opera
|
||
|
||
1. **访问应用**
|
||
|
||
```
|
||
https://2fa-dev.guts.eu.org/
|
||
```
|
||
|
||
2. **安装方式**:
|
||
|
||
**方式 1**: 地址栏安装图标
|
||
- 地址栏右侧会出现 **安装图标** (⊕ 或 💻)
|
||
- 点击图标
|
||
- 点击「安装」
|
||
|
||
**方式 2**: 菜单安装
|
||
- 点击浏览器菜单(右上角 ⋮)
|
||
- 选择「安装 2FA ...」
|
||
- 点击「安装」
|
||
|
||
3. **验证安装**
|
||
- 应用图标出现在桌面
|
||
- 应用出现在开始菜单(Windows)或应用程序文件夹(macOS)
|
||
- 可以独立窗口运行,无浏览器UI
|
||
|
||
---
|
||
|
||
## Service Worker
|
||
|
||
### 缓存策略
|
||
|
||
2FA 使用智能分层缓存策略:
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ 静态资源 (Cache First) │
|
||
│ - / (主页面) │
|
||
│ - /manifest.json │
|
||
│ - /icon-192.png, /icon-512.png │
|
||
│ 缓存优先,更新时替换 │
|
||
└─────────────────────────────────────────┘
|
||
|
||
┌─────────────────────────────────────────┐
|
||
│ CDN 资源 (Cache First + CORS) │
|
||
│ - jsQR.min.js (二维码识别) │
|
||
│ - qrcode.min.js (二维码生成) │
|
||
│ 缓存优先,失败时从网络获取 │
|
||
└─────────────────────────────────────────┘
|
||
|
||
┌─────────────────────────────────────────┐
|
||
│ API 请求 (Network Only) │
|
||
│ - /api/secrets │
|
||
│ - /api/backup │
|
||
│ 始终从网络获取最新数据,不缓存 │
|
||
└─────────────────────────────────────────┘
|
||
|
||
┌─────────────────────────────────────────┐
|
||
│ 外部资源 (Network Only + Pass Through) │
|
||
│ - favicon, logo 等 │
|
||
│ 直接透传,失败时静默处理 │
|
||
└─────────────────────────────────────────┘
|
||
```
|
||
|
||
### 自动更新机制
|
||
|
||
Service Worker 会自动检测并应用新版本:
|
||
|
||
- 新版本发布后,后台自动下载和安装
|
||
- 下次访问或刷新页面时自动使用新版本
|
||
- 无需用户手动操作,完全透明
|
||
|
||
**离线状态指示器**:实时显示网络状态:
|
||
|
||
- 📡 当网络断开时,页面右上角会显示"离线模式"指示器
|
||
- 🌐 网络恢复时,指示器自动消失,并显示"正在同步..."提示
|
||
- 离线期间的操作会自动保存到本地队列
|
||
- 网络恢复后自动同步所有离线操作
|
||
|
||
```javascript
|
||
// Service Worker 生命周期
|
||
|
||
1. 安装 (Install)
|
||
↓
|
||
预缓存静态资源和 CDN 库
|
||
↓
|
||
skipWaiting() - 立即激活
|
||
|
||
2. 激活 (Activate)
|
||
↓
|
||
清理旧版本缓存
|
||
↓
|
||
clients.claim() - 立即控制页面
|
||
|
||
3. 拦截请求 (Fetch)
|
||
↓
|
||
根据资源类型应用不同缓存策略
|
||
↓
|
||
返回缓存或网络响应
|
||
|
||
4. 更新检查 (每小时)
|
||
↓
|
||
检测新版本 Service Worker
|
||
↓
|
||
自动更新并通知用户
|
||
```
|
||
|
||
### Service Worker 版本
|
||
|
||
**当前版本**: v2
|
||
|
||
**版本历史**:
|
||
|
||
- `v2` (2025-10-24): 优化 CDN 缓存策略,修复 CORS 错误
|
||
- `v1` (2025-10-23): 初始版本,基础缓存功能
|
||
|
||
**查看 Service Worker 状态**:
|
||
|
||
1. **Chrome DevTools**:
|
||
- F12 → Application → Service Workers
|
||
- 查看注册状态和缓存内容
|
||
|
||
2. **chrome://serviceworker-internals/**:
|
||
- 查看所有已注册的 Service Worker
|
||
- 可以手动卸载或更新
|
||
|
||
---
|
||
|
||
## 故障排查
|
||
|
||
### 问题 1: 安装提示未出现
|
||
|
||
**原因**:
|
||
|
||
- Service Worker 未成功注册
|
||
- 未满足 PWA 安装条件
|
||
- 浏览器不支持 PWA
|
||
|
||
**解决方案**:
|
||
|
||
1. **检查 HTTPS**:
|
||
|
||
```
|
||
确保使用 HTTPS 访问(Cloudflare Workers 自动提供)
|
||
```
|
||
|
||
2. **检查 Service Worker**:
|
||
- Chrome: `chrome://serviceworker-internals/`
|
||
- 查找 `2fa-dev.guts.eu.org`
|
||
- 确认状态为「ACTIVATED and is running」
|
||
|
||
3. **清除缓存并重新访问**:
|
||
|
||
```
|
||
Chrome → 设置 → 隐私和安全 → 清除浏览数据
|
||
选择「缓存的图片和文件」→ 清除
|
||
```
|
||
|
||
4. **等待足够时间**:
|
||
- 访问网站至少 30 秒
|
||
- 让 Service Worker 完成注册
|
||
|
||
---
|
||
|
||
### 问题 2: Service Worker 未注册
|
||
|
||
**检查方法**:
|
||
|
||
1. 打开浏览器控制台(F12)
|
||
2. 查看是否有错误信息
|
||
3. 检查 Application → Service Workers
|
||
|
||
**常见错误**:
|
||
|
||
**错误 1**: `Failed to register service worker`
|
||
|
||
```
|
||
原因: Service Worker 文件无法访问
|
||
解决: 确认 /sw.js 可以正常访问
|
||
```
|
||
|
||
**错误 2**: `DOMException: Only secure origins are allowed`
|
||
|
||
```
|
||
原因: 未使用 HTTPS
|
||
解决: 使用 HTTPS 访问(Cloudflare Workers 自动提供)
|
||
```
|
||
|
||
---
|
||
|
||
### 问题 3: 离线功能不工作
|
||
|
||
**检查清单**:
|
||
|
||
1. ✅ Service Worker 已注册并激活
|
||
2. ✅ 至少访问过一次在线版本(预缓存资源)
|
||
3. ✅ 尝试访问的功能已被缓存
|
||
|
||
**已缓存的功能**:
|
||
|
||
- ✅ 主页面UI
|
||
- ✅ 查看已保存的密钥
|
||
- ✅ 生成 OTP(基于本地时间)
|
||
- ✅ 二维码生成(CDN 库已缓存)
|
||
|
||
**需要网络的功能**:
|
||
|
||
- ❌ 添加/编辑/删除密钥(需要 API)
|
||
- ❌ 备份和恢复(需要 API)
|
||
- ❌ 登录认证(需要 API)
|
||
|
||
---
|
||
|
||
### 问题 4: 应用未更新到最新版本
|
||
|
||
**手动触发更新**:
|
||
|
||
1. **浏览器刷新**:
|
||
- 按 `Ctrl+Shift+R` (Windows/Linux)
|
||
- 按 `Cmd+Shift+R` (macOS)
|
||
|
||
2. **卸载并重新安装**:
|
||
- Android: 设置 → 应用 → 2FA → 卸载
|
||
- iOS: 长按图标 → 删除
|
||
- 桌面: 右键图标 → 卸载
|
||
- 重新访问网站并安装
|
||
|
||
3. **清除 Service Worker**:
|
||
```
|
||
chrome://serviceworker-internals/
|
||
找到 2fa-dev.guts.eu.org
|
||
点击「Unregister」
|
||
刷新页面重新注册
|
||
```
|
||
|
||
---
|
||
|
||
### 问题 5: CDN 资源加载失败
|
||
|
||
**现象**:
|
||
|
||
- 二维码扫描功能不可用
|
||
- 二维码生成功能不可用
|
||
- 控制台显示 CDN 资源加载错误
|
||
|
||
**解决方案**:
|
||
|
||
1. **检查网络连接**:
|
||
- 确保可以访问外部 CDN
|
||
|
||
2. **清除缓存**:
|
||
|
||
```
|
||
Chrome → F12 → Application → Storage → Clear site data
|
||
```
|
||
|
||
3. **检查 Service Worker 缓存**:
|
||
```
|
||
Chrome → F12 → Application → Cache Storage
|
||
查看 2fa-v2 缓存
|
||
确认 jsQR.min.js 和 qrcode.min.js 已缓存
|
||
```
|
||
|
||
---
|
||
|
||
## PWA 最佳实践
|
||
|
||
### 用户体验
|
||
|
||
1. **定期访问在线版本**:
|
||
- 确保获得最新功能和安全更新
|
||
- 更新缓存资源
|
||
|
||
2. **及时同步数据**:
|
||
- PWA 支持离线查看,但数据变更需要网络
|
||
|
||
3. **保持应用更新**:
|
||
- 当看到更新提示时,及时刷新应用
|
||
|
||
### 性能优化
|
||
|
||
1. **首次加载**:
|
||
- 约 1-2 秒(全球平均,Cloudflare CDN)
|
||
|
||
2. **后续加载**:
|
||
- < 500ms(从缓存加载)
|
||
|
||
3. **离线启动**:
|
||
- < 300ms(完全离线)
|
||
|
||
---
|
||
|
||
## 技术规格
|
||
|
||
### Service Worker API 版本
|
||
|
||
| API | 支持状态 |
|
||
| ------------------------ | ----------- |
|
||
| Cache API | ✅ 完全支持 |
|
||
| Fetch API | ✅ 完全支持 |
|
||
| Background Sync | 🚧 预留接口 |
|
||
| Push Notifications | 🚧 计划中 |
|
||
| Periodic Background Sync | 🚧 计划中 |
|
||
|
||
### 浏览器支持
|
||
|
||
| 浏览器 | 版本要求 | PWA 支持 | WebAPK |
|
||
| ------- | -------- | -------- | ------------ |
|
||
| Chrome | ≥ 90 | ✅ | ✅ (Android) |
|
||
| Edge | ≥ 90 | ✅ | ✅ (Android) |
|
||
| Safari | ≥ 14 | 🟡 部分 | ❌ |
|
||
| Firefox | ≥ 88 | 🟡 部分 | ❌ |
|
||
| Opera | ≥ 76 | ✅ | ✅ (Android) |
|
||
|
||
**图例**:
|
||
|
||
- ✅ 完全支持
|
||
- 🟡 部分支持
|
||
- ❌ 不支持
|
||
|
||
---
|
||
|
||
## 未来计划
|
||
|
||
### 🚧 计划中的功能
|
||
|
||
1. **后台同步**:
|
||
- 离线时的操作队列
|
||
- 恢复网络后自动同步
|
||
2. **周期性后台同步**:
|
||
- 定期检查更新
|
||
- 自动备份
|
||
|
||
3. **离线编辑**:
|
||
- 完整的离线 CRUD 操作
|
||
- 自动冲突解决
|
||
|
||
---
|
||
|
||
## 相关文档
|
||
|
||
- [架构文档](ARCHITECTURE.md#pwa-架构) - PWA 技术架构
|
||
- [部署指南](DEPLOYMENT.md) - PWA 部署配置
|
||
- [API 参考](API_REFERENCE.md) - API 端点文档
|
||
|
||
---
|
||
|
||
**Service Worker 版本**: v1 (自动化版本管理)
|
||
|
||
**v2.2 更新内容**:
|
||
|
||
- ✨ 新增智能安装提示横幅
|
||
- ✨ 新增离线状态指示器,实时显示网络状态
|
||
- 📱 优化 PWA 用户体验
|
||
- 🔄 简化更新流程,自动应用新版本
|