Webpack 5:文件加载器生成具有哈希名称的字体副本

Tog*_*oge 33 javascript css fonts webpack webpack-5

我不知道这里发生了什么事。我使用文件加载器加载应用程序的字体:

{
    test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
    use: [{
      loader: 'file-loader',
      options: {
        name: '[name].[ext]',
        outputPath: 'assets/fonts/',
        publicPath: '../fonts/'
      }
    }]
  },
Run Code Online (Sandbox Code Playgroud)

字体也是在我指定的结构中生成的:dist/assets/fonts。 outputPath: 'assets/fonts/'...它似乎工作正常。

但是: Webpack 还会将字体以哈希值作为名称打包到 /dist 下,并将 CSS 文件中的路径设置为这些文件。

@font-face{font-family:"PaulGrotesk";font-style:normal;font-weight:400;src:url(../../d9bc4e30281429c0cddd.eot);
Run Code Online (Sandbox Code Playgroud)

奇怪的字体文件

这里发生了什么?如何防止生成附加文件并将其用作路径?

我在用

  • 网页包:^5.47.1
  • webpack-cli: ^4.7.2

我的 webpack.config:

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {

  entry: './src/index.js',

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'assets/js/bundle_v1.0.0.js'
  },

  module: {

    rules: [

      {
        test: /\.js?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        include: path.join(__dirname, 'index'),
        options: {
          presets: ['@babel/preset-env']
        }
      },

      {
        test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'assets/fonts/',
            publicPath: '../fonts/'
          }
        }]
      },

      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader'
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
            }
          }
        ]
      },

      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },

    ]
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'node_modules'),
      /* https://webpack.js.org/configuration/resolve/ */
    },
  },
  plugins: [

    new MiniCssExtractPlugin({
      filename: 'assets/css/bundle_v1.0.0.css'
    }),

    new HtmlWebpackPlugin({
      inject: 'body',
      template: './src/index.html',
      filename: 'index.html',
    })

  ]

};
Run Code Online (Sandbox Code Playgroud)

Har*_*inn 55

我遇到了与 OP (@toge) 从 Webpack 4 迁移到 5 完全相同的问题。当我希望实现 @seanbun 发布的解决方案时,我遇到了以下新 Webpack 5 资产模块配置的设置,该设置允许我要file-loader正确生成之前的 svgs 和字体文件,而不会在根输出文件夹中重复:

{
    test: /\.(woff(2)?|ttf|eot)$/,
    type: 'asset/resource',
    generator: {
        filename: './fonts/[name][ext]',
    },
},
Run Code Online (Sandbox Code Playgroud)

这告诉 webpack 通过资产模块配置来处理它,但输出到自定义文件路径,类似于file-loader配置的工作方式。

这个设置也消除了我降级的需要,css-loader这是一个额外的好处

  • 是的,这对我有用! (2认同)
  • 这是获胜者,谢谢 (2认同)

sea*_*bun 11

显然,Webpack 5 有一项Asset Modules功能,允许人们使用资源文件(字体、图标等),而无需配置额外的加载器file-loaderurl-loader例如 等。它Asset Modules提供了四种类型来处理不同类型的资源。您可以在https://webpack.js.org/guides/asset-modules/找到更多详细信息。

因此,当您为字体文件添加以下规则时,这些文件实际上由Asset Modulesfile-loader.

    {
        test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'assets/fonts/',
            publicPath: '../fonts/'
          }
        }]
    }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们想使用我们自己的file-loader并禁用Asset Module. 我们可以将类型设置为“javascript/auto”。这将遵循您的路径设置并将字体文件保留在assets/fonts文件夹中。

    {
        test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
        **type: "javascript/auto",**
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'assets/fonts/',
            publicPath: '../fonts/'
          }
        }]
    }
Run Code Online (Sandbox Code Playgroud)

PS我正在使用css-loader 6.2.0并且有一个错误 - url.replace is not a function。我降级到css-loader 5.2.7解决问题。


小智 0

加载程序从最后到第一个应用。所以我的猜测是,将文件加载器放置在 css/sass 加载器下方可以解决该问题。

当 css 加载器需要时,字体可能不会以这种方式注册,因此会加载两次。