November 09, 2019

Less JavaScript Makes Font Awesome More Awesome

I decided to use Font Awesome's SVG icons to display social media icons prominently on this site's homepage. I am a long time fan of Font Awesome and supported their Kickstarter campaign in 2017, which was the highest-funded software project on Kickstarter at that time with a total of $1,076,960 pledged. Despite its awesomeness, I did run into a small issue with how the default styles were loaded when adding Font Awesome to this site.

Problem 🐛: CSS loading differently locally vs in-production

Overall, I had a smooth experience implementing Font Awesome and did not experience any major issues when developing but as soon as my site was deployed I noticed that there was a huge discrepancy in the size of the icons as they rendered.

comparing the icon size on final load vs load without javascript

To illustrate this problem using the above GIF, the beginning of the GIF shows how misformatted and large the social icons appeared in production initially (while waiting for JavaScript to fully load or when JavaScript was disabled). Towards the end of the GIF the icons change to the proper styled size. In development the icons only appeared in the proper styled size.

The below screenshot from the Web Page Test further illustrates how the rendering issue manifested in production by showing how the icon appearances changed over time (1.5s to 1.8s) as the page loaded.

a screenshot from the filmstrip from web page speed test showing the icons appearing as different sizes in different snapshots over time

Investigating why the icon styling behaved differently in production vs development led me to understand a bit more how the styles were being applied to my icons and to the realization that using Font Awesome's NPM packages out of the box in a server-side rendered (SSR) application you will likely experience some jarring rendering issues. By default, Font Awesome's NPM packages import styles from "@fortawesome/fontawesome-svg-core". While the CSS loaded from "@fortawesome/... was readily available in development this same CSS was consistently not available on the initial load of the production version of my site causing the icons to initially render too large and then to snap to their proper size. As I looked into this I discovered this rendering issue is a known Font Awesome issue that requires a little bit of additional configuration. The Font Awesome site has some suggestions for handling the issue of CSS not being available on load for server-side rendered applications.

TLDR; CSS local to your application is your friend as the underlying issue is that the availability on the initial page load of JavaScript assets is different locally vs in production for a server-side rendered application.

What is Server-side rendering?

Server-side rendering is when an application generates and sends a complete HTML page from the server to the client on the initial load that doesn't require JavaScript to be available before content can be displayed. After the initial load, Client-side rendering can take over to allow better interactivity."Without Server Side Rendering, all your server ships is an HTML page with no body, just some script tags that are then used by the browser to render the application." (source: Flavioscopes).

For this site I am using GatsbyJS which has server-side rendering configured for the production build of the website which means the initial render has HTML/CSS loaded and "[o]nce a site has been built by Gatsby and loaded in a web browser, client-side JavaScript assets will download and turn the site into a full React application that can manipulate the DOM. " (source: Gatsby Glossary). In other words, the HTML/CSS for this site loads but then additional network requests are made to retrieve additional JavaScript files required for full functionality.

Solution 💡

In order to resolve the issue with the icon font size being too large on initial render, I first needed to replicate the issue in development. To replicate in development, I manually blocked JavaScript from loading for my site in the Chrome Dev Tools. For the production version I was able to block JavaScript from loading by opening the Dev Tools and going to settings > preferences > debugger > and then selecting "disable javascript" however, in development I had to block specific JS files from loading in the Network tab instead or else I saw a message that said "This app works best with JavaScript enabled.".

Reproduce issue by disabling and blocking external JavaScript

Disabling JavaScript allowed me to see the larger icons and to use CSS that replicated the final styling I wanted without relying on external JavaScript.

After finalizing the styles, I also needed to add the following lines to my layout.jsx file. The layout.jsx file is responsible for rendering the overall layout for all content on this site and is where styles are loaded.

import { config, dom } from "@fortawesome/fontawesome-svg-core"
config.autoAddCss = false

The above code removed the Font Awesome CSS which is loaded via JavaScript from the site. The CSS I had written with JavaScript disabled now reflected 100% how I wanted the icons to look and didn't rely on Font Awesome for additional styling. Since the CSS no longer had to be fetched from an external JavaScript file, it became available on the initial load in production and did not require the page to hydrate with additional JavaScript.

Verify Solution

Below is a screenshot from Web Page Test after updating the code to not import CSS from fontawesome-svg-core and only rely on my own CSS.

a screenshot from the filmstrip from web page speed test showing the icons as the same size in each snapshot

The Web Page Test helped me confirm that the rendering issue was resolved in addition to being able to block JavaScript in Chrome DevTools. Web Page Test and Chrome DevTools can be invaluable when debugging 🐛 something related to loading JavaScript in a SSR application.

If you learned something from reading "Less JavaScript Makes Font Awesome More Awesome" consider sharing it.
LinkedIn

Hi, I'm Monica! I'm a Full Stack Engineer who is currently building technology to bring people together IRL at Meetup and focusing on growing the React Ladies community for women + non-binary React developers. I'm interested in discussing React, JAMStack, open-source, tech inclusion, automation and more. 🍿