4 ms·
> In fact, if your script is not async it's actively _bad_ advice because while the CSS load will start even before the JS has loaded, the JS will NOT run until
by nateberkopec 11y ago
> In fact, if your script is not async it's actively _bad_ advice because while the CSS load will start even before the JS has loaded, the JS will NOT run until the CSS has loaded. If you revers the order, then the JS will run as soon as it's loaded, and the CSS will be loading in parallel with all of that anyway.
Scripts without an async attribute will cause the browser to stop where it's at in the DOM and wait for the external script to download. The browser will not start downloading any stylesheets that come after the script tag until that's done. This is all straight from Google and can be verified in Chrome Timeline. https://developers.google.com/speed/docs/insights/BlockingJS https://developers.google.com/speed/docs/insights/BlockingJS
> So if you put your CSS link before your JS link and the JS is not async, the running of the JS will be blocked on the load of the CSS.
Downloading CSS isn't required to fire DomContentLoaded, so most browsers will download it in a non-blocking fashion. Chrome does not behave in the way in which you describe, which is shown plainly in the article. Again, this can be verified in Chrome Timeline.
All that said, I'm curious as to what browser engine you work when where what you said is the case - I don't doubt it, but you're not describing the way Chrome (and, I suspect, Webkit) works.
Right-o on the bit about DomContentLoaded, will fix.
- evmar 11y agoThere are two kinds of blocking that are easy to confuse. One is network: whether the browser will wait for a resource to fetch before fetching another. The other is execution: whether the browser will wait for a resource to execute (which itself depends on fetching) before executing the next. Script async controls the latter. WebKit (and consequently Chrome) have a "preload scanner" (you can Google for those words to find posts about it) that attempt to parallelize the former in all cases. That is to say, a <script> followed by a stylesheet should always fetch both in parallel. The "async" tag controls whether the browser waits for the script to finish loading and executing before rendering the rest of the page. I think this is a relevant snippet of Chrome code: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp&q=preloadscanner&sq=package:chromium&l=364 https://code.google.com/p/chromium/codesearch#chromium/src/t... That's from the preload scanner, where it's deciding whether to fetch a URL referenced on the page. As far as I understand it this runs in parallel with any script execution blocking etc. (Disclaimer: I worked on Chrome but never on this part.)
- youngtaff 11y agoIt's a couple years old but this is a pretty good explanation of the preloader - http://andydavies.me/blog/2013/10/22/how-the-browser-pre-loader-makes-pages-load-faster/ http://andydavies.me/blog/2013/10/22/how-the-browser-pre-loa...
- paulirish 11y ago(Mostly agreeing, just adding some more)... I suppose theres 3 kinds of blocking really: 1. Network blocking. Requests must wait until the previous one finished. Browsers in 2005 might have done this but not anymore. Even in terrible document.write() scenarios, browsers will still try to do additional work/requests. 2. JS Execution blocking. The difference between [async] and [defer]. Browsers default to executing JS in order, which sucks if an early script takes forever to download. And layout/rendering is typically awaiting all this script to execute anyway. 3. Render blocking. (Or technically, layout blocking). Can the browser try to display pixels before this script has finished downloading or executing? By default, it cannot, but an [async] attribute at least allows the browser to. #2 and #3 definitely matter, with render blocking behavior usually being the most important. [async] and decreasing script request count are very good.
- gsnedders 11y agoFor #2 it's also worthwhile to remember that stylesheets block scripts, so it's not just scripts blocking other scripts.
- gsnedders 11y ago> WebKit (and consequently Chrome) have a "preload scanner" (you can Google for those words to find posts about it) that attempt to parallelize the former in all cases. Everyone does, as far as I'm aware. (And I'm pretty sure this is a case where one can invoke the Opera-did-it-first meme[0].) [0]: http://w3cmemes.tumblr.com/post/62942106027/if-you-can-think-of-it-its-999-likely-opera http://w3cmemes.tumblr.com/post/62942106027/if-you-can-think...
- radicalbyte 11y ago> All that said, I'm curious as to what browser engine you work when where what you said is the case He works on Gecko :) https://github.com/bzbarsky https://github.com/bzbarsky
- bzbarsky 11y ago> Scripts without an async attribute will cause the browser to stop where it's at in the DOM and wait Sort of. The browser will keep looking for things to speculatively download that are past the point where the DOM construction got blocked by the script. In Gecko, this actually speculatively tokenizes the HTML; in WebKit and Blink there's a separate preload scanner that doesn't do a full tokenization pass. In both, the script shouldn't block the sheet downloads starting. I'm fairly certain IE has a similar setup, but I haven't looked at their code, so can't guarantee it. If Chrome Timeline is showing you that the script load blocks the stylesheet load, then it's either a bug in Chrome Timeline or a bug in Chrome's preload scanner; either way you should report it to them, because their intent is that it not block. Or possibly a case of running out of HTTP connections, of course, though I thought their connection limit was higher than that at this point. > I'm curious as to what browser engine you work Gecko. But I've spent a fair amount of time looking through WebKit and Blink sources over the years I've been doing this.