Search code examples
ioscachingwkwebviewcapacitor

WKWebView max cached object size


I have an Ionic capacitor react iOS application (which uses WKWebView) with local html and Rest API content

Caching is working for all the API endpoints except one which returns quite a large amount of data (2MB gzipped - 16MB un)

I'd really like this to be cached, but it seems there is a max size that WKWebView is able to store.

If I just lower the about of data the endpoint returns, then caching working i.e. I get 304s

Any ideas what the limit is, how to up the limit, or handle in some other way?

Edit from trial and error it appears limit is 10MB (unzipped - or some weird value of gzipped ~1.2 MB)


Solution

  • The limit of WKWebView cacheable object is 10MB, stored unzipped in the cache.

    It does not seem possible to legitimately up this limit (<= iOS13 at time of writing).

    It is possible to intercept requests with WKWebKit, and use URLSession/URLCache directly. Something to note is that the URLCache will only store a response IF the size of the response < ~5% of the size of the cache - and I imagine this is the same reason WKWebView doesn't cache responses >= 10MB directly. So, in my case I have had to create a URLCache of ~600MB to accommodate this. I tried storing the response manually with storeCachedResponse(_:for:) but seemed to get corruption when retrieving it - not looked into why, having a 600MB cache is just about acceptable for my use case.

    Apple documentation states URLCache will only cache if:

    • The request is for an HTTP or HTTPS URL (or your own custom networking protocol that supports caching).
    • The request was successful (with a status code in the 200–299 range).
    • The provided response came from the server, rather than out of the cache.
    • The session configuration’s cache policy allows caching.
    • The provided URLRequest object's cache policy (if applicable) allows caching.
    • The cache-related headers in the server’s response (if present) allow caching.
    • The response size is small enough to reasonably fit within the cache. (For example, if you provide a disk cache, the response must be no larger than about 5% of the disk cache size.)

    source

    edit further to this I found just upping the URLCache size unreliable, and quite often got cache misses even though the Etag had not changed. Instead I created a separate small URLCache (just over double the data I need to store). Set the cache policy to .reloadIgnoringLocalCacheData and store/retrieve the cached data manually.