Load Web Fonts Asynchronously to Avoid Render-Blocking CSS

Render-blocking CSS resources, such as web fonts, can hinder the performance of your website for your users. This is important for several reasons. First, we want to minimize the initial page rendering time. And second, we want to get a good PageSpeed Insights score. ūüôā

pagespeed_insights

Your page has 2 blocking CSS resources. This causes a delay in rendering your page.

Have you ever seen the error above in the PageSpeed Insights tool as a result of loading web fonts? In this brief tutorial I am going to show you how to load your web fonts asynchronously to avoid this issue. If you are not familiar with CSS and web fonts, check out our CSS3 for Web Designers and Developers course where we cover CSS3 topics, including web fonts.

Avoid @import

The first mistake I made was using @import to load the web fonts:

/* Import Google Open Sans Font */
/*@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,500italic,600italic,700italic,400,500,600,700);*/

/*Import Google Roboto Font */
@import url(https://fonts.googleapis.com/css?family=);

This causes the browser to fetch the resource prior to the rendering of the page. This is because the browser is programmed to fetch and parse all CSS resources that are defined using @import or the <link rel="stylesheet"> tag. To avoid this, we can load¬†our web fonts asynchronously. While that might sound difficult, it’s not, thanks to TypeKit’s Web Font Loader open-source project.

Web Font Loader

A big thank you to the TypeKit team that has provided the Web Font Loader project. I am going to use¬†Google’s Font API in my examples. If you are loading fonts from another source, such as TypeKit or FontDeck, check out the documentation for¬†Web Font Loader on GitHub.

In this tutorial I am going to use¬†the Node Package Manager (npm), which is part of Node.js. If you have not already installed Node.js then follow one of Webucator’s how-to articles:

If you want to learn more about Node.js and npm, check out¬†our Node.js Software Development Training course. It’s a 2-day course where you learn the basics of Node.js, using npm for dependency management, accessing the file system, and even running an HTTP server using Express.

Ok, let’s install the Web Font Loader library using npm:

$ npm install webfontloader --save

Notice that I am using the --save flag so that the webfontloader dependency will be saved into my project’s package.json file.

Webpack

Next, I am going to use Webpack to load the webfontloader.js file into a vendor bundle. I like to separate out the JavaScript (JS) for a project into two bundles: a vendor bundle and an application bundle. The vendor bundle contains all of the JS libraries that I am using. These do not change much, so I can let this file be cached in the browser. The application bundle contains all of the JS code for my application, which changes frequently with each release. I then use cache busting strategies on my application bundle file when pushing a release.

Here is what my webpack.config.js file looks like:

var path = require("path");
var webpack = require("webpack");

module.exports = {
  "devtool": "source-map",
  "entry": {
    //main entry
    "main": path.resolve(__dirname, "./js/src/main.ts"),

    //third-party libraries
    "vendor": [
      //others ommitted
      "webfontloader"
    ]
  },
  "output": {
    "path": "./js/build",
    "filename": "[name].bundle.js"
  },
  "resolve": {
    "alias": {

      //webfontloader (https://github.com/typekit/webfontloader)
      "webfontloader": path.resolve(__dirname, "./node_modules/webfontloader/webfontloader.js")
    },
    "extensions": ["", ".webpack.js", ".web.js", ".js", ".ts"],
    "modulesDirectories": ["node_modules", "bower_components"]
  }
};

Some things to note:

  • Within the enty.vendor array I have included the webfontloader dependency.
  • I defined the webfontloader alias within the resolve.alias object.

Install TypeScript Declarations

In this tutorial I am going to use TypeScript. You can ignore the typings in my code examples and skip this step on installing the TypeScript definitions if you are using vanilla JS.

If you do not have typings installed, let’s do that first:

$ npm install typings --global

I installed typings globally so that I can use it in other projects as well. You can choose to not do this, and then access the binary in ./node_modules/.bin/. Once we have typings installed, let’s install the webfontloader TypeScript declaration files:

$ typings install dt~webfontloader --global --save

Let’s break down this command, as it is a bit long and potentially confusing. The typings install¬†portion¬†is pretty simple; we’re telling the typings command to run the install command. Then we provide the location. We are instructing typings to use the source dt and the package webfontloader. The source of dt stands for DefinitelyTyped, which is a publicly available repository of TypeScript declaration files. The source of the webfontloader declaration file can be found on GitHub in the DefinitelyTyped repository. Finally, we specify the --global and --save flags. The --global flag instructs typings to install and persist the declaration file as a global definition. And the --save flag instructs typings to save the dependency to the typings.json file.

Load Fonts via WebFont

We are now ready to require the WebFont module into our TypeScript code and to load our web fonts asynchronously using Web Font Loader. First, we need to require() the WebFont module:

//require webfontloader
var WebFont = require("webfontloader");

Next, create a configuration object for WebFont. This is where you will use your own configuration based on the web fonts in your application or on your website. I am going to use¬†Google’s Open Sans and Roboto fonts.

let config: WebFont.Config = {
  google: {
    families: [
      "Open Sans:400italic,500italic,600italic,700italic,400,500,600,700",
      "Roboto:400,900,100"
    ]
  }
};

Finally, using the config object, load the fonts using the load() static method on WebFont:

WebFont.load(config);

To verify everything is working, check Chrome’s Network tab in the Development Tools and you should see that the fonts are now being loaded using webfontloader.js:

web font loader


About Webucator

Webucator provides instructor-led training to students throughout the US and Canada. We have trained over 90,000 students from over 16,000 organizations on technologies such as Microsoft ASP.NET, Microsoft Office, Azure, Windows, Java, Adobe, Python, SQL, JavaScript, Angular and much more. Check out our complete course catalog.