lighthouse: Implement a layout-blocking property on networkrequests in Blink

https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js#L58 only checks for script in <head>.

We should expand that to cover blocking scripts within <body> (example). False positives will likely be trickier to deal with. Strawman below.

For all scripts in <body>:

  1. Determine if the script is before the end of the page (document.body.lastElementChild).
  2. If it’s not at the end, check if there’s rendered DOM after it. Filter out script, template, and anything else in the default stylesheet that’s hidden by default.
  3. For all the sibling nodes after the script, check node.offsetParent === null to determine if it is being rendered. Note: cannot use getComputedStyle(node).display === 'none won’t work as expected.

We’ll need to also update the reference do, which talks about scripts in the head: https://developers.google.com/web/tools/lighthouse/audits/blocking-resources

cc @igrigorik

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Comments: 30 (10 by maintainers)

Commits related to this issue

Most upvoted comments

https://chromium-review.googlesource.com/c/chromium/src/+/2626665 landed! (including redirect support) Let the tracing begin!! 😃

🎉 soon we’ll have a trace event for render-blocking styles: https://chromium-review.googlesource.com/c/chromium/src/+/2626665

https://chromium-review.googlesource.com/c/chromium/src/+/5208571

With the latest changes to Chrome, the trace’s renderBlocking signal matches Lighthouse’s TagsBlockingFirstPaint for dbw_tester.html:

❯❯❯ cat latest-run/artifacts.json | jq ".TagsBlockingFirstPaint.[] | .tag.url"
"http://localhost:10200/dobetterweb/dbw_tester.css?delay=100"
"http://localhost:10200/dobetterweb/unknown404.css?delay=200"
"http://localhost:10200/dobetterweb/dbw_tester.css?delay=2200"
"http://localhost:10200/dobetterweb/dbw_tester.css?delay=3000&capped"
"http://localhost:10200/dobetterweb/dbw_tester.js"
"http://localhost:10200/dobetterweb/fcp-delayer.js?delay=5000"

❯❯❯ cat latest-run/defaultPass.trace.json | jq '.traceEvents.[] | select(.name == "ResourceSendRequest" and .args.data.renderBlocking == "blocking") | .args.data.url'
"http://localhost:10200/dobetterweb/dbw_tester.css?delay=100"
"http://localhost:10200/dobetterweb/unknown404.css?delay=200"
"http://localhost:10200/dobetterweb/dbw_tester.css?delay=2200"
"http://localhost:10200/dobetterweb/dbw_tester.css?delay=3000&capped"
"http://localhost:10200/dobetterweb/dbw_tester.js"
"http://localhost:10200/dobetterweb/fcp-delayer.js?delay=5000"

<link disabled> (dbw_disabled aka +2): wow yes this triggers a network request. what? why? spec actually somewhat suggests there shouldn’t be a request. (even if the request is necessary, i don’t see why it should be blocking)

Agree this should not trigger a fetch at all, and definitely not a high priority/blocking one. As it stands (from casually looking at the code), I think it does, so the reporting seems correct.

/cc @foolip and @mfreed7 who may have opinions on the compat implications of this.

I also agree that <link disabled> should not trigger a fetch. We only recently changed the behavior here, but that seems to have settled out without compat issues. Perhaps we could try making this change now? I’m happy to give it a try, unless you’d like to do it.

<link preload css> (dbw_tester.css?delay=2000& aka +3)… the protocol reports the initator as the preload line of html (via parser), so i think its the preload and the requests are not attributed to the attached onload js handler. it doesn’t feel like preloaded css requests are blocking to me.

Should not be blocking, so this sounds like a reporting bug. I’ll look into it.

I just +1’d your CL for this.

<link rel="import"> (aka -6) trace event didnt catch it but I don’t think it was in-scope for yoav. that said, it’d be nice to mark 'em in blink as blocking.

Haven’t we deprecated those?

What’s a <link rel=import>? That’s so Feb 2021 - they’re now gone. 😄