【问题标题】:Webpack "OTS parsing error" loading fontsWebpack“OTS 解析错误”加载字体
【发布时间】:2016-03-12 01:40:29
【问题描述】:

我的 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 限制)。

【问题讨论】:

  • 如果您的字体文件为空或损坏,您可能会遇到此问题。所以检查你的字体文件的大小

标签: css fonts webpack webpack-style-loader


【解决方案1】:

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

问题

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

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

这就是它在 Chrome DevTools 中的样子

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

现在默认情况下,file-loaderurl-loader 代表大文件)将使用 相对 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 将被正确解析。

【讨论】:

  • 哇,上周刚遇到这个问题。当您有许多部署或开发环境时会发生什么情况,手动更改 IP 不是很繁琐吗?
  • @benoror 对于不使用 style-loader 的部署来说这不是问题,因为 CSS 将从单独的 CSS 文件提供,Chrome 将能够正确解析资产 URL。所以你应该没问题,例如暂存、测试、QA 环境,您可以在其中将应用程序部署到某处并提取 CSS。但是,如果您有许多开发环境,则可能会出现问题。在我们的团队中,至少我们只在本地运行一次开发服务器,然后从那里开始工作。这并不理想,我不得不通知我的队友关于配置的更改,但这并没有真正影响我们。
  • 顺便说一句,刚刚看到一个可能与此特定问题有关的视频:youtu.be/MzVFrIAwwS8?t=870
  • 谢谢,我从您的回答中找到了我的 SPA 页面重新加载问题的原因。只需注释publicPath: '/', 也可以使用
  • 实际上这个解决方案并没有解决我的环境问题。有没有办法将整个 webpack 配置和 scss(相关块)上传到 CodePen?谢谢!
【解决方案2】:

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

{
    test: /\.(woff|ttf|eot|svg)(\?v=[a-z0-9]\.[a-z0-9]\.[a-z0-9])?$/,
    loader: 'url-loader?limit=100000'
},

【讨论】:

  • 从测试中删除 woff2 并且它有效... { test: /\.(png|jpe?g|gif|svg|woff|ttf|eot|ico)$/, loader: ' file?name=assets/[name].[hash].[ext]' },
【解决方案3】:

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

【讨论】:

  • 这个答案适用于我以及上面更受欢迎的答案。
  • 感谢您的回答。 Storybook 无法加载 Semantic UI 的字体时遇到问题,花了很多时间寻找解决方案。这解决了它。只需从 CSS 加载器中删除 ?sourceMap 即可。
  • 完美!删除源映射我没有任何问题,我的构建需要在不预先指定域的情况下工作
【解决方案4】:

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

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

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

【讨论】:

  • 这是我遇到的问题,但由于我使用的是easy-webpack(实际上可能是错误命名),我不确定如何从url加载器中排除字体文件夹..
  • @DarrenOster:我认为您必须使用他们的Object generators 将其指定为覆盖,以便您可以修改生成的配置。
【解决方案5】:

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

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

【讨论】:

    【解决方案6】:

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

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

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

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

    我最后只是简单地将/font/ 复制到我的assets/css/ 并且问题已为我解决。

    【讨论】:

      【解决方案7】:

      既然你用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 响应时,这可能会很困难。

      最后一个注意事项,不建议将此配置用于生产。这只是为了便于开发。

      【讨论】:

        【解决方案8】:

        最好和最简单的方法是对字体文件进行 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');
        }  
        

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

        【讨论】:

        • 比发布的其他解决方案更混乱,但如果您无法直接访问您的 webpack 配置(例如,如果使用 CRA),它会有效且有用
        【解决方案9】:

        我刚刚在 Font Awesome 上遇到了同样的问题。原来这是 由 FTP 问题引起。文件以文本 (ASCII) 形式上传 而不是二进制文件,它损坏了文件。我只是更改了我的 FTP 软件转二进制,重新上传字体文件,然后全部 工作。

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

        【讨论】:

          【解决方案10】:

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

          <base href="/"> 
          

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

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

          到这里:

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

          问题已解决。 感谢this post让我大开眼界。

          【讨论】:

            【解决方案11】:

            截至 2018 年,

            use MiniCssExtractPlugin

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

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

            在接受的答案中使用extract-text-webpack-plugin推荐用于 Webpack 4.0+。

            【讨论】:

              【解决方案12】:

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

              use: [
                {
                  loader: 'url-loader',
                  options: {
                    limit: 8192,
                  },
                },
              ],
              

              【讨论】:

                【解决方案13】:

                在我的情况下,将以下行添加到 lambda.js {我的部署是在 AWS Lambda 上} 解决了这个问题。

                 'font/opentype',
                 'font/sfnt',
                 'font/ttf',
                 'font/woff',
                 'font/woff2'
                

                【讨论】:

                  猜你喜欢
                  • 2017-09-08
                  • 2021-10-20
                  • 2019-02-11
                  • 2019-02-04
                  • 2019-06-12
                  • 2021-10-27
                  • 2019-06-10
                  • 2021-09-28
                  • 2016-07-28
                  相关资源
                  最近更新 更多