You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Add non-"fully active" document handling guide
As discussed in w3ctag/design-reviews#628, we want to improve support for BFCache/non-fully active documents, as we noticed that a lot of API specifications do not handle it well/explicitly.
This change adds various guides and things to be aware of related to non-"fully active" documents, including gives various examples. We hope this will help future APIs to handle BFCache/on-"fully active" documents correctly by default.
* Rewrite "discard" bit
* Apply suggestions from code review
Co-authored-by: Domenic Denicola <[email protected]>
* Apply suggestions from review
* Link to pattern
* Add note about prerender
* Link to discard definition
* Link to Geolocation API's TR page.
* Apply suggestions from code review
Co-authored-by: Marcos Cáceres <[email protected]>
* Do not leave document stale
* prerender link
* Use old link for prerender
Co-authored-by: Domenic Denicola <[email protected]>
Co-authored-by: Marcos Cáceres <[email protected]>
the document might be cached in a non-[=Document/fully active=] state,
586
+
and might be reused when the user navigates back to the entry holding the document, which makes navigation fast for users.
587
+
In browsers, this is known as the back/forward cache, or "<abbr title="back/forward cache">BFCache</abbr>" for short.
588
+
In the past, many APIs have missed specifying support for non-[=Document/fully active=] documents,
589
+
making them hard to support in various user agents to cache pages in the BFCache, effectively making the user experience of navigating back and forth less optimal.
590
+
591
+
To avoid this happening with your API,
592
+
you should specify support for non-[=Document/fully active=] documents by following these guidelines:
593
+
594
+
Note: It is possible for a document to not become [=Document/fully active=] for other reasons not related to
595
+
caching, such as when the iframe holding the document gets detached.
596
+
Some advices below might not be relevant for those cases,
597
+
since the document will never return to [=Document/fully active=] again.
598
+
599
+
<h4 id="gate-fully-active">Gate actions with [=Document/fully active=] checks</h4>
600
+
601
+
When performing actions that might update the state of a document,
602
+
be aware that the document might not be [=Document/fully active=]
603
+
and is considered as "non-existent" from the user's perspective.
604
+
This means they should not receive updates or perform actions.
605
+
606
+
Note: It is possible for a [=Document/fully active=] document to be perceived as "non-existent" by users,
607
+
such as when the document is [displaying prerendered content](https://jeremyroman.github.io/alternate-loading-modes/).
608
+
These documents might behave differently than non-[=Document/fully active=] documents,
609
+
and the guidelines here might not be applicable to them,
610
+
as it is written only for handling non-[=Document/fully active=] documents.
611
+
612
+
In many cases,
613
+
anything that happens while the document is not [=Document/fully active=]
614
+
should be treated as if it never happened.
615
+
If it makes more sense to "update" a document to ensure it does not hold stale information
616
+
after it becomes [=Document/fully active=] again, consider the [[#listen-fully-active]] pattern below.
617
+
<div class="example">
618
+
APIs that periodically send information updates,
619
+
such as Geolocation API's {{Geolocation/watchPosition()}}
620
+
should not send updates if the document is no longer fully active.
621
+
They also should not queue those updates to arrive later,
622
+
and only resume sending updates when the document becomes active again,
623
+
possibly sending one update with the latest information then.
624
+
</div>
625
+
626
+
<h4 id="listen-fully-active">Listen for changes to [=Document/fully active=] status</h4>
627
+
628
+
When a document goes from [=Document/fully active=] to non-[=Document/fully active=],
629
+
it should be treated similarly to the way discarded documents are treated.
630
+
The document must not retain exclusive access to shared resources
631
+
and must ensure that no new requests are issued
632
+
and that connections that allow for new incoming requests are terminated.
633
+
When a document goes from non-[=Document/fully active=] to [=Document/fully active=] again,
634
+
it can restore connections if appropriate.
635
+
636
+
While web authors can manually do cleanup (e.g. release the resources, sever connections)
637
+
from within the {{pagehide}} event and restore them from the {{pageshow}} event themselves,
638
+
doing this automatically from the API design allows the document to be kept alive after navigation by default,
639
+
and is more likely to lead to well-functioning web applications.
640
+
641
+
<div class="example">
642
+
APIs that create live connections can pause/close the connection and possibly resume/reopen it later.
643
+
It's also possible to let the connection stay open to complete existing ongoing requests,
644
+
and later update the document with the result when it gets restored, if appropriate (e.g.
645
+
resource loads).
646
+
</div>
647
+
<div class="example">
648
+
APIs that hold non-exclusive resources
649
+
may be able to release the resource when the document becomes not fully active,
650
+
and re-acquire them when it becomes [=Document/fully active=] again
651
+
(Screen Wake Lock API is already [doing](https://w3c.github.io/screen-wake-lock/#handling-document-loss-of-full-activity) the first part).
652
+
</div>
653
+
654
+
Note: this might not be appropriate for all types of resources,
655
+
e.g. if an exclusive lock is held,
656
+
we cannot just release it and reacquire when [=Document/fully active=]
657
+
since another page could then take that lock.
658
+
If there is an API to signal to the page that this has happened,
659
+
it may be acceptable but beware that if the only time this happens is with BFCache,
660
+
then it's likely many pages are not prepared for it. If it is not possible to support BFCache,
661
+
follow the [[#discard]] pattern described below.
662
+
663
+
Additionally, when a document becomes [=Document/fully active=] again,
664
+
it can be useful to update it with the current state of the world,
665
+
if anything has changed while it is in the non-[=Document/fully active=] state.
666
+
However, care needs to be taken with events that occurred while in the BFCache.
667
+
When not [=Document/fully active=], for some cases, all events should be dropped,
668
+
in some the latest state should be delivered in a single event,
669
+
in others it may be appropriate to queue events or deliver a combined event.
670
+
The correct approach is case by case and should consider privacy,
671
+
correctness, performance and ergonomics.
672
+
673
+
Note: Making sure the latest state is sent to a document that becomes
674
+
[=Document/fully active=] again is especially important when retrofitting existing APIs.
675
+
This is because current users of these APIs expect to always have the latest information.
676
+
Dropping state updates can leave the document with stale information,
677
+
which can lead to unexpected and hard-to-detect breakage of existing sites.
678
+
679
+
<div class="example">
680
+
The {{gamepadconnected}} event
681
+
can be sent to a document that becomes [=Document/fully active=] again
682
+
if a gamepad is connected while the document is not [=Document/fully active=].
683
+
If the gamepad was repeatedly connected and disconnected,
684
+
only the final connected event should be delivered.
685
+
(This is not specified yet, see [issue](https://github.com/w3c/gamepad/issues/149))
686
+
</div>
687
+
<div class="example">
688
+
For geolocation or other physical sensors,
689
+
no information about what happened while not [=Document/fully active=] should be delivered.
690
+
The events should simply resume from when the document became [=Document/fully active=].
691
+
However, these APIs should check the state when the document becomes [=Document/fully active=] again,
692
+
to determine if a status update should be sent (e.g. is the current location far away from the
693
+
location when the document becomes not fully active?), to ensure the document has the latest
694
+
information, as guaranteed by the API normally.
695
+
</div>
696
+
<div class="example">
697
+
For network connections or streams,
698
+
the data received while not [=Document/fully active=] should be delivered only
699
+
when the document becomes [=Document/fully active=] again,
700
+
but whereas a stream might have created many events with a small amount of data each,
701
+
it could be delivered as smaller number of events with more data in each.
702
+
</div>
703
+
704
+
<h4 id="omit-non-fully-active">Omit non-[=Document/fully active=] documents from APIs that span multiple documents</h4>
705
+
Non-[=Document/fully active=] documents should not be observable,
706
+
so APIs should treat them as if they no longer exist.
707
+
They should not be visible to the "outside world" through document-spanning APIs
Note: This should be rare since cross-document-spanning APIs are themselves relatively rare.
711
+
712
+
<div class="example">
713
+
{{BroadcastChannel}}[checks](https://html.spec.whatwg.org/multipage/web-messaging.html#broadcasting-to-other-browsing-contexts:fully-active) for [=Document/fully active=] before sending messages to other browsing contexts.
714
+
</div>
715
+
<div class="example">
716
+
{{Clients/matchAll()|clients.matchAll()}}
717
+
currently does not distinguish between [=Document/fully active=]
718
+
and non-[=Document/fully active=] clients,
719
+
but correct implementations should only return [=Document/fully active=] clients.
720
+
(See [issue](https://github.com/w3c/ServiceWorker/issues/1594))
721
+
</div>
722
+
723
+
<h4 id="discard">Discard non-[=Document/fully active=] documents for situations that can't be supported</h4>
724
+
If supporting non-[=Document/fully active=] documents is not possible for certain cases,
725
+
explicitly specify it by [=discard a document|discarding the document|=] if the situation happens after the user navigated away,
726
+
or setting the document's [salvageable](https://html.spec.whatwg.org/multipage/browsing-the-web.html#concept-document-salvageable)
727
+
bit to false if the situation happens before or during the navigation away from the document,
728
+
to cause it to be automatically discarded after navigation.
729
+
730
+
Note: this should be rare and probably should only be used when retrofitting old APIs,
731
+
as new APIs should always strive to work well with BFCache.
732
+
733
+
<div class="example">
734
+
WebSockets [sets the salvageable bit to false](https://html.spec.whatwg.org/#unloading-documents:concept-document-salvageable-7) during unload.
735
+
</div>
736
+
<div class="example">
737
+
Calling {{Clients/claim()|clients.claim()}}
738
+
should not wait for non-[=Document/fully active=] clients,
739
+
instead it should cause the non-[=Document/fully active=] client documents to be discarded.
740
+
(This is currently not specified, see [issue](https://github.com/w3c/ServiceWorker/issues/1594))
741
+
</div>
742
+
743
+
<h4 id="per-document-state">Be aware that per-document state/data might persist after navigation</h4>
744
+
As a document might be reused even after navigation,
745
+
be aware that tying something to a document's lifetime
746
+
also means reusing it after navigations.
747
+
If this is not desirable,
748
+
consider listening to changes to the [=Document/fully active=] state
749
+
and doing cleanup as necessary (see above).
750
+
<div class=example>
751
+
[=Sticky activation=] is determined by the "last activation timestamp",
752
+
which is tied to a document.
753
+
This means after a user triggers activation once on a document,
754
+
the document will have sticky activation forever,
755
+
even after the user navigated away and back to it again.
756
+
Whether this should actually be reset when full activity is lost or not
757
+
is still [under discussion](https://github.com/whatwg/html/issues/6588).
758
+
</div>
759
+
582
760
<h2 id="html">HTML</h2>
583
761
584
762
This section details design principles for features which are exposed via HTML.
0 commit comments