Bug 230343

Summary: Page does not reload properly when cold starting Safari
Product: WebKit Reporter: Mads Erik Forberg <mads>
Component: Page LoadingAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: achristensen, ap, beidson, cdumez, koivisto, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: Safari Technology Preview   
Hardware: Unspecified   
OS: Unspecified   

Description Mads Erik Forberg 2021-09-16 05:37:58 PDT
When opening Safari "cold" (aka. exiting Safari and opening later), the current page is loaded with stale/old content, even though I use `Cache-Control: max-age=0, must-revalidate`. The user has to manually reload the page to get the updated content.
I can use `Cache-Control: no-store` to force reloading, but that would break BFCache, which is somewhat critical for the user experience.

This bug is present in Safari 14 and latest Safari 15.

Is there something I'm missing? Should I do a workaround?
Comment 1 Mads Erik Forberg 2021-09-16 05:41:53 PDT
At least present on iOS 14/15
Comment 2 Alex Christensen 2021-09-17 17:36:57 PDT
I think we'll need more details to look into this bug, ideally a website that exhibits the problem.
Comment 3 Mads Erik Forberg 2021-09-20 05:30:41 PDT
@Alex:

You can reproduce it here with `Cache-Control: max-age=0, must-revalidate`:
1. Visit https://www.vg.no/spesial/_safari-cache/ on Safari (iOS). You'll see the current date and time from server.
2. Close Safari without navigating away from https://www.vg.no/spesial/_safari-cache/
3. Re-open Safari, you'll see the previous date and time present.


The page is properly refreshed when adding `no-store` to Cache-Control, but that header breaks BFCache in Safari, which is not ideal.
Comment 4 Mads Erik Forberg 2021-09-20 05:31:04 PDT
You can see the `no-store` example here: https://www.vg.no/spesial/_safari-cache/no-store.php
Comment 5 Chris Dumez 2021-09-20 07:10:50 PDT
Yes, Safari intentionally shows the previously shown content (even if stale) upon relaunch and restoring session. This behavior is intentional.
Comment 6 Mads Erik Forberg 2021-09-20 07:14:16 PDT
Why is it inentional? Is there a way work around it without using no-store and breaking BFCache?
Comment 7 Chris Dumez 2021-09-20 07:19:12 PDT
(In reply to Mads Erik Forberg from comment #6)
> Why is it inentional? Is there a way work around it without using no-store
> and breaking BFCache?

It is intentional because this is a session restore and we believe a lot of users will want to see the content they were seeing before exiting Safari. It also requires less resources (network & cpu) to load from cache. Also, if the user want to refresh the content, that's what the reload button is for.

I am not aware of any mechanism to avoid this although I am sure somebody could write JavaScript to reload the page under the right circumstances. Sure, no-store will also avoid this behavior because you disable caching altogether.
Comment 8 Mads Erik Forberg 2021-09-20 07:30:31 PDT
(In reply to Chris Dumez from comment #7)
 > It is intentional because this is a session restore and we believe a lot of
> users will want to see the content they were seeing before exiting Safari.
> It also requires less resources (network & cpu) to load from cache. Also, if
> the user want to refresh the content, that's what the reload button is for.


I get that, for some pages, but for a frontpage of a news site it can get stale pretty quickly.


> 
> I am not aware of any mechanism to avoid this although I am sure somebody
> could write JavaScript to reload the page under the right circumstances.


Tried to use `document.lastModified` to check for stale content. But that property is updated to the current date when opening the browser, even though the content is older.


> Sure, no-store will also avoid this behavior because you disable caching
> altogether.


Yep. I would hope there was a header or smth. that can be used for a "best of both world" scenario. Where you would get fresh content from current site and still have BFCache when navigating in the new session.
Comment 9 Chris Dumez 2021-09-20 07:38:25 PDT
(In reply to Mads Erik Forberg from comment #8)
> (In reply to Chris Dumez from comment #7)
>  > It is intentional because this is a session restore and we believe a lot
> of
> > users will want to see the content they were seeing before exiting Safari.
> > It also requires less resources (network & cpu) to load from cache. Also, if
> > the user want to refresh the content, that's what the reload button is for.
> 
> 
> I get that, for some pages, but for a frontpage of a news site it can get
> stale pretty quickly.
> 
> 
> > 
> > I am not aware of any mechanism to avoid this although I am sure somebody
> > could write JavaScript to reload the page under the right circumstances.
> 
> 
> Tried to use `document.lastModified` to check for stale content. But that
> property is updated to the current date when opening the browser, even
> though the content is older.

That seems unexpected. I looked at our code and document.lastModified is only supposed to fall back to the current date if we couldn't find or parse the Last-Modified HTTP header on the main resource response. Are you sure this header is present and properly formatted? If so, you can file a bug about that (ideally with a repro case) and I am happy to take a look.

You could also imagine getting the content's freshness from a hidden HTML element that is part of the content served by the server and then checking it on JS side.

There are definitely ways to implement this in JS if you really want to.

> 
> 
> > Sure, no-store will also avoid this behavior because you disable caching
> > altogether.
> 
> 
> Yep. I would hope there was a header or smth. that can be used for a "best
> of both world" scenario. Where you would get fresh content from current site
> and still have BFCache when navigating in the new session.
Comment 10 Mads Erik Forberg 2021-09-20 07:48:09 PDT
(In reply to Chris Dumez from comment #9)
> (In reply to Mads Erik Forberg from comment #8)
> > (In reply to Chris Dumez from comment #7)
> >  > It is intentional because this is a session restore and we believe a lot
> > of
> > > users will want to see the content they were seeing before exiting Safari.
> > > It also requires less resources (network & cpu) to load from cache. Also, if
> > > the user want to refresh the content, that's what the reload button is for.
> > 
> > 
> > I get that, for some pages, but for a frontpage of a news site it can get
> > stale pretty quickly.
> > 
> > 
> > > 
> > > I am not aware of any mechanism to avoid this although I am sure somebody
> > > could write JavaScript to reload the page under the right circumstances.
> > 
> > 
> > Tried to use `document.lastModified` to check for stale content. But that
> > property is updated to the current date when opening the browser, even
> > though the content is older.
> 
> That seems unexpected. I looked at our code and document.lastModified is
> only supposed to fall back to the current date if we couldn't find or parse
> the Last-Modified HTTP header on the main resource response. Are you sure
> this header is present and properly formatted? If so, you can file a bug
> about that (ideally with a repro case) and I am happy to take a look.
> 
> You could also imagine getting the content's freshness from a hidden HTML
> element that is part of the content served by the server and then checking
> it on JS side.
> 
> There are definitely ways to implement this in JS if you really want to.


I’ll have a look at the header, thanks! :) 
I was just hoping for a header so I could avoid javascript and refetch fre

(In reply to Chris Dumez from comment #9)
> (In reply to Mads Erik Forberg from comment #8)
> > (In reply to Chris Dumez from comment #7)
> >  > It is intentional because this is a session restore and we believe a lot
> > of
> > > users will want to see the content they were seeing before exiting Safari.
> > > It also requires less resources (network & cpu) to load from cache. Also, if
> > > the user want to refresh the content, that's what the reload button is for.
> > 
> > 
> > I get that, for some pages, but for a frontpage of a news site it can get
> > stale pretty quickly.
> > 
> > 
> > > 
> > > I am not aware of any mechanism to avoid this although I am sure somebody
> > > could write JavaScript to reload the page under the right circumstances.
> > 
> > 
> > Tried to use `document.lastModified` to check for stale content. But that
> > property is updated to the current date when opening the browser, even
> > though the content is older.
> 
> That seems unexpected. I looked at our code and document.lastModified is
> only supposed to fall back to the current date if we couldn't find or parse
> the Last-Modified HTTP header on the main resource response. Are you sure
> this header is present and properly formatted? If so, you can file a bug
> about that (ideally with a repro case) and I am happy to take a look.
> 
> You could also imagine getting the content's freshness from a hidden HTML
> element that is part of the content served by the server and then checking
> it on JS side.
> 
> There are definitely ways to implement this in JS if you really want to.
> 
> > 
> > 
> > > Sure, no-store will also avoid this behavior because you disable caching
> > > altogether.
> > 
> > 
> > Yep. I would hope there was a header or smth. that can be used for a "best
> > of both world" scenario. Where you would get fresh content from current site
> > and still have BFCache when navigating in the new session.



Thanks! I’ll dig into last modified in our end. Thanks!
I was just hoping for a «header-way» of refreshing the content to avoid JavaScript so the browser doesn’t wait for the JS execution before refreshing :)
Comment 11 Radar WebKit Bug Importer 2021-09-23 05:38:23 PDT
<rdar://problem/83443450>
Comment 12 Mads Erik Forberg 2023-08-04 02:19:23 PDT
Still an issue in iOS 17 public beta. Is there any hope of fixing the issue? It still seems present if the user visits a site, has that sites app installed and that site has an app-banner.