Webpack“OTS 解析错误”加载字体

Posted

技术标签:

【中文标题】Webpack“OTS 解析错误”加载字体【英文标题】:Webpack "OTS parsing error" loading fonts 【发布时间】: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 限制)。

【问题讨论】:

如果您的字体文件为空或损坏,您可能会遇到此问题。所以检查你的字体文件的大小 【参考方案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'

【讨论】:

以上是关于Webpack“OTS 解析错误”加载字体的主要内容,如果未能解决你的问题,请参考以下文章

创建 React 应用程序:无法解码下载的字体 | OTS 解析错误

自托管 Google 的 Material Design 图标字体 - OTS 解析错误 - 无效的版本标签

Spring Boot - Font Awesome OTS 解析错误:转换失败

使用 webpack 2.2.0 时 CSS 字体加载器出错

React + Webpack 不解析文件加载器

Webpack 和导入加载程序错误“无法解析”