Using web fonts with SASS and Webpack

12 May 2020
2.0 min read

Linking web fonts in SASS when using Webpack might not work as expected. The most common problem is incorrect URL resolving if a font is linked with url(). This post covers this and the following traps on your way to nice fonts on your webpage.

thumb
Image source: https://processtypefoundry.com/blog/2011/02/five-new-webfonts/

Load fonts

Instruct your webpack how to load font with file-loader:

{
    test: /\.(ttf|eot|woff|woff2|svg)$/,
    use: {
        loader: 'file-loader',
        options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
        },
    },
},

More info about loading fonts options on SurviveJs project.

Resolve URLs

If you use SASS, you must face a problem of resolving URLs. Let's say your Webpack configuration for processing SASS files is like the following.

{
    test: /\.scss$/,
    loaders: [
        'style-loader',
        'css-loader',
        'sass-loader',
    ]
},

Everything looks normal but you still get the following error for every single SASS file.

ERROR in ./src/styles.scss (./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/resolve-url-loader!./node_modules/sass-loader/dist/cjs.js??ref--5-3!./src/styles.scss)
Module not found: Error: Can't resolve './open-sans-v10-latin-regular.woff' in '/Users/varya/WebDev/my-pet-project'
    @ ./src/styles.scss (./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/resolve-url-loader!./node_modules/sass-loader/dist/cjs.js??ref--5-3!./src/styles.scss) 19:42-87

In this case, you need to add resolve-url-loader because SASS itself does not do url rewriting.

{
    test: /\.scss$/,
    loaders: [
        'style-loader',
        'css-loader',
        'resolve-url-loader', // add this before sass-loader
        'sass-loader',
    ]
},

For more information, you can check Problems with url(...) in Webpack official documentation.

SVG, I caught you!

Note that the above configuration also applies to SVG files. You may have other SVG files that you do not want to process as fonts. In this case, do not forget to use include and exclude options.

For the fonts, include only the files from a directory where you keep fonts:

{
    test: /\.(ttf|eot|woff|woff2|svg)$/,
    use: {
        loader: 'file-loader',
        include: path.resolve(__dirname, './src/webfonts'),
        options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
        },
    },
},

For SVG illustrations, exclude the font folder:

{
    test: /\.svg$/,
    exclude: path.resolve(__dirname, './src/webfonts'),
    use: ['@svgr/webpack'],
},

Production: resolve URLs

Now everything works in the development environment, but with production webpack configuration you must get the familiar error for every single SASS file.

ERROR in ./src/styles.scss (./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/resolve-url-loader!./node_modules/sass-loader/dist/cjs.js??ref--5-3!./src/styles.scss)
Module not found: Error: Can't resolve './open-sans-v10-latin-regular.woff' in '/Users/varya/WebDev/my-pet-project'
    @ ./src/styles.scss (./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/resolve-url-loader!./node_modules/sass-loader/dist/cjs.js??ref--5-3!./src/styles.scss) 19:42-87

For production mode, you need to add devtool: 'source-map' to the root of your Webpack configuration. This is for the resolve-url-loader to work correctly also when building for production.

Turn off ES modules

By default, file-loader generates JS modules that use the ES modules syntax. But in the fonts case it would give you src: url([object Module]);. To avoid it, use esModule: false,

{
    test: /\.(ttf|eot|woff|woff2|svg)$/,
    use: {
        loader: 'file-loader',
        include: path.resolve(__dirname, './src/webfonts'),
        options: {
            name: '[name].[ext]',
            outputPath: 'fonts/',
            esModule: false,
        },
    },
},
enjoy

Did you notice a typo? Welcome to edit this page on GitHub. Thank you!

You can hire me and the whole Bridge-the-Gap team to set up, manage, develop, and champion your design system. I can align the design and development processes in your organisation for a larger business impact.

© Varya Stepanova 2024