Sun Jun 10 2018 15:17:54 GMT-0400 (EDT)

Loading Fonts with webpack

If you're currently using webpack to manage your CSS, importing font files won't work without a little bit of extra configuration.

I've spent more than a few hours fiddling around with webpack and it's various font loading options, and even with the available documentation, getting this to work correctly while still maintaining a basic understanding of what's going is a bit of a headache. Hopefully this post will fix that.

In this tutorial, I'll show you how to get fonts working with webpack and explain the fine details along the way to better your understanding of webpack as a whole. We're going to start with a basic webpack config that compiles SCSS down to CSS. Download the repo, install its dependencies (use yarn or npm install), and let's get started.

Adding File Loader

Without the necessary configuration in place, trying to load a font-face with webpack is going to throw an error that says something along the lines of: "You may need an appropriate loader to handle this file type."

webpack and Fonts Error Message
Attempting to use fonts without any config alterations will force webpack to throw some nasty errors. #rude

Ya don't say webpack?! Let's fix this by adding the appropriate loader as recommended by our terminal errors.

1.Install file-loader

The first thing we have to do is install an external webpack loader called file-loader. File-loader will allow us to import file-based assets into our webpack managed JS and CSS files. Some examples of files we may want to import include images (.jpg, .png, etc.) and font files (.woff2, .eot, etc.), we just need to make sure we tell webpack to run file-loader whenever it comes across one of these files.

Install file-loader by running one of the following commands:

yarn add file-loader --dev

or

npm install file-loader --save-dev

2.Add file-loader to webpack.config.js

After we've downloaded the file-loader package, we then need to integrate it within our webpack.config.js. To do just that, add the highlighted lines of code to your loaders array:

webpack.config.js
module.exports = {
    entry: './src/app.js',
    output: {
        path: __dirname + '/dist',
        filename: 'build.js',
    },
    module: {
        loaders: [
            {
                test: /\.scss$/,
                loader: 'style-loader!css-loader!sass-loader'
            },
            {
                test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
                use: [{
                    loader: 'file-loader',
                    options: {
                        name: '[name].[ext]',
                        outputPath: 'fonts/'
                    }
                }]
            }
        ],
    },
    watch: true,
};

This will tell webpack to search for any fonts being pulled in through one of our webpack entry points, in this case, our entry point is a file in a src directory called app.js.

If webpack finds any font files being referenced inside of any CSS files being pulled into app.js, it'll duplicate the font files, and place them into whatever directory we specify using outputPath. This is required for our fonts to be referenced correctly within our compiled down version of our CSS located in /dist. In this instance, webpack and file-loader will duplicate all fonts to a folder called fonts/ within our dist/ directory since the output path of the fileLoader is relative to the path specified in the output.path property of the overall webpack config.

Restart webpack to ensure that these new changes take effect.

Importing Fonts from Local Files — Font Awesome

All we need to do now is import some fonts into an .scss file and import that .scss file into our app's entry point: app.js. To get quick access to a variety of font files, we're going to be downloading Font Awesome, a font package that contains plenty of font extensions such as .woff, .woff2, .ttf, and so forth.

First, download Font Awesome by running the following in terminal and restarting webpack:

yarn add font-awesome

If your webpack config is watching for CSS instead of SCSS, you'll be able to load all of Font Awesome's fonts by importing its CSS file directly into app.js like so:

src/app.js
import 'font-awesome/css/font-awesome.css';

However, if you're following along with the tutorial repo, webpack will be watching for SCSS files instead CSS files, returning an error in the terminal:

ERROR in ./node_modules/font-awesome/css/font-awesome.css Module parse failed: /Users/christopherlis/web/webpack/cc-extract-text-webpack-plugin/node_modules/font-awesome/css/font-awesome.css Unexpected character '@' (7:0) You may need an appropriate loader to handle this file type.
"You need an appropriate loader to handle this file type." Sound familiar?

This occurs since we haven't set up a way for webpack to watch for .css files—our current config is only watching for .scss files. As a result, we're not going make any alterations our webpack config, rather, we're going to import Font Awesome's CSS file into an .scss file as mentioned earlier.

Importing Fonts via SCSS

To import Font Awesome into an SCSS file, first we'll need to create one. Create a file called style.scss and place it inside of your src directory. Once there, import this newly created file into your app.js entry point like so:

src/app.js
import './style.scss';

Any SCSS written inside of style.scss should now be compiled down to CSS as expected, but as I alluded to, to get Font Awesome working, we need to import its CSS into our newly created style.scss file. We can do so with the following line of code:

src/style.scss
@import '~font-awesome/css/font-awesome.css';

The ~ here means that rather than trying to locate a file relative to our current file's location, locate a file relative to our project's node_modules directory instead. And with that, you webpack should compile without errors, Font Awesome will be bundled into your CSS, and you'll be able to use its fonts within your HTML and CSS files as normal.

Importing Fonts Using an External URL — Google Fonts

To wrap things up, let's go ahead and import some Google Fonts using an external URL.

Now that file-loader is integrated into our config, to load Google Fonts, all we need to do is import the desired font's URL into our style.scss file like we did with Font Awesome. The import statement should look like this:

src/style.scss
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,700|Roboto:100,300,400");

That's all it takes. With that, we can now reference Google font families directly within our SCSS without webpack throwing any errors: font-family: 'Roboto', sans-serif;

Our finished files should look like this:
dist/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Loading Fonts with webpack - Chris Courses</title>
</head>
<body>
    <h1>Loading Fonts with webpack - Chris Courses</h1>
    <i class="fa fa-check fa-lg"></i>
    <script type="text/javascript" src="build.js"></script>
</body>
</html>
src/style.scss
@import '~font-awesome/css/font-awesome.css';
@import url("https://fonts.googleapis.com/css?family=Montserrat:400,700|Roboto:100,300,400");

h1 {
    font-family: 'Roboto', sans-serif;
}
src/app.js
import './style.scss';
webpack.config.js
module.exports = {
    entry: './src/app.js',
    output: {
        path: __dirname + '/dist',
        filename: 'build.js',
    },
    module: {
        loaders: [
            {
                test: /\.scss$/,
                loader: 'style-loader!css-loader!sass-loader'
            },
            {
                test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
                use: [{
                    loader: 'file-loader',
                    options: {
                        name: '[name].[ext]',
                        outputPath: 'fonts/'
                    }
                }]
            }
        ],
    },
    watch: true,
};

And that's a wrap folks, you should now be able to load fonts into your CSS and JS files without webpack throwing any errors.

To summarize, to avoid any font related errors with webpack, you need to download file-loader, integrate it within your webpack config, and import whatever fonts you wish to use into your CSS or SCSS files. If you have some local font files of your own, place them in a font directory within src and reference them within .style.scss using @font-face as you normally would—webpack will see that you're referencing a font file and run it through the file-loader like it did with Font Awesome and Google Fonts.

If you'd like a completed version of the project, clone up the completed repo, install its dependencies, and run yarn for font loading goodness. Otherwise, if you experience any issues along the way, be sure to leave a comment below, I'll do my best to assist. Til' next time, keep it cool and I'll be back with more content this week.

PEACE HOMIES ✌️


Support the Cause

All Chris Courses tutorials are completely free—help support the production of more free blog posts and tutorials via PayPal or Patreon.