How To Host Fonts And Icons Locally With Webpack

Da Feng
6 min readNov 28, 2021
Photo by CHUTTERSNAP on Unsplash

You might be wondering why we should self-hosting fonts and icons. Isn’t it more common to just link to a public CDN address for fonts and icons? We used to think that it will have a lot of advantages over self-hosting such as:

  • It’s convenient. Just copy the CDN address in our index.html header. Boom! It’s done.
  • It’s quick and efficient. Our browser cache might already have that font downloaded by other websites, so the browser doesn’t even need to download it again.

Well, things change quickly in front-end world. Now people are saying we should self-hosting our static assets. Because we could have many potential risks now using public CDN as public sources. Reading this article by Harry will give you more details about that.

If you also agree with that author, and want to have more control of the fonts and icons that your website is using, please keep reading! In this tutorial, I will show you how to get fonts and icons working with both Webpack 4 and Webpack 5 and host them locally as the following picture shows. Oh! I also made a repo here for the project, feel free to check out if you are interested. So let’s get started!

Prepare the source files of fonts and icons

First, let’s init a project by calling npm init, it will give us a package.json file inside the project folder. Let's move on to pick fonts and icons.

Picking the right fonts and icons for your website is crucial. Luckily, Google Fonts offers us a lot options, there is also a very nice helper website called Google Webfonts Helper, which we can use to choose the right fonts we want. I liked the font Zen Tokyo Zoo , the fonts looks like many zebras, right?

Copy the @font-face snippet and save it into a file and name ittokyo-zoo.scss , webpack will latter use this file as entry point to compile the project.

/* zen-tokyo-zoo-regular - latin */@font-face {  font-family: 'Zen Tokyo Zoo';  font-style: normal;  font-weight: 400;  src: local(''), 
url('./zen-tokyo-zoo-v1-latin-regular.woff2') format('woff2'),
url('./zen-tokyo-zoo-v1-latin-regular.woff') format('woff');
}

Then hit the download button below to download the web-fonts, including woff2, woff, ttf ,eot . In our project, create a folder called fonts and put the scss file and fonts inside the folder.

Icons are essentially fonts also. So it’s actually the same. In this tutorial, I will be using the popular icon library: fontawesome. Unlike google fonts we used, font-awesome ships everything we need in the package. Remember we want to host the icons locally right? So we will install fontawesome as dev dependancy and then use webpack to build it, which will latter be used by our project. That’s why we only need fontawesome as a dev dependancy: npm install @fortawesome/fontawesome-free --save-dev

With that finished, we will have all the sources ready. Next will be the actual fun part: use webpack to build them into css files and use them in our HTML file. So I created an index.html file and installed webpack. Before we code the webpack cofig, let’s have a look at our project now.

Config webpack to build them

Do you notice that in the above picture, I added two links in index.htmlhead?

You guessed right! So I will make webpack compile all the sources and generate two css files inside the dist folder, one for icons and one for fonts.

  • We start with a scss file defining the font-face, which also has reference to the font files with different format.
  • We then config webpack to use the scss file as entry point, use sass-loader to parse scss
  • And then pass result to css-loader to build them into CSS0
  • After that we will need to extract the final result, and take out the CSS part from each of them as our ready to use output.
  • In the same process, we need also copy over the used font files ( woff2, woff and so on)
  • It is also preferred that the final output should be uglified and minified so that the size is small and efficient to use.

With Webpack 4

With all these requirements in mind, here are the webpack plugins that we need in webpack 4:

  • file-loader: load font files with format ttf, eot, svg (these are mostly for older browsers)
  • url-loader: load font files with formt woff, woff2 (these are for modern browsers)
  • sass-loader: loads a Sass/SCSS file and compiles it to CSS, we need also sass
  • css-loader: collect css from all the css files referenced and bundle them all together
  • MiniCssExtractPlugin: extract css out of the final bundle and put them into different files. We can config webpack to bundle many different web fonts at the same time, and then use this plugin to seperate them into it's own css file, so we can use different fonts seperately.
  • UglifyJsPlugin: webpack plugin to uglify the final results

So we need download them as dev dependancies

Notice that, sincecss-loader version 6 and above and sass-loader version 10 and above require webpack 5. So here is the webpack config file using webpack 4:

Webpack 5

Webpack 5 has a new module called Asset Modules, according to webpack official doc:

Asset Modules is a type of module that allows one to use asset files (fonts, icons, etc) without configuring additional loaders.

So with webpack 5, we don’t need to installfile-loader and url-loader anymore, to load all kinds of font files, we can do them all together with just one line of config

Also latest version ofcss-loader and sass-loader both require webpack 5, they are actually more happy to work with webpack 5!

Here is the Webpack5 config file:

Thank you for reading, I hope you like it :)

Bonus: can you help me find the problem?

If you are still here, I actually got a small problem that you might be able to help me :) There problem is this file @fortawesome/fontawesome-free/scss/fontawesome.scss, it is missing 'regular', ‘brands', 'solid', 'v4-shims' that I have to add them after npm install , which is not possible to automate it like this. I tried to created a locall file my-fontawesome.scssunder pathsrc/icon with following content:

then set my-fontawesome.scss file as a entry file in webpack.config.js This is giving me error. I created a branch here. If you know how to fix the problem, please kindly give a reply :)

Have a good day!

--

--

Da Feng

I am a software developer, write blogs about Typescript, Angular, React, vue, Front-end technologies, also share some of my life stories and good memories here.