Search code examples
csswebpackfontsfont-face

Webpack configuration for css @font-face? Current setup changes url() to a very long string


I am bundling and minimizing my css's with webpack 5.4.0

This goes ok, except for the fonts.css file, which originally is simply this:

@font-face {
  font-family: 'Kulim Park';
  font-style: normal;
  font-weight: 400;
  src: url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.eot');
  src: local(''), url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.eot?#iefix') format('embedded-opentype'),
    url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.woff2') format('woff2'),
    url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.woff') format('woff'),
    url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.ttf') format('truetype'),
    url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.svg#KulimPark') format('svg');
}

@font-face {
  font-family: 'Staatliches';
  font-style: normal;
  font-weight: 400;
  src: url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.eot');
  src: local('Staatliches Regular'), local('Staatliches-Regular'),
    url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.eot?#iefix') format('embedded-opentype'),
    url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.woff2') format('woff2'),
    url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.woff') format('woff'),
    url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.ttf') format('truetype'),
    url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.svg#Staatliches') format('svg');
}

The final bundle is kilometric, the url() is transformed into this (in development, in production with the "correct" part minimized)

@font-face {
  font-family: 'Kulim Park';
  font-style: normal;
  font-weight: 400;
  src: url(data:application/vnd.ms-fontobject;base64,kEoAAIxJAAACAAIABAAAAAAAAAAAAAAAAAABAJABAAAAAExQJwAAgEsAAAAAAAAAAAAAAJMAACAAAAAA3HSrPQAAAAAAAAAAAAAAAAAAAAAAABQASwB1AGwAaQBtACAAUABhAHIAawAAAA4AUgBlAGcAdQBsAGEAcgAAAEYAVgBlAHIAcwBpAG8AbgAgADEALgAwADAAMAA7ACAAdAB0AGYAYQB1AHQAbwBoAGkAbgB0ACAAKAB2ADEALgA4AC4AMwApAAAAJABLAHUAbABpAG0AIABQAGEAcgBrACAAUgBlAGcAdQBsAGEAcgAAAAAAQlNHUAAAAAAAAAAAAAAAAAAAAAADAIcAADulAEPpADWAEs3pishg2FfJaEtyb3BxIlU6Yiwvlj0Tx7en4cGPvQIuQaxIgG1JJSQGliGIUdk3GlqcHgcNRFx0xGTawgT7oKcSv0LGOIBgp/67SUixSTBAOLp3AixitjCZniGkUSZ0ZK7pGtw8aIkw+KDQEo11ZXwXGrQSlXZVee5mStSqmu0ptfSoJXlHVLUgwdIhShAkIY9nWdD6aQdYMm1k/8k06Saw34XfjmSk89dni9ec76k0/XN1AgIGqC//IeABHG5Vm/a7wNALJha++urEAA0pw9wGdf/Slb0Ol9qC5x9G1lQw2NpHmEGnTX3FnTmawqPNHEvOZ7CDF1aViYcI2E30T1rBJDRHr8OcWCPOFgjz5VIe7yZet7lCfZKNzOlGNAVwDuzHuTvxRUTGCKEw+p0CcWJIRdVcXJj/JtABvCOFpCCBXs/jsMEqd2WQ9ZapOu1g9pRMSvsWvo9kDkWcnibydGX14O2GSSkALNi1zGex257sCJgo4xLAYrzvRLfxMelGEkSMdyGUXagBW4unGlpbRsefQciOlbRyNqAbIEanIQPm5IcXPeX2b6eWE+zBuOV8hFjkotgTNoI1rcnypyzbm3RcDitI+X5pa3bS1LrS4OCudxDWlIa0ol+t/w1RK98xvgjZ8qTNvRNi3RUo4MKzjMgZTRp1QJ6BHRroEWNItLyXPS/UAOQZZBsINE4m4DDALUAfPxSn+wJM2rYA1NrwekiF2r5FLhLpgc8NbgLmAZ4FOwCbD9RqoP9BhkiYBKz3QJNBwOGJywcLtwdsV+Cxj1YSS5NgDsfzBEYExgp6Q+7B4YM2lO1gwqdVGyh2B2Ap5ypYXoFPIUyek71HYxKfDeBKgSQDPsIPQDRxHcPCncAYQBzlsKiaRfkty8BRALQC3AJcBQARwFCAgw3bqAiAE/M/lBwG5s8RnNv230X6n6rat65hAxsIGYXBNfdko2hjtlx (much longer)

Where is the error in the webpack configuration? (I paste the relevant part)

const fastGlob = require('fast-glob')
const path = require('path')
const webpack = require('webpack')

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

const isDev = process.env.NODE_ENV !== 'production'
const filename = isDev ? '[name]' : '[contenthash].[name]'

const entries = {
  css: [
    path.resolve(__dirname, 'src/_assets/styles/base.css'),
    path.resolve(__dirname, 'src/_assets/styles/fonts.css'),
    path.resolve(__dirname, 'src/_assets/styles/site.css'),
    path.resolve(__dirname, 'src/_assets/styles/atomic.css'),
    path.resolve(__dirname, 'src/_assets/styles/theme.css'),
  ],
}

module.exports = {
  mode: isDev ? 'development' : 'production',
  stats: {
    colors: true,
    preset: 'minimal',
  },
  performance: { hints: isDev ? 'warning' : false },
  devtool: isDev ? 'cheap-module-source-map' : 'source-map',
  entry: entries,
  output: {
    path: path.resolve(__dirname, '_build/_assets'),
    publicPath: '/_assets/',
  },
  plugins: [
    new CompressionPlugin({
      filename: '[path][base].gz',
      algorithm: 'gzip',
      test: /\.(js|css|html|svg)$/,
      threshold: 10240,
      minRatio: 0.8,
    }),
    new webpack.ids.HashedModuleIdsPlugin(),
    new ManifestPlugin(),
    new RemoveEmptyScriptsPlugin(),
    new MiniCssExtractPlugin({
      filename: `${filename}.css`,
    }),
  ],
  ...(!isDev && {
    optimization: {
      nodeEnv: 'production',
      mangleWasmImports: true,
      removeAvailableModules: true,
      minimizer: [
        new TerserPlugin(),
        new CssMinimizerPlugin({
          minimizerOptions: {
            preset: [
              'default',
              {
                discardComments: { removeAll: true },
                discardUnused: { removeAll: true },
              },
            ],
          },
        }),
      ],
    },
  }),
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [{ loader: 'babel-loader' }],
      },
      {
        test: /\.css$/i,
        exclude: /node_modules/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {},
          },
          {
            loader: 'css-loader',
            options: {
              sourceMap: isDev,
            },
          },
        ],
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        use: [{ loader: 'url-loader' }],
      },
    ],
  },
  resolve: {
    alias: {
      assets: path.resolve(__dirname, 'src/_assets'),
    },
  },
}

Solution

  • Because you're using url-loader for fonts. With webpack 5, you can use Asset Modules for loading fonts:

     {
            test: /\.(woff|woff2|eot|ttf|otf)$/i,
            type: 'asset/resource',
          },