CSS Preload Scanner in WebKit

In WebKit world, preload scanner refers to a side parser which kicks in if the main HTML parser is halted by a blocking script loading. Because this preload scanner can see what other resources (e.g. stylesheets, images, inputs) are to be fetched, it can trigger the associated network requests as early as possible, without waiting for the main parser to finish, thereby improving the overall loading time. Now, what about speculatively loading dependent resources on a stylesheet instead of the main HTML file? Fortunately, WebKit has something called CSS Preload Scanner.

During the implementation of a standard-compliant HTML5 parser in WebKit, the preload scanner got cleaned up. While the bulk of the scanning still resides in the main HTMLPreloadScanner, a small portion went into its own CSSPreloadScanner. Like its HTML cousin, the job of CSS Preload Scanner is to scan the stylesheet for resources which can be fetched early. For now, it only supports CSS @import rule.

Let us have a look at the following example. In this fragment (not the best practice, only for illustration purposes), we see a script element and a stylesheet:

<p>The quick brown fox jumps over the lazy dog.</p>
<script>setTimeout(function() { document.title = document.title }, 1000);</script>
<p>The quick brown fox jumps over the lazy dog.</p>
<style>
@import url("another-style.css");
body { background-color: white }
</style>

Due to the script element, WebKit parser will invoke the preload scanner, both HTML and CSS flavors. The preload scanner quickly realizes that there is this particular URL within @import. It then schedules the process of fetching another-style.css (the actual request will be tackled by the network stack).

Because CSS preload scanner is pretty simple (it does not need to understand the full CSS grammar), it does the job pretty well. In fact, there was an optimization so that it bails out quickly if @import is not found early in the stylesheet. This is important so that the CPU cycles are not wasted on large CSS files.

The use of @import is often discouraged (see Steve Souder’s don’t use @import). With the current and future improvements inside the browser engine, such a best practice needs to be evaluated again from time to time. Of course, I wouldn’t recommend sprinkling @import everywhere on your web sites. Use the tools available to you (e.g. Web Inspector) to analyze the network performance and then you will be in the position to make an informed decision.

Like in Hamlet, “To import, or not to import”.

Note: Special thanks to Ilya Grigorik for reviewing the draft of this blog post.