core(preconnect): add warning if preconnect link is not used#6694
Conversation
I actually like that we discard these records. Now your warning message isn't super helpful. If I read it I would add crossorigin to the preconnect tag and I'll see the same message pop up. Sometimes crossorigin helps but the urls listed in the bugs do not get fixed by slapping crossorigin on it. |
As in, you would like it if we started discarding ones started within the first 300 ms? :) Right now it's kinda strict at 50 ms.
Good point, should we not mention it at all then just save it for the docs? |
not sure what the correct timing is on this :) i'm fine with whatever is correct
Yes indeed, maybe just point out that the preconnect fields had no effect and refer to docs |
| async afterPass(passContext) { | ||
| const driver = passContext.driver; | ||
|
|
||
| // TODO(phulce): merge this with the main resource header values too |
There was a problem hiding this comment.
it does seem weird to do it both ways.
instead we could stick to the DOM methods and just new URL(href, finalUrl) for the normalized href.
Or just use the JS version and ditch the other.
There was a problem hiding this comment.
oh we're not doing it both ways it returns the JS way, it seems I never pushed up the removal of the dead code in case people screamed bloody murder about doing it in browser-executed js :)
Yes, but there's a common case where they have added it incorrectly so it's not being used (i.e. missing
This PR is 3, but sounds like you're a fan of 2? |
paulirish
left a comment
There was a problem hiding this comment.
This PR is 3, but sounds like you're a fan of 2?
Hmmm. I guess I'm asking why we say ericbidelman.com should preconnect to https://fonts.googleapis.com.. He already has the preconnect reference (with crossorigin). And it basically looks like the preconnect works? Perhaps this line isn't being satisfied, but probably should be?
// filter out all resources where origins are already resolved
UsesRelPreconnectAudit.hasAlreadyConnectedToOrigin(record) ||
Also unfortunately our UI for warnings in opps is kinda ugly:

| const Gatherer = require('./gatherer'); | ||
| const getElementsInDocumentString = require('../../lib/page-functions').getElementsInDocumentString; | ||
|
|
||
| class LinkElements extends Gatherer { |
There was a problem hiding this comment.
should rename the file as well.
| async afterPass(passContext) { | ||
| const driver = passContext.driver; | ||
|
|
||
| // TODO(phulce): merge this with the main resource header values too |
| return driver.evaluateAsync(`(() => { | ||
| ${getElementsInDocumentString}; | ||
|
|
||
| return getElementsInDocument('link').map(link => { |
There was a problem hiding this comment.
There's probably a difference between link elems in head vs body that will be important at some point, but for now we can ignore it.
|
|
||
| const Gatherer = require('../gatherer'); | ||
|
|
||
| // TODO(phulce): remove this in favor of LinkElements gatherer |
There was a problem hiding this comment.
this is tracked by your issue now so I'll just remove anyway :)
There was a problem hiding this comment.
canonical too fwiw
this is tracked by your issue now so I'll just remove anyway :)
we should split those bullet points up into the implementation steps
| 'Consider adding preconnect or dns-prefetch resource hints to establish early ' + | ||
| `connections to important third-party origins. [Learn more](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect).`, | ||
| /** A warning message that is shown when the user tried to follow the advice of the audit, but it's not working as expected. Forgetting to set the `crossorigin` HTML attribute on the link is a common mistake when adding preconnect links. */ | ||
| crossoriginWarning: 'A preconnect link was found for "{securityOrigin}" but was not used.', |
There was a problem hiding this comment.
Let's mention crossorigin here in the warning.
There was a problem hiding this comment.
I feel weird calling these links. A preconnect "reference"?
There was a problem hiding this comment.
@wardpeet and I discussed and he suggested removing the mention of crossorigin, I somewhat agree and given our other positions it makes some sense to keep it in the docs
Now your warning message isn't super helpful. If I read it I would add crossorigin to the preconnect tag and I'll see the same message pop up. Sometimes crossorigin helps but the urls listed in the bugs do not get fixed by slapping crossorigin on it.
There was a problem hiding this comment.
- would it be terrible to do
"A preconnect <link> was..."to make it clear what's being referenced? - if not going to mention crossorigin, does the string var need a new name?
"was not used"is kind of ambiguous."was not used by the browser"?"was not able to be used by the browser"? followed? honored?- Is there any more hint we can give about what went wrong?
There was a problem hiding this comment.
would it be terrible
nope sounds good
if not going to mention crossorigin, does the string var need a new name?
heh, yes, but hang on one sec
is kind of ambiguous
was not used by the browser SGTM
Is there any more hint we can give about what went wrong?
This is 99% a crossorigin problem IMO, since you and Paul both are on that side and that was my first instinct as well, I think it's worth going back :) sorry @wardpeet!
but he doesn't? :) he's preconnecting to |
|
|
||
| // And that they have the correct shape. | ||
| opportunityResults.forEach(auditResult => { | ||
| assert.strictEqual(auditResult.details.type, 'opportunity'); |
There was a problem hiding this comment.
any reason for this change?
There was a problem hiding this comment.
yeah I failed this test while I was working and the error message you get is useless, this way it shows you what audit details you actually did get back so you know where to go fix
| 'Consider adding preconnect or dns-prefetch resource hints to establish early ' + | ||
| `connections to important third-party origins. [Learn more](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect).`, | ||
| /** A warning message that is shown when the user tried to follow the advice of the audit, but it's not working as expected. Forgetting to set the `crossorigin` HTML attribute on the link is a common mistake when adding preconnect links. */ | ||
| crossoriginWarning: 'A preconnect link was found for "{securityOrigin}" but was not used.', |
There was a problem hiding this comment.
- would it be terrible to do
"A preconnect <link> was..."to make it clear what's being referenced? - if not going to mention crossorigin, does the string var need a new name?
"was not used"is kind of ambiguous."was not used by the browser"?"was not able to be used by the browser"? followed? honored?- Is there any more hint we can give about what went wrong?
| const URL = artifacts.URL; | ||
| const settings = context.settings; | ||
| const preconnectLinks = artifacts.LinkElements.filter(el => el.rel === 'preconnect'); | ||
| const preconnectOrigins = new Set(preconnectLinks.map(link => URL.getOrigin(link.href || ''))); |
There was a problem hiding this comment.
move these two lines down below where they're used?
| */ | ||
| 'use strict'; | ||
|
|
||
| const Gatherer = require('./gatherer'); |
There was a problem hiding this comment.
I think we settled(ish) on .js going forward?
| crossorigin: link.crossorigin, | ||
| }; | ||
| }); | ||
| })()`, {useIsolation: true}); |
There was a problem hiding this comment.
a rare useIsolation sighting!
| rel: link.rel, | ||
| href: link.href, | ||
| as: link.as, | ||
| crossorigin: link.crossorigin, |
There was a problem hiding this comment.
link.crossOrigin
(we probably want to go with the same camel case for the artifact property as well?)
There was a problem hiding this comment.
good points, maybe I shouldn't bring in attributes I'm not using yet 😆
| rel?: string | ||
| href?: string | ||
| as?: string | ||
| crossorigin?: string |
There was a problem hiding this comment.
shouldn't these all be required since the browser will normalize to at least an empty string? Or we could have the gatherer explicitly drop '' in favor of undefined.
And from the spec/a quick test, crossorigin can be null | 'anonymous' | 'use-credentials' (the browser corrects anything else to `'anonymous')
There was a problem hiding this comment.
yeah, SGTM I'll change to match spec
| "path": "accessibility", | ||
| }, | ||
| Object { | ||
| "path": "external-resource-links", |
There was a problem hiding this comment.
travis failure is just needing to update this snapshot
|
|
||
| const Gatherer = require('../gatherer'); | ||
|
|
||
| // TODO(phulce): remove this in favor of LinkElements gatherer |
There was a problem hiding this comment.
canonical too fwiw
this is tracked by your issue now so I'll just remove anyway :)
we should split those bullet points up into the implementation steps
There was a problem hiding this comment.
This seems great and love the new artifact.
Smoke testing for the gatherer will follow when the other audits are moved to use this artifact, but any chance of getting a preconnect warning smoke test as well? We have one suggested preconnect origin in preload_style.css already, maybe we could add another and a failing <link rel="preconnect"> in the preload.html test page?
this one is trickier because it needs new origins, are you onboard for introducing external internet dependencies into the local smoke tests? I was holding off because of that, but I think a google fonts smoketest for this would the ideal test case since it's also what I imagine is the most common real-world scenario |
ha, maybe it is time to give up on that. We do have the two static_server ports so we can technically request from a different origin (used in e.g. An external dependency is also not as big a deal as it once was for e.g. testing on a plane since I guess the big thing would be how flakey it would end up being. Ideally google fonts will be pretty reliable? |
Yeah but that's the one we're already using for real so we already ran out of origins to use for warnings! 😆
Yeah I agree here, I'll take the plunge |
brendankenny
left a comment
There was a problem hiding this comment.
LGTM!
over to @paulirish
| rel: string | ||
| href: string | ||
| as: string | ||
| crossOrigin: string|null |
There was a problem hiding this comment.
not worth the extra specificity?
There was a problem hiding this comment.
not totally sure which direction you're suggesting going :)
There was a problem hiding this comment.
'anonymous'|'use-credentials'|null instead of just string|null. It might not buy us anything (maybe if we end up with a switch statement somewhere).
There was a problem hiding this comment.
oh gotcha, sure!
|
👏 sweet, looking good |
Summary
This PR adds a warning to the preconnect audit when the origin is found in a
link[rel=preconnect]but still isn't being used. Usually it's because of a missingcrossoriginbut good to be aware of either way.I'd also like to start ignoring origins that were discovered within ~300 ms or so of the main document since that's basically what preconnect would do anyway, but thought I'd bring that up for discussion first.
#6676 also suggested mentioning a limit on the number of preconnect origins in our help text. I think that makes sense but goes against our "it's all in the learn more link" stance. Others Ok with it?
Related Issues/PRs
fixes #5932 #6676