Webpack" OTS解析错误"加载字体

时间:2015-12-07 12:41:07

标签: css fonts webpack webpack-style-loader

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

13 个答案:

答案 0 :(得分:132)

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

问题

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

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

  

Screenshot of embedded CSS in Chrome DevTools   这就是Chrome DevTools中的样子

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

现在默认情况下,file-loaderurl-loader代表大型文件的代理人)将使用相对网址来引用资产 - 而问题!

  

Relative URLs generated by Webpack   这些是file-loader默认生成的网址 - 相对网址

当您使用相对网址时,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
  }
}

现在,它生成的网址如下所示:

  

enter image description here   绝对网址!

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

使用extract-text-webpack-plugin

值得注意的是,如果您将CSS解压缩到单独的文件中,则您不会遇到此问题,因为您的CSS将在正确的文件中,并且URL将得到正确解析。

答案 1 :(得分:13)

如@mcortesi所述here如果从css加载器查询中删除sourceMaps,将在不使用blob的情况下构建css,并且数据网址将被正确解析

答案 2 :(得分:12)

对我来说问题是我的正则表达式。下面做了引导工作的技巧:

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

答案 3 :(得分:4)

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

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

在fonts目录中而不是真实字体,字体文件位于哈希码下的输出文件夹中。要解决这个问题,我必须更改我的url-loader(在我的情况下是我的图像处理器)上的测试,以便不加载fonts文件夹。我仍然必须在webpack.config.js中将output.publicPath设置为@ will-madden注意到他的优秀答案。

答案 4 :(得分:2)

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

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

答案 5 :(得分:1)

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

我的Slick Slider的.scss文件包含如下:

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

仔细观察后发现,它试图从无效位置(<host>/assets/css/fonts/slick.woff)加载字体,就像从样式表中引用它一样。

我最后只是将/font/复制到我的assets/css/,问题就解决了。

答案 6 :(得分:1)

由于您使用url-loader

  

url-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

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

只需最后一个考虑因素,不建议将此配置用于生产。这只是为了发展的容易程度。

答案 7 :(得分:1)

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

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

答案 8 :(得分:0)

如果你正在使用Angular ,你需要检查以确保你的

<base href="/"> 

标签位于样式表包之前。我改变了我的代码:

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

到此:

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

问题得到解决。 感谢this post让我睁开眼睛。

答案 9 :(得分:0)

截至2018年

use MiniCssExtractPlugin

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

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

对于Webpack 4.0及更高版本,建议在接受的答案中使用extract-text-webpack-plugin

答案 10 :(得分:0)

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

答案 11 :(得分:0)

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

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

答案 12 :(得分:0)

在我的情况下,向lambda.js添加以下行{我的部署在AWS Lambda上}解决了该问题。

invoke()