Reputation: 630
I'm experimenting with dynamically adding <link rel="preload">
tag for loading font files based on the user connection navigator.connection.effectiveType
, e.g. if effective type is '4g' inject <link as="font" type="font/woff2" rel="preload" crossorigin="anonymous" href="inter-var.woff2">
in the head
tag before any other resources, if connection is 'slow-2g' / '2g' / '3g' don't inject link
.
I'm also loading other resources using preload
, but they are not as critical as fonts thus they are injected after the font files.
<head>
// some other code
<script id="connection-type-checker">
(() => {
const inter = document.createElement('link')
const interItalic = document.createElement('link')
const firaCode = document.createElement('link')
inter.as = 'font'
inter.type = 'font/woff2'
inter.rel = 'preload'
inter.crossOrigin = 'anonymous'
inter.href = 'inter-var.woff2'
interItalic.as = 'font'
interItalic.type = 'font/woff2'
interItalic.rel = 'preload'
interItalic.crossOrigin = 'anonymous'
interItalic.href = 'inter-var-italic.woff2'
firaCode.as = 'font'
firaCode.type = 'font/woff2'
firaCode.rel = 'preload'
firaCode.crossOrigin = 'anonymous'
firaCode.href = 'fira-code.woff2'
const insertAfter = (newNode, referenceNode) => referenceNode
.parentNode.insertBefore(newNode, referenceNode.nextSibling)
const target = document.getElementById('connection-type-checker')
insertAfter(inter, target)
insertAfter(interItalic, target)
insertAfter(firaCode, target)
})()
</script>
// **This is where <link>s get injected**
// some other code...
<link as="script" rel="preload" href="script.js" crossorigin="anonymous">
</head>
The problem I'm facing is that Chrome doesn't keep the original order for resources loaded with link preload if the link
element was created with JavaScript (if link elements are inlined as HTML in the head
tag everything works as expected).
Screenshot:
I'm trying to understand why the original order is breaking in Chrome and if it can be fixed?
Upvotes: 3
Views: 304
Reputation: 1383
Chrome engineer here. There are a few inconsistencies here, from what I can tell:
image.jpeg
before the preloads as well, given your pictureWhat you're seeing here is Chrome's (and some other browsers') background HTML parser at work, which is just another lightweight parser that quickly rips through the page looking for resources to speculatively (early) fetch. From debugging Chrome a bit on the example page you've created, the order of events happening is roughly:
script.js
image.jpeg
So in this case you're seeing the speculative/background parser jump ahead a bit, and start fetching things before the main parser is able to via your script
tag. Most browsers have this kind of parser here's an article about it, and unfortunately it is not specified by any standard, since it is not supposed to have any observable (to application code) effects.
However, if you're seeing a performance problem due to this, your best bet is to file a Chromium bug on https://crbug.com and maybe let me know and I can get it in front of the right people.
P.S. I noticed you filed https://github.com/w3c/preload/issues/146, which I'll probably close in favor of you filing a Chrome bug if that's OK.
Upvotes: 1