移动端适配与 PWA

2025 年全球移动端流量占比超过 60%,但很多 Web 应用仍然是"桌面优先、移动凑合"。移动端适配不仅仅是"屏幕变小"——触摸交互、网络环境、性能预算、离线能力都与桌面端截然不同。PWA(Progressive Web App)更进一步,让 Web 应用具备原生 App 的体验——安装到主屏幕、离线访问、推送通知。本章系统讲解 Next.js 的移动端适配策略和 PWA 实现。

1. 移动端适配基础

1.1 移动端与桌面端的核心差异

维度桌面端移动端
输入方式鼠标 + 键盘触摸 + 手势
屏幕尺寸1280-2560px320-430px
网络稳定宽带4G/5G(可能不稳定)
性能高端 CPU/GPU中低端处理器
注意力长时间深度使用碎片化短时使用
上下文办公室/家地铁/户外/走路

1.2 Viewport 配置

Next.js App Router 中配置 viewport:

// app/layout.tsx
export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  maximumScale: 1,        // 禁止用户缩放(表单场景避免 iOS 自动缩放)
  userScalable: false,
  themeColor: '#ffffff',
}
配置项推荐值说明
widthdevice-width视口宽度等于设备宽度
initialScale1初始缩放 100%
maximumScale看场景内容站允许缩放,App 型可禁止
themeColor品牌色浏览器工具栏颜色

1.3 触摸交互设计

设计原则说明
点击区域 ≥ 44pxApple HIG 推荐的最小触摸目标
避免 hover 依赖移动端没有 hover 状态
手势友好上下滑动浏览、左右滑动切换
底部导航拇指操作区在屏幕下半部分
避免双击缩放延迟touch-action: manipulation
安全区域适配 iPhone 刘海和底部条

1.4 安全区域适配

现代手机有刘海、挖孔、圆角等异形屏幕,需要使用 env() 函数适配:

.bottom-nav {
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.header {
  padding-top: env(safe-area-inset-top, 0px);
}

Tailwind v4 中可以用 pb-[env(safe-area-inset-bottom)] 内联使用。

2. 移动端性能优化

2.1 移动端性能预算

指标桌面目标移动目标说明
LCP< 2.5s< 2.5s移动端网络慢,需要更多优化
INP< 200ms< 200ms移动端 CPU 慢,JS 执行更耗时
JS Bundle< 200KB< 150KB移动端解析 JS 更慢
首屏图片优化WebP/AVIF + 适配尺寸不要加载桌面尺寸的图片

2.2 响应式图片

不同设备应该加载不同尺寸的图片:

设备屏幕宽度图片宽度预估大小
手机375px375px~30KB
平板768px768px~80KB
桌面1280px1280px~150KB

Next.js &lt;Image&gt; 组件自动处理:

  • 根据设备 DPR 生成 srcset
  • 懒加载视口外的图片
  • 自动转换为 WebP/AVIF
  • 根据容器宽度选择最优尺寸

2.3 移动端特有的性能优化

优化说明
减少 JS 执行量Server Components 把逻辑移到服务端
骨架屏Suspense fallback 替代白屏等待
预连接preconnect 到 API 域名
字体优化font-display: swap + next/font
延迟加载非关键资源dynamic() + loading="lazy"
减少动画prefers-reduced-motion 检测

3. PWA 基础

3.1 什么是 PWA

PWA 是一种让 Web 应用具备原生 App 体验的技术集合:

能力原生 AppWebPWA
安装到主屏幕
离线访问
推送通知
全屏模式
自动更新
应用商店⚠️ 部分
跨平台
无需安装
SEO

3.2 PWA 的三大要素

要素作用必须?
HTTPS安全环境✅ 必须
Web App Manifest定义应用名称、图标、启动行为✅ 必须
Service Worker离线缓存、后台同步、推送通知✅ 核心

3.3 PWA 在 2025 年的现状

平台支持程度限制
Android Chrome⭐⭐⭐⭐⭐完整支持
iOS Safari⭐⭐⭐推送通知支持(iOS 16.4+),但仍有限制
Windows Edge⭐⭐⭐⭐⭐完整支持
macOS Safari⭐⭐⭐⭐Sonoma 开始支持

iOS 的限制

  • Storage 限制(50MB 缓存)
  • 后台执行受限
  • 推送通知需要用户从主屏幕打开
  • 没有完整的 Web App Manifest 支持

4. Web App Manifest

4.1 Manifest 配置

Next.js App Router 中可以通过 app/manifest.ts 生成:

字段说明示例
name完整应用名"My App"
short_name简短名称(主屏幕图标下方)"App"
start_url启动 URL"/"
display显示模式"standalone"
background_color启动画面背景色"#ffffff"
theme_color主题色"#3b82f6"
icons应用图标数组多个尺寸

4.2 显示模式

模式效果适用场景
browser普通浏览器不推荐
minimal-ui最小化浏览器 UI内容网站
standalone无浏览器 UI(像原生 App)App 型 PWA
fullscreen全屏(无状态栏)游戏

推荐 standalone——用户感觉不到是在浏览器中运行。

4.3 图标要求

尺寸用途
192x192Android 主屏幕图标
512x512Android 启动画面
180x180iOS 主屏幕图标(apple-touch-icon
任意 SVG现代浏览器矢量图标

5. Service Worker

5.1 Service Worker 的作用

Service Worker 是运行在浏览器后台的 JavaScript 线程——它拦截网络请求,实现离线缓存、后台同步、推送通知。

用户请求 → Service Worker 拦截
├── 缓存命中 → 直接返回缓存(离线可用)
├── 缓存未命中 + 在线 → 请求网络 → 缓存结果 → 返回
└── 缓存未命中 + 离线 → 返回离线页面

5.2 缓存策略

策略名称行为适用场景
Cache First缓存优先先查缓存,没有才网络静态资源(JS/CSS/图片)
Network First网络优先先网络,失败用缓存API 数据、页面 HTML
Stale While Revalidate先旧后新返回缓存,后台更新非关键但需要新鲜的数据
Network Only仅网络不缓存实时数据(支付、认证)
Cache Only仅缓存只读缓存构建时预缓存的资源

5.3 Next.js 的 Service Worker 方案

方案特点推荐度
@serwist/nextSerwist(next-pwa 继任者),Workbox 底层⭐⭐⭐⭐⭐
next-pwa经典方案,但维护放缓⭐⭐⭐
自定义 Service Worker完全控制⭐⭐⭐(需要手写)
WorkboxGoogle 出品,底层工具⭐⭐⭐⭐

推荐 @serwist/next——它是 next-pwa 的现代继任者,与 App Router 兼容性最好。

5.4 预缓存 vs 运行时缓存

类型时机内容优势
预缓存安装 Service Worker 时JS/CSS/关键页面离线立即可用
运行时缓存用户访问时API 响应、图片按需缓存,节省空间

6. 离线体验设计

6.1 离线策略

策略说明适用场景
离线页面显示友好的离线提示页面所有 PWA 最低要求
离线阅读缓存已访问的内容新闻、博客、文档
离线操作允许用户操作,上线后同步表单、任务管理
完全离线应用核心功能离线可用工具类 App

6.2 离线数据同步

用户离线操作(创建/修改/删除)
    ↓
操作存入 IndexedDB 队列
    ↓
网络恢复
    ↓
Background Sync API 触发
    ↓
逐个提交离线操作到服务器
    ↓
处理冲突(Last Write Wins / 合并)

6.3 离线 UI 反馈

状态UI 反馈
在线正常显示
离线顶部 Banner 提示"当前离线"
操作排队显示"待同步"标记
同步中显示同步进度
同步完成清除标记
同步失败显示错误 + 重试按钮

7. 推送通知

7.1 Web Push 架构

服务端发送推送请求
    ↓
Push Service(Google FCM / Apple APNs)
    ↓
用户设备接收
    ↓
Service Worker 触发 push 事件
    ↓
显示系统通知

7.2 推送通知的最佳实践

实践说明
延迟请求权限不要一打开就弹权限请求
说明价值告诉用户"订阅后会收到什么"
控制频率每天不超过 2-3 条
提供退出应用内提供取消订阅的选项
相关性只推送用户关心的内容
及时性推送时效性强的信息

7.3 权限请求时机

❌ 糟糕的时机✅ 好的时机
首次访问就弹窗用户完成注册后
随机弹出用户主动点击"接收通知"
无上下文在相关场景中(如"订阅订单更新")

8. PWA 适用性评估

8.1 何时选择 PWA

适合 PWA 的场景

  • 内容消费型应用(新闻、博客、文档)
  • 轻量工具型应用(待办、记账、翻译)
  • 电商(浏览 + 收藏 + 推送)
  • 需要跨平台但预算有限

不适合 PWA 的场景

  • 需要深度系统集成(相机高级功能、蓝牙)
  • 高性能图形(3D 游戏)
  • 必须在应用商店分发
  • iOS 用户为主(PWA 限制较多)

8.2 PWA vs 原生 App vs 混合 App

维度PWAReact NativeFlutter原生
开发成本最低最高
性能良好优秀最佳
离线能力有限完整完整完整
系统集成有限大部分大部分完整
更新速度即时即时/商店即时/商店商店审核
SEO
安装门槛几乎无需要下载需要下载需要下载

本章小结

  • 移动优先:触摸交互 ≥ 44px 点击区域、安全区域适配、移动端性能预算更严格
  • 响应式图片:Next.js &lt;Image&gt; 自动处理 srcset、格式转换、懒加载
  • PWA 三要素:HTTPS + Web App Manifest + Service Worker
  • 缓存策略:静态资源 Cache First,API 数据 Network First,非关键数据 Stale While Revalidate
  • Service Worker:推荐 @serwist/next(next-pwa 继任者)
  • 离线设计:操作存入 IndexedDB → 网络恢复后 Background Sync 同步
  • 推送通知:延迟请求权限、说明价值、控制频率
  • 选型:内容/工具类应用适合 PWA,需要深度系统集成的选择原生/RN/Flutter