Showing posts with label stylesheets. Show all posts
Showing posts with label stylesheets. Show all posts

Saturday, 20 January 2018

Lazy loading stylesheets - resource hints

One thing I forgot to mention in my previous post on lazy loading stylesheets using loadCSS, was how you can improve performance even further by tipping the browser off to what you're going to lazy load in advance.  This is called using resource hints.

There are a few different levels of hint that you can use, so I'll go through them individually, before giving the example that I've used.


DNS Prefetch

This tells the browser that there will be a file required from this domain, and that it should get a head start by doing the DNS lookup (converting the domain name into an IP address).

For example...
<link rel="dns-prefetch" href="https://example.com">
Preconnect

This tells the browser to go a step further and make the TCP handshake - this is required at the start of each TCP connection.  It will also do the TLS negotiation, if the link points to an https: resource - this is where the browser and the server decide what type of encryption they both understand.

For example...
<link rel="preconnect" href="https://example.com">

Prefetch

This is used to download and cache a particular resource, so can be used if you're sure a particular asset will be required later.  The file is downloaded as relatively low priority, but will still give the browser a head start - this is often used for fetching files for the next anticipated page or future interaction on the current page.

For example...

<link rel="prefetch" href="https://example.com/style.css">

Subresource

This is similar to prefetch, in the sense that it is used to download and cache a particular resource.  However, the file is downloaded as a high priority, meaning it is best used when requesting files for the current page.  Having said that, this has been superceded by "preload" and has been removed from Chrome.


So for me, I typically like preconnect.  In my example from my lazy loading stylesheets using loadCSS post, I was lazy loading a Google Font stylesheet.  In this case, there are two domains I want to preconnect to, which can be done like this...
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com">
The first is the location of the stylesheet itself, and the second is the location of the font file that will subsequently be downloaded.  I could use prefetch on the stylesheet file itself, if I wanted to, but this returns dynamic content based on your browser, so it would be impossible to prefetch the web font file itself.

Thursday, 18 January 2018

Lazy loading stylesheets using LoadCSS

In my last post, I talked about adding stylesheets into my Gulp file, part of my new development process.  The follow on to this for me was thinking about whether all of those stylesheets were really needed up front.  As I explained in that post, concatenating them and minifying them will certainly reduce the overall filesize, and the number of TCP connections (and therefore time), but what if some of this could be delayed until after the page had even loaded?

This is often referred to as lazy loading.  The Filament Group have created a great plugin for this called loadCSS, which can be found on NPM as fg-loadcss.  Their description of why you should be using it goes like this...
Referencing CSS stylesheets with link[rel=stylesheet] or @import causes browsers to delay page rendering while a stylesheet loads. When loading stylesheets that are not critical to the initial rendering of a page, this blocking behavior is undesirable. The new <link rel="preload">standard enables us to load stylesheets asynchronously, without blocking rendering, and loadCSS provides a JavaScript polyfill for that feature to allow it to work across browsers. Additionally, loadCSS offers a separate (and optional) JavaScript function for loading stylesheets dynamically.

The "preload" option is not well supported at all currently, so for the time being at least, a polyfill of this nature is definitely required.

As I'm already using Browserify in my javascript Gulp task, this is really easy to add into my javascript file.  Obviously I need to first install the fg-loadcss package, and then I can add the following lines of javascript...
  var loadcss = require("fg-loadcss");
  var reflink = $("head").children("link[rel=stylesheet]").get(-1);
  loadcss.loadCSS("https://fonts.googleapis.com/css?family=Indie+Flower",reflink);


This first requires the package (which Browserify will pull in), then finds a reference element (it will insert the <style> tag directly after this one) and then it calls the manual "loadCSS" function with the path to the stylesheet.  In my example, this is to a Google Font file.

This manual method is actually not part of Filament Groups recommended workflow, but I prefer it, as it keeps the code neat in my opinion, and runs it after my javascript is running, which I think is best for non-critical styles.  If you look on their Github repo, they do give other example usage though.

You can then remove the reference to the stylesheet from the <head> section, or better yet, move it to the very bottom of your page with a no-javascript fallback, like this...
<noscript><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Indie+Flower"></noscript>

This means that even if javascript is disabled, your stylesheet (or font, in my case) will still load, which is great!

I didn't get the chance to cover this in my Optimising your website: A development workflow with Git and Gulp course on Skillshare, but I hope to add it into a future course.