使用 Webpack 和 font-face 加载字体

Posted

技术标签:

【中文标题】使用 Webpack 和 font-face 加载字体【英文标题】:Load fonts with Webpack and font-face 【发布时间】:2018-01-11 09:28:03 【问题描述】:

我正在尝试使用 @font-face 在我的 CSS 文件中加载字体,但字体永远不会加载。这是我的目录结构。

然后在webpack.config.js 我有加载器来获取字体。

var path = require('path');
var webpack = require('webpack');

module.exports = 
  devtool: 'eval',
  entry: [
    "./index.js"
  ],
  output: 
    path: __dirname+"/build",
    filename: "main.js"
  ,
  plugins: [
    new webpack.NoErrorsPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],
  resolve: 
    extensions: ['', '.js', '.jsx']
  ,
  module: 
      loaders: [
           test: /\.js$/, loaders: ['react-hot', 'babel-loader'], exclude: /node_modules/ ,
           test: /\.jsx?$/, loaders: ['react-hot', 'babel-loader'], exclude: /node_modules/ ,
           test: /\.svg$/, loader: "raw" ,
           test: /\.css$/, loader: "style-loader!css-loader" ,
           test: /\.(eot|svg|ttf|woff|woff2)$/, loader: 'file?name=src/css/[name].[ext]'

      ]
  
;

在我的 CSS 文件中,我有这个:

@font-face 
  font-family: 'Darkenstone';
  src: url('./Darkenstone.woff') format('woff');


body 
  background-color: green;
  font-size: 24px;
  font-family: 'Darkenstone';

最后,我在 index.js 中调用我的 CSS 文件:

import './src/css/master.css';

一切正常,但从不加载字体。

【问题讨论】:

【参考方案1】:

在尝试了很多东西之后,下一个加载器完成了工作。我使用了 url-loader 而不是文件加载器。您需要安装 url-loader。

 test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000' 

【讨论】:

内联 Base64 不是一个好主意,因为可以更有效地缓存外部资源。此外,它在移动设备上的解释速度要慢 30%,这是一个巨大的差异。 在解决这个错误几个小时后,你救了我的命! 如果您使用的是 Webpack 5 及更高版本,这不再是答案。请参阅@arbob 的答案,其中包含“资产/资源”。【参考方案2】:

使用 webpack 4 这就是为我解决问题的方法(差异):

       
         test: /\.svg$/,
         use: ['svg-loader']
       ,
       
         test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/,
         use: ['file-loader']
       
        test: /\.(png|woff|woff2|eot|ttf|svg)$/, use: ['url-loader?limit=100000'] 

我不得不删除 svg-loaderfile-loader 以支持 url-loader

我的app.scss 文件如下所示:

$fa-font-path: '~font-awesome/fonts';
@import '~font-awesome/scss/font-awesome';

$icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/";
@import '~bootstrap-sass/assets/stylesheets/bootstrap';

在我的app.js 中,我导入了app.scss

import './app.scss';

因此,更改后,我的 webpack 配置如下所示:

const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');
const webpackConfig = require('./webpack.config');

module.exports = 
  entry: 
    app: './client/app/app.js'
  ,
  devtool: 'source-map',
  mode: 'development',
  plugins: [
    new HtmlWebpackPlugin(
      title: 'Development',
      template: 'client/index.html'
    )
  ],
  output: 
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  ,
  module: 
    rules: [
      
        test: /\.(sa|sc|c)ss$/,
        use: [
          'style-loader',
          'css-loader',
          'sass-loader',
        ],
      ,
       test: /\.(png|woff|woff2|eot|ttf|svg)$/, use: ['url-loader?limit=100000'] 
    ]
  
;

【讨论】:

【参考方案3】:

根据Webpack's Documentation,您需要更新您的webpack.config.js 以处理字体文件。查看最后一个加载程序,即


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

我们将为 webpack 包含各种文件格式。最终的webpack.config.js 文件将如下所示。

const path = require('path');
module.exports = 
       entry: './src/index.js',
       output: 
         filename: 'bundle.js',
         path: path.resolve(__dirname, 'dist'),
       ,
       module: 
         rules: [
           
             test: /\.css$/i,
             use: ['style-loader', 'css-loader'],
           ,
           
             test: /\.(png|svg|jpg|jpeg|gif)$/i,
             type: 'asset/resource',
           ,
          
            test: /\.(woff|woff2|eot|ttf|otf)$/i,
            type: 'asset/resource',
          ,
         ],
       ,
     ;

然后,您必须将字体导入您的条目文件。在这种情况下./src/index.js。配置好加载器并设置好字体后,您可以通过@font-face 声明合并它们。本地 url(...) 指令将被 webpack 拾取,就像它处理图像一样。

【讨论】:

请仅链接答案即使它回答了问题也没有用。请将链接的相关部分添加到您的答案中 这是从 Webpack 5 开始的正确答案。任何其他涉及加载程序的内容都已过时。文件加载器已弃用:v4.webpack.js.org/loaders/file-loader【参考方案4】:

我遇到了同样的问题。 在我的例子中,字体的“src”变成了 src="[object Module]"。

在 webpack 上禁用 esModule 是解决方案:


  test: /\.(png|jpe?g|gif|svg|ttf|woff|otf)$/,
  use: [
    
      loader: 'file-loader',
      options: 
        name: '[name].[contenthash].[ext]',
        outputPath: 'static/img',
        esModule: false // <- here
      
    
  ]

更多信息here。

【讨论】:

这对我有用,但使用的是 url-loader,而不是 file-loader。我正在使用 webpack 4.43.0【参考方案5】:

尝试将您的加载器更改为

test: /\.(eot|svg|ttf|woff|woff2)$/, loader: 'file?name=[name].[ext]'

并将publicPath: 'build/' 添加到您的output 密钥中。

【讨论】:

在我的输出路径(webpack.config.js)中我有“build”,所以使用那个加载器我在 build 中得到了另一个 build 文件夹。类似构建/构建。 哦,好吧,我已经从加载器中删除了 build/。那应该将字体放在构建文件夹的根目录中,是吗?然后将publicPath: 'build/' 添加到output。可以打开index.html找到style标签,看看字体的url是什么,应该是build/Darkenstone.woff 我在 mi 控制台中收到此错误:95% emitError: EACCES: permission denied, open '/Darkenstone.woff' at Error (native) I've remove Path: __dirname+"/build" to add publicPath,这样可以吗? 不,您应该同时拥有path: __dirname + '/build'publicPath: 'build/'。请将index.html的内容添加到您的问题中。 实际上我已经用不同的加载器解决了我的问题,它在下面的答案中,但非常感谢你的帮助;)【参考方案6】:

当我从 Webpack 4.x.x 更新到最新的 5.52.1 时,我的字体出现了一些问题

我导出的.woff / .woff2 / .ttf ... 的内容如下所示:

export default __webpack_public_path__ + "glyphicons-halflings-regular.woff2";

我的解决方案是完全删除我以前的file-loader。文件似乎被多次处理,导致错误。

之前:

...
module: 
    rules: [
        
            test: /\.(png|jpg|gif|ico|woff|woff2|ttf|svg|eot)$/,
            use: 
                loader: 'file-loader',
                options:  
                    name: '[name].[ext]',
                    useRelativePath: true
                
            
        ,
        
            test: /\.css$/,
            use: [
                MiniCssExtractPlugin.loader,
                
                    loader: 'css-loader',
                    options:  url: false 
                
            ]
        
    ]

...

之后:

...
module: 
    rules: [
        
            test: /\.css$/,
            use: [
                MiniCssExtractPlugin.loader,
                
                    loader: 'css-loader',
                    options:  url: false 
                
            ]
        
    ]

...

欲了解更多信息:https://webpack.js.org/guides/asset-modules/

【讨论】:

这在尝试将自定义字体加载添加到 Next.js 项目时救了我。谢谢!【参考方案7】:

我将 webpack 版本从 4.20.2 升级到 4.42.0,我的代码开始加载我想要的字体。

const URL_LOADER_LIMIT = 8192

module.exports = () => (
  module: 
    rules: [
      
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          
            loader: 'url-loader',
            options: 
              name: '[name].[ext]',
              outputPath: 'fonts/',
              limit: URL_LOADER_LIMIT
            
          
        ]
      ,
      
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        use: [
          
            loader: 'url-loader',
            options: 
              name: '[name].[ext]',
              outputPath: 'fonts/',
              limit: URL_LOADER_LIMIT,
              mimetype: 'application/font-woff'
            
          
        ]
      ,
      
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          
            loader: 'url-loader',
            options: 
              name: '[name].[ext]',
              outputPath: 'fonts/',
              limit: URL_LOADER_LIMIT,
              mimetype: 'application/octet-stream'
            
          
        ]
      ,
      
        test: /\.mp3$/,
        use: ['file-loader']
      ,
      
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: [
          
            loader: 'url-loader',
            options: 
              outputPath: 'images/',
              name: '[name].[ext]',
              limit: URL_LOADER_LIMIT,
              mimetype: 'image/svg+xml'
            
          
        ]
      ,
      
        test: /\.(png|jpg|gif)$/,
        use: [
          
            loader: 'url-loader',
            options: 
              outputPath: 'images/',
              name: '[name].[ext]',
              limit: URL_LOADER_LIMIT
            
          
        ]
      
    ]
  
)

【讨论】:

这个答案没有提供真正解决问题的解决方案。只是建议更新一个版本是可以的,但可能不是这里的问题,因为你还添加了一个长配置,请解释一下这个配置可能有什么不同。

以上是关于使用 Webpack 和 font-face 加载字体的主要内容,如果未能解决你的问题,请参考以下文章

Webpack @font-face 相对路径问题

Webpack sass-loader,css-loader 在 scss 文件中与 font-face 中断

如何在 webpack 的 css-loader 中使用@font-face?

Webpack mini-css-extract-plugin @font-face url 解析问题

无法使用 @font-face 加载字体

Firefox 无法加载@font-face? [复制]