Search code examples
webpackcss-loaderwebpack-file-loader

Webpack 4: css-loader + file-loader to add fonts and their stylesheets in the build process


Given this setup:

fonts/styles.css

@font-face {
  family: 'MyFont';
  src: url('fonts/myfont.otf');
}

How can I:

  1. in my JS bundle, obtain a reference to the URL of the CSS file, as a string, e.g. [name].[hash].css
  2. the generated CSS file should be a plain CSS file, but with url()s pointing to the generated webfont files?

Something like:

@font-face {
  family: 'MyFont';
  src: url('myfont.dds9394u329d9sa9r8439.otf');
}

I'm trying with:

webpack.config.js

{
  test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
  loader: 'file-loader',
  include: [/fonts/]
},

{
  test: /\.css$/,
  use: ['file-loader', 'css-loader'],
  include: [/fonts/]
}

JS file

const myfont = {
  family: 'MyFont',
  stylesheet: require('fonts/styles.css')
}

As per a previous question, using file-loader and require() works well to get the URL for the CSS, but the generated file is not plain CSS.

How can I combine file-loader and css-loader (+ possibly other loaders) to obtain this CSS file?

Thanks!

P.S. I would like to avoid copy-webpack-plugin for this, because I want the CSS / font files to be hashed and addressable in code.


Solution

  • For posterity: this is the Webpack configuration with which I was able to obtain the result I was looking for.

    module: {
      rules: {
        // Font stylesheets
        {
          test: /\.css$/,
          use: [
            {
              loader: 'file-loader',
              options: {
                name: 'css/[hash].[ext]'
              }
            },
            'extract-loader',
            'css-loader',
            'postcss-loader'
          ],
          include: [/fonts/]
        },
    
        // Font files
        {
          test: /\.(woff|woff2|ttf|otf)$/,
          loader: 'file-loader',
          include: [/fonts/],
    
          options: {
            name: '[hash].[ext]',
            outputPath: 'css/',
            publicPath: url => '../css/' + url
          }
        },
      }
    }