Progressive Enhancements
Over the last little while I have been slowly adding in bits and pieces to improve the site. Most of these are recommendations from web.dev.
Web fonts
Web fonts are expensive, and their initial load can be quite costly. Traditionally, web fonts will render invisible text on load 🙀. Once the font is available your content will pop into existence. Good news is that there is a newish css descriptor, font-display, which tells the browser what to do while the font is loading. The bad news is the google font api does not include support for this. To get around this, you can host the font locally and link it in your css.
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-display: swap;
src: local('Roboto Light'), local('Roboto-Light'),
url('../fonts/roboto-v18-latin-300.woff2') format('woff2');
}
Setting the value to swap will cause the text to be rendered as a fallback until the web font is loaded.
This is a good start, but we still have to wait for the browser to load and parse this css file before the browser will kick off a request for the font. Here we can use another newish feature, rel=”preload” to prompt the browser to preload the font.
<link rel="preload" href="/fonts/roboto-v18-latin-300.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/roboto-v18-latin-regular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/roboto-v18-latin-500.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/MaterialIcons-Regular.woff2" as="font" type="font/woff2" crossorigin>
Service workers and caching
Service works are pretty neat. They can operate as another level of cache for the site, and can even make the site available for offline viewing. I opted to use WorkboxJs due to its amazingly simple webpack integration.
new WorkboxPlugin.GenerateSW({
// Exclude images from the precache
exclude: [/\.(?:png|jpg|jpeg|svg)$/],
runtimeCaching: [{
// Match any request ends with .png, .jpg, .jpeg or .svg.
urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
handler: 'cacheFirst',
options: {
cacheName: 'images',
expiration: {
maxEntries: 20,
},
}
},{
urlPattern: /\/post\/\d{4}\/\d{2}\/.*/,
handler: 'cacheFirst',
options: {
cacheName: 'posts',
expiration: {
maxEntries: 40,
},
}
},{
urlPattern: /\/$/,
handler: 'networkFirst',
options: {
cacheName: 'static-pages'
}
}]
})
This is still a work in progress 👷. This will precache my webpack files (css, js, woff files) and offer runtime caching for pretty much everything else. The list pages like /post/, taxonomy pages, or the index page are set as a network first strategy. This means the browser will attempt to load the page from the network before falling back to the cache. This seems ideal for things like recent posts.
The end result
The end result of these changes are a faster loading site ⚡that can be accessed when the user is offline 🎉.