58

我的 webpack 配置指定应使用 加载字体url-loader,当我尝试使用 Chrome 查看页面时,出现以下错误:

OTS parsing error: invalid version tag
Failed to decode downloaded font: [My local URL]

我的配置的相关部分如下所示:

{
  module: {
    loaders: [
      // ...
      {
        test: /\.scss$/,
        loaders: ['style', 'css?sourceMap', 'autoprefixer', 'sass?sourceMap'],
      },
      {
        test: /images\/.*\.(png|jpg|svg|gif)$/,
        loader: 'url-loader?limit=10000&name="[name]-[hash].[ext]"',
      },
      {
        test: /fonts\/.*\.(woff|woff2|eot|ttf|svg)$/,
        loader: 'file-loader?name="[name]-[hash].[ext]"',
      }
    ],
  },
}

它不会在 Safari 中发生,我也没有尝试过 Firefox。

在开发中,我通过 提供文件webpack-dev-server,在生产中,它们被写入磁盘并复制到 S3;在这两种情况下,我在 Chrome 中都会得到相同的行为。

这也会发生在较大的图像上(大于图像加载器配置中的 10kB 限制)。

4

13 回答 13

142

TL;DRoutput.publicPath通过将您设置为例如“ http://example.com/assets/ ”来使用资产的绝对路径(包括您的完整主机名)。

问题

问题是当从动态加载的 CSS blob 解析 URL 时,Chrome 解析 URL 的方式。

当您加载页面时,浏览器会加载您的 Webpack 包条目 JavaScript 文件,该文件(当您使用 时style-loader)还包含您的 CSS 的 Base64 编码副本,该副本会被加载到页面中。

Chrome DevTools 中嵌入 CSS 的屏幕截图 这就是它在 Chrome DevTools 中的样子

这对于作为数据 URI 编码到 CSS 中的所有图像或字体都很好(即文件的内容嵌入在 CSS 中),但对于URL引用的资产,浏览器必须查找并获取文件。

现在默认情况下file-loaderurl-loader代表大文件)将使用相对URL 来引用资产 -这就是问题所在!

Webpack 生成的相对 URL 这些是file-loader默认生成的 URL - 相对 URL

当您使用相对 URL 时,Chrome 会相对于包含的 CSS 文件解析它们。通常这很好,但在这种情况下,包含文件位于blob://...并且任何相对 URL 都以相同的方式引用。最终结果是 Chrome 尝试从父 HTML 文件加载它们,并最终尝试将 HTML 文件解析为字体的内容,这显然不起作用。

解决方案

强制file-loader使用包含协议(“http”或“https”)的绝对路径。

更改您的 webpack 配置以包含与以下内容等效的内容:

{
  output: {
    publicPath: "http://localhost:8080/", // Development Server
    // publicPath: "http://example.com/", // Production Server
  }
}

现在它生成的 URL 将如下所示:

在此处输入图像描述 绝对网址!

Chrome 和其他所有浏览器都会正确解析这些 URL。

使用extract-text-webpack-plugin

值得注意的是,如果您将 CSS 提取到单独的文件中,则不会出现此问题,因为您的 CSS 将位于正确的文件中并且 URL 将被正确解析。

于 2015-12-07T12:41:07.350 回答
15

对我来说,问题是我的正则表达式。下面的技巧可以让引导程序正常工作:

{
    test: /\.(woff|ttf|eot|svg)(\?v=[a-z0-9]\.[a-z0-9]\.[a-z0-9])?$/,
    loader: 'url-loader?limit=100000'
},
于 2016-11-06T02:05:26.833 回答
13

正如@mcortesi所说,如果您从 css 加载器查询中删除 sourceMaps,则 css 将在不使用 blob 的情况下构建,并且数据 url 将被很好地解析

于 2015-12-22T15:46:29.630 回答
5

与上面的 @user3006381 一样,我的问题不仅仅是相对 URL,而是 webpack 将文件放置为 javascript 文件。他们的内容基本上都是:

module.exports = __webpack_public_path__ + "7410dd7fd1616d9a61625679285ff5d4.eot";

在字体目录而不是真正的字体中,字体文件位于哈希码下的输出文件夹中。为了解决这个问题,我不得不更改我的 url-loader(在我的情况下是我的图像处理器)上的测试,以不加载字体文件夹。我仍然必须在 webpack.config.js 中设置 output.publicPath ,正如@will-madden 在他的出色回答中所指出的那样。

于 2016-04-08T22:49:41.427 回答
2

我遇到了同样的问题,但原因不同。

在 Will Madden 的解决方案没有帮助之后,我尝试了所有可以通过 Intertubes 找到的替代解决方案 - 也无济于事。进一步探索,我碰巧打开了一个有问题的字体文件。该文件的原始内容不知何故被 Webpack 覆盖以包含某种配置信息,可能来自之前对文件加载器的修补。我用原始文件替换了损坏的文件,瞧,错误消失了(对于 Chrome 和 Firefox)。

于 2016-03-28T02:10:14.703 回答
1

我知道这并不能回答 OP 的确切问题,但我来到这里的症状相同,但原因不同:

我有 Slick Slider 的 .scss 文件,如下所示:

@import "../../../node_modules/slick-carousel/slick/slick.scss";

仔细检查后发现,它试图从无效位置 ( <host>/assets/css/fonts/slick.woff) 加载字体,这是从样式表中引用它的方式。

我最终只是简单地将其复制/font/到我assets/css/的,问题就为我解决了。

于 2017-07-14T12:09:17.600 回答
1

由于您使用url-loader

url-loader 的工作方式与 file-loader 类似,但如果文件小于字节限制,则可以返回 DataURL。

因此,此问题的另一个解决方案是将限制设置得足够高,以便将字体文件包含为 DataURL,例如,100000或多或少100Kb

{
  module: {
    loaders: [
      // ...
      {
        test: /\.scss$/,
        loaders: ['style', 'css?sourceMap', 'autoprefixer', 'sass?sourceMap'],
      },
      {
        test: /images\/.*\.(png|jpg|svg|gif)$/,
        loader: 'url-loader?limit=10000&name="[name]-[hash].[ext]"',
      },
      {
        test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
        use: 'url-loader?limit=100000&mimetype=application/font-woff',
      },
      {
        test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
        use: 'url-loader?limit=100000&mimetype=application/font-woff',
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        use: 'url-loader?limit=100000&mimetype=application/octet-stream',
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        use: 'file-loader',
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: 'url-loader?limit=100000&mimetype=image/svg+xml',
      },
    ],
  },
}

始终考虑限制数字代表的含义:

作为数据 URL 的内联文件的字节限制

这样您就不需要指定资产的整个 URL。当您希望 Webpack 不仅从 localhost 响应时,这可能会很困难。

只是最后一个考虑因素,不建议将此配置用于生产。这只是为了便于开发。

于 2018-01-04T11:03:19.223 回答
1

最好和最简单的方法是对字体文件进行 base64 编码。并在字体中使用它。对于编码,转到具有字体文件的文件夹并在终端中使用命令:

base64 Roboto.ttf > basecodedtext.txt

您将获得一个名为 basecodedtext.txt 的输出文件。打开那个文件。删除其中的任何空格。

复制该代码并将以下行添加到 CSS 文件中:

@font-face {
  font-family: "font-name";
  src: url(data:application/x-font-woff;charset=utf-8;base64,<<paste your code here>>) format('woff');
}  

然后你可以font-family: "font-name"在你的CSS中使用。

于 2019-05-15T13:50:44.920 回答
1

我刚刚遇到了与 Font Awesome 相同的问题。原来这是由FTP问题引起的。该文件以文本 (ASCII) 而不是二进制文件的形式上传,这会损坏文件。我只是将我的 FTP 软件更改为二进制文件,重新上传字体文件,然后一切正常。

https://css-tricks.com/forums/topic/custom-fonts-returns-failed-to-decode-downloaded-font/ 这最终帮助了我我在 FTP 将文件作为文本传输时遇到了同样的问题

于 2020-05-03T03:12:52.993 回答
0

如果您使用的是 Angular,则需要检查以确保您的

<base href="/"> 

标签位于您的样式表包之前。我从这里切换了我的代码:

 <script src="~/bundles/style.bundle.js"></script>
 <base href="~/" />

对此:

 <base href="~/" />
 <script src="~/bundles/style.bundle.js"></script>

问题得到解决。感谢这篇文章让我大开眼界。

于 2017-03-13T15:38:08.477 回答
0

截至 2018 年,

use MiniCssExtractPlugin

对于 Webpack(> 4.0) 将解决这个问题。

https://github.com/webpack-contrib/mini-css-extract-plugin

对于 Webpack 4.0+,extract-text-webpack-plugin建议在接受的答案中使用。

于 2018-08-02T10:07:42.650 回答
0

limit是我的代码的线索,但我必须像这样指定它:

use: [
  {
    loader: 'url-loader',
    options: {
      limit: 8192,
    },
  },
],
于 2020-01-30T09:13:42.117 回答
0

在我的情况下,将以下行添加到 lambda.js {my deploy is on AWS Lambda} 解决了这个问题。

 'font/opentype',
 'font/sfnt',
 'font/ttf',
 'font/woff',
 'font/woff2'
于 2020-02-06T12:24:02.423 回答