How to: Ensure proper iconfont rendering with Webpack

Posted . Visible to the public.

Background

After switching a project from Sprockets to Webpack, I started observing a bug that was hard to debug: Our custom icon font could sometimes not be displayed until a full page reload.

Digging deeper the only difference before and after the page load was the encoding interpretation of the iconfont stylesheet:

Correct representation (UTF-8):

.icon:before {
    content: ""
}

Broken representation (other charset):

.icon:before {
    content: "ï„""
}

Other people have the same issue Show archive.org snapshot , it could be a bug in Chrome.

Now, according to MDN Show archive.org snapshot there are three non-obsolete ways to manually define the charset of a CSS file:

  1. The value of the Unicode byte-order character placed at the beginning of the file (BOM).
  2. The value given by the charset attribute of the Content-Type: HTTP header or the equivalent in the protocol used to serve the style sheet.
  3. The @charset CSS at-rule.

Sprockets

The asset pipeline (with Sprockets) does not seem to be affected by this issue, as every generated file includes a BOM.
The first rule above is fulfilled.

You can check if a file has a BOM with the file command, e.g. file styles.css should include the text "(with BOM)".

Webpack

Webpack does not include a BOM per default. Adding the unpopular library webpack-utf8-bom Show archive.org snapshot to my project (production.js) solved the issue for me. Or at least, I did not encounter it again yet.
You might have to upgrade Webpack to version 5 for this approach.

Adding the @charset "UTF-8"; rule to my stylesheet seemed easier at first, but turned out to be very hard to archive outside the development environment. See the issue @import invalidates @charset declaration Show archive.org snapshot for more context.

Using the Content-Type: charset=UTF-8 header might do the trick for you. I decided against it as it implied changing both manual and automatic rules for CSS files at the Load Balancer and CDN. Setting the charset globally to utf-8 may cause other issues as the original charset (e.g. UTF-16) is no longer respected.

Profile picture of Michael Leimstädtner
Michael Leimstädtner
Last edit
Jakob Scholz
License
Source code in this card is licensed under the MIT License.
Posted by Michael Leimstädtner to makandra dev (2021-06-23 07:58)