1. 理解WebView缓存体系
WebView缓存体系是移动端性能优化的核心基础。一个请求从触发到资源加载完成,会依次经过 HTTP缓存、WebKit内核缓存 以及 原生平台缓存三级结构。理解每一层的作用域、触发条件和限制,是实现精准缓存策略的前提。
1.1 HTTP缓存机制
HTTP缓存位于最外层,由服务器和客户端通过HTTP头部字段协商控制。它决定资源是否可以复用(强制缓存)或需要询问服务器是否有效(协商缓存)。
| 缓存类型 | 控制头字段 | 判定流程 | 网络请求 |
|---|---|---|---|
| 强制缓存 | Cache-Control: max-age=xxx / Expires |
客户端直接计算资源是否过期 | 不发送 |
| 协商缓存 | ETag / Last-Modified |
客户端携带验证字段,服务端返回304或200 | 发送(无资源传输或全量传输) |
关键指标:强制缓存命中可减少 100% 网络延迟;协商缓存至少减少 资源传输时间,但请求往返仍存在。Android / iOS 平台上,混合使用两种策略是降低首屏加载时间的基线手段。
1.2 WebKit缓存分层
WebKit内核在HTTP缓存之下维护了多级私有缓存存储层,主要包括 资源缓存(MemoryCache) 和 磁盘缓存(DiskCache)。资源在内存中按DOMId/URL索引,磁盘缓存则以二进制blob的形式存储在应用沙盒中。
# 用于内存缓存的典型内部结构(伪代码描述)
class MemoryCache {
LRUHashMap<URL, Resource*> m_resources;
int m_capacity; // 默认10-15MB
int m_cacheTime; // 默认15-60秒
}
常见陷阱:WebKit磁盘缓存 不支持手动清理单个资源,且不同版本的WebKit对磁盘缓存大小有硬限制(通常为总容量的1/8或最大100MB)。超出后默认驱逐最旧的资源,可能导致频繁缓存未被驱逐前就失效。
1.3 Android / iOS 原生缓存差异
Android和iOS在WebView内部使用不同的原生缓存实现,直接影响开发者可配置的缓存策略与失效行为。
| 维度 | Android (Chromium WebView) | iOS (WKWebView) |
|---|---|---|
| API控制点 | WebSettings.setCacheMode + WebViewClient.shouldInterceptRequest |
URLCache + WKWebsiteDataStore + URLProtocol |
| 磁盘缓存目录 | /data/data/包名/app_webview/Default/Cache |
应用沙盒内 Library/Caches/com.apple.WebKit.WebContent |
| 跨进程隔离 | 是(Android 10+多进程WebView) | 否(WKWebView位于应用内进程) |
| HSTS缓存 | 内置支持 | 仅通过 NSURLSession 间接支持 |
| Service Worker缓存 | 支持(通过 ServiceWorkerController) |
不支持 |
平台取舍:Android端可以借助
shouldInterceptRequest 实现自定义缓存逻辑(如内存LRU+磁盘SQLite),覆盖WebKit默认策略;iOS端建议将 URLCache 的内存和磁盘容量调大(默认内存512KB、磁盘10MB)并配合 WKURLSchemeHandler 实现对特定协议的缓存拦截。
1.4 缓存体系结构总览
下图展示了WebView从请求发起至资源渲染的完整缓存层级关系,以及各层之间的优先级与数据流向。
1.5 本章小结
WebView缓存优化必须建立在对三层缓存体系的理解之上:
- HTTP缓存决定是否发起网络请求,是最快的降本手段;
- WebKit缓存提供内存/磁盘两级存储,但受限于内核默认大小和驱逐策略;
- 原生平台缓存允许开发者通过系统API干预,但Android与iOS的控制能力存在显著差异。