Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API shape for monitoring new navigation-like entries such as App History, BFCache, etc #182

Open
nicjansma opened this issue Jun 24, 2021 · 5 comments

Comments

@nicjansma
Copy link

nicjansma commented Jun 24, 2021

As a followup to recent changes for the WICG App History proposal to integrate it with the PerformanceTimeline, we discussed on a recent W3C WebPerf call what kind of API shape would be ideal for monitoring all of the new possible navigation entry types, e.g.:

  • Regular Navigations PerformanceNavigationTiming
    • The only type that exists today
    • Monitored via the navigation keyword in a PerformanceObserver
    • Has fields for network timestamps, .name (URL), etc
  • App History (Soft Navs)
  • BFCache
    • Proposal to have BFCache navs show up, should it have a different entry type than PerformanceNavigationTiming?
    • Would probably want to have the same reduced fields as App History, but maybe even .duration is not appropriate?

One question is: How we want these new navigation types to integrate with the existing PerformanceTimeline and PerformanceObservers?

Today, you simply get a single "the navigation" NavigationTiming entry if you do this:

const observer = new PerformanceObserver(...);
observer.observe({ type: "navigation" });

With these new possible "navigation-like" types, would you get additional entries from the above observer?

Or should we expose them elsewhere?

For example, we may want to require developers to specifically observe new types if they want them (for back-compat):

const observer = new PerformanceObserver(...);
observer.observe({ types: ["navigation", "same-document-navigation"] });

We could also offer a new "super" type to listen for, that would emit entries for the above navigations, plus any new ones that are created in the future:

const observer = new PerformanceObserver(...);
observer.observe({ type: "all-navigations" });

The alternative is to simply emit these new ones under the navigation observer, as IIRC we crawled the web and found that nearly everyone looking at NavigationTiming from a PerformanceObserver was just looking at the [0]th entry.

We had some discussion about this on a recent call, and you can find our minutes here;

This issue is intended as a continuation of that discussion to gather more feedback on the above ideas.

@yoavweiss
Copy link
Contributor

^^ @domenic

@domenic
Copy link

domenic commented Jun 25, 2021

Thanks for starting this thread!

From the web developers we've talked to who work on SPAs, they expect to not start getting SPA navs from their cross-document nav telemetry endpoints, and they expect to get a different set of data. In particular they found the idea of getting all the network timing stuff for SPA navs confusing.

Also, a couple points of clarification:

  • The app history proposal plan is to send "same-document-navigation" for all same-document navigations, whether they're initiated from app history or via other APIs like fragment navigations or history.pushState(). This will become much clearer once we write an actual spec :).

  • There's also the .name field which we inherit from PerformanceEntry. We plan to put the URL there since apparently in performance API land "name" means "URL" :)

@clelland
Copy link
Contributor

In meeting with a number of RUM analytics providers, Google has heard solid support for a new event type for bfcache navs, rather than exposing them as PerformanceNavigationTiming events. It wouldn't need all of the network-level timing members.

There's also a lot of interest, in that case, to have a future-proof "all-navigations" observer (we didn't ask for opinions on the name there; I'm sure there's room to bikeshed)

@clelland
Copy link
Contributor

clelland commented Oct 29, 2021

#192 is the start of an attempt to add support for this.

It seems that there are a couple of ways we could go to have the spec recognize certain performance entries as 'navigations':

  1. The simplest and least extensible is to hard code the list of types which should be considered navigations into this spec, naming them as specific strings.
  2. Just a little bit better is to add an internal boolean isNavigation to PerformanceEntry. This would be set by navigation timing events, app history navs, bfcache navs, etc. In algorithms, we'd use that boolean to match events of pseudo-"type" all-navigations. This makes navigations special, and requires specific handling for them in this spec.
  3. We could instead add a category enum to PerformanceEntry, with values like "Navigation", "Resource", "User", etc, and then specs which create PerformanceEntry objects will need to choose a category for their events. This is similar to the first option, but navigations aren't special: Every category could have similar treatment. It still requires central control over the category list in the PerformanceTimeline spec.
  4. (Most flexible and decentralized) We could make the category a free-form string, set by each spec independently. NavigationTiming, AppHistory, and bfcache navs would all set this to "navigations" or something similar, and PerformanceTimeline wouldn't know about the values that any particular entry uses. Getting entries of "type" all-X would just return all those with category X.

These should all be invisible to the user; this is just about spec ergonomics, and how easy it is to expand on this idea in the future. My inclination is to avoid over-engineering by starting with #2 (an isNavigation boolean) and moving to the more complex solutions when and only when there is a real use case for them.

@clelland
Copy link
Contributor

clelland commented Jun 9, 2023

There's also been significant discussion of this on WICG/soft-navigations#12, but I'll try to steer that discussion back here, since this is where it would eventually need to be implemented.

It sounds like what we need is

  • an id of some sort for all "navigation-like" entries -- @noamr has suggested that the name property could be used, although I don't think we can do that for the initial fetch navigation. We could use a UUID, or a semantic string like "-" instead, or we could even make it opaque and up to the user agent to ensure that they are unique within a document's lifetime.
  • a navigationId property on all timeline entries, to associate them with the navigation which was active when they were created.
  • a getEntriesByNavigationId method to retrieve all object with a given navigation id.

And maybe, for ergonomics:

  • A navigationId key in PerformanceObserverInit?
  • performance.currentNavigationId to know whether an entry is associated with the most recent navigation or not?
  • a supertype, 'all-navigations' for filtering all navigation-like entries, without having to enumerate them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants