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.

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)