-
Notifications
You must be signed in to change notification settings - Fork 427
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
LoAF Summary attribution information #574
base: v5
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Barry! Left a few comments.
src/attribution/onINP.ts
Outdated
} | ||
totalScriptTime += script.duration; | ||
numScripts++; | ||
totalForcedStyleAndLayout += script.forcedStyleAndLayoutDuration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's an open question whether we should only be taking the blocking/intersecting portion of all duration metrics. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately we can't for forced style and layout since we don't have the timings LoAF. Maybe that's a good reason to keep this simple and just take it for all intersecting scripts (which is what it does currently)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incidentally, it seems like we're leaning subparts
, not phases
for LCP, so we might want to do the same thing here (or object quickly on the LCP side of things :)
I'm cool with subparts so switched to that throughout. |
@rviscomi I've flattened the structure, and updated the comment in #574 (comment) to show that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! I'll try it out in the next RC.
* NOTE: This may be be less than the total count of scripts in the Long | ||
* Animation Frames as some scripts may occur before the interaction. | ||
*/ | ||
numIntersectingScripts: number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather that just listing the number of intersecting scripts, I wonder if it would be more useful to create an array of intersecting scripts (which then someone could easily call .length
on).
Related, how common is it for scripts from multiple different LoAF entries to all be intersecting with INP?
/** | ||
* The number of Long Animation Frames intersecting the INP interaction. | ||
*/ | ||
numLongAnimationFrames: number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems unnecessary because someone could easily do longAnimationFrameEntries.length
, right?
/** | ||
* The INP sub-part where the longest script ran. | ||
*/ | ||
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On web.dev these are currently referred to as "phases". Are we planning to change that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brendankenny I think it was you that told me were were moving towards subparts to mirror LCP, is that right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should definitely unify. I suggested it specifically because we didn't want to simultaneously cement "phases" here in web-vitals and "subparts" over in CrUX, and everyone in the LCP discussions agreed on "subpart".
/** | ||
* The INP sub-part where the longest script ran. | ||
*/ | ||
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay'; | |
subpart: INPSubpart; // 'input-delay' | 'processing-duration' | 'presentation-delay' |
For consistency with other enum-type options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting. Yes as an enum they should use that format. However this is then exposed in output—as both property names and values:
"slowestScript": {
...
"subpart": "processingDuration",
"intersectingDuration": 100,
...
},
"totalDurationsPerSubpart": {
"processingDuration": {
"event-listener": 100
}
},
And so they should really follow camelCase? Though the invoker type is hyphenated (and that's part of the spec) so it's a little inconsistent anyway in that regards
The other consideration is that camelCase is also consistent with what we use for LCP sub parts, but there they are strict property names (not values) and we don't have them defined as an enum.
* The slowest Long Animation Frame script that intersects the INP | ||
* interaction. | ||
*/ | ||
slowestScript: SlowestScriptSummary; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now the SlowestScriptSummary
object duplicates many of the native PerformanceScriptTiming
properties, and it's not clear to me how valuable that is. AFAICT the only "computed" values are subpart
and intersectingDuration
.
What if instead we just had three top-level attribution properties?
slowestScriptEntry
slowestScriptPhase
(or subpart)slowestScriptIntersectingDuration
@@ -24,6 +24,140 @@ export interface INPMetric extends Metric { | |||
entries: PerformanceEventTiming[]; | |||
} | |||
|
|||
export type INPSubpart = | |||
| 'inputDelay' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 'inputDelay' | |
| 'input-delay' |
@@ -24,6 +24,140 @@ export interface INPMetric extends Metric { | |||
entries: PerformanceEventTiming[]; | |||
} | |||
|
|||
export type INPSubpart = | |||
| 'inputDelay' | |||
| 'processingDuration' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 'processingDuration' | |
| 'processing-duration' |
export type INPSubpart = | ||
| 'inputDelay' | ||
| 'processingDuration' | ||
| 'presentationDelay'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 'presentationDelay'; | |
| 'presentation-delay'; |
/** | ||
* The INP sub-part where the longest script ran. | ||
*/ | ||
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subpart: INPSubpart; //'inputDelay' | 'processingDuration' | 'presentationDelay'; | |
subpart: INPSubpart; // 'input-delay' | 'processing-duration' | 'presentation-delay' |
* The slowest Long Animation Frame script that intersects the INP | ||
* interaction. | ||
*/ | ||
slowestScript: SlowestScriptSummary; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I wonder if longestScript
would be better and more consistent with other API names (e.g. Long Tasks and Long Animation Frames).
subpart: slowestScriptSubpart, | ||
intersectingDuration: slowestScriptDuration, | ||
totalDuration: slowestScriptEntry?.duration, | ||
compileDuration: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the ?.
optional chaining operator here seems risky because if slowestScriptEntry
is undefined then you'll end up doing math operations on undefined
, which will result in NaN
.
I know there's been some discussion of removing these properties anyway, but if we don't then it's probably better to just omit these (or set them to 0) if there's no slowest script.
Co-authored-by: Philip Walton <[email protected]>
Co-authored-by: Philip Walton <[email protected]>
Fixes #559
Includes object like this: