web-dev-qa-db-ja.com

フォントをロードするWebpack「OTS解析エラー」

私の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の制限を超える)。

55
Will Madden

TL; DRoutput.publicPathを設定して、アセットへの絶対パス(完全なホスト名を含む)を使用します。 " http://example.com/assets/ "。

問題

問題は、動的にロードされたCSS blobから解析されるときにChromeによってURLが解決される方法です。

ページをロードすると、ブラウザはWebpackバンドルエントリJavaScriptファイルをロードします(style-loaderを使用している場合)。これには、ページにロードされるCSSのBase64エンコードコピーも含まれます。

Screenshot of embedded CSS in Chrome DevTools これはChrome DevToolsでの表示です

データURIとしてCSSにエンコードされるすべての画像またはフォント(つまり、ファイルのコンテンツはCSSに埋め込まれます)では問題ありませんが、URL、ブラウザはファイルを見つけて取得する必要があります。

これで、デフォルトでfile-loaderurl-loaderが大きなファイルに委任する)は、アセットを参照するためにrelativeURLを使用します-そしてそれが問題です!

Relative URLs generated by Webpackこれらは、デフォルトで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は次のようになります。

enter image description here絶対URL!

これらのURLは、Chromeおよび他のすべてのブラウザーによって正しく解析されます。

extract-text-webpack-pluginを使用する

CSSを別のファイルに抽出する場合、CSSは適切なファイルにあり、URLは正しく解決されるため、この問題は発生しません。

133
Will Madden

Asnwered here by @mcortesi css loader queryからsourceMapsを削除すると、cssはblobを使用せずに構築され、データURLは適切に解析されます

13
Nadav SInai

私にとって問題は正規表現でした。以下は、bootstrapを機能させるためのトリックです。

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

上記の@ user3006381と同様、私の問題は相対URLだけではなく、webpackがファイルをjavascriptファイルであるかのように配置していたことです。その内容はすべて基本的に次のとおりです。

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

実際のフォントの代わりにフォントディレクトリにあり、フォントファイルはハッシュコードの下の出力フォルダーにありました。これを修正するには、url-loader(私の場合はイメージプロセッサ)のテストを変更して、fontsフォルダーを読み込まないようにする必要がありました。 @ pack-config.jsのoutput.publicPathを@ will-maddenの優れた回答のメモとして設定する必要がありました。

4
Adam McCormick

同じ問題が発生しましたが、理由は異なります。

Will Maddenのソリューションが役に立たなかった後、Intertubesで見つけることができるすべての代替修正を試してみましたが、やはり役に立ちませんでした。さらに調べてみると、問題のフォントファイルの1つを開いたことがあります。ファイルの元のコンテンツは、何らかの形でWebpackによって上書きされ、おそらく以前のファイルローダーの変更による何らかの構成情報が含まれていました。破損したファイルを元のファイルに置き換えると、エラーが消えました(ChromeとFirefoxの両方)。

2
user3006381

私はこれがOPの正確な質問に答えないことを知っていますが、同じ症状で別の原因でここに来ました:

Slick Sliderの.scssファイルは次のように含まれていました。

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

よく調べてみると、スタイルシートから参照されている方法で、無効な場所(<Host>/assets/css/fonts/slick.woff)からフォントをロードしようとしていたことがわかりました。

/font/assets/css/にコピーするだけで、問題は解決しました。

1
bpylearner

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がローカルホストから応答するだけでなく、難しい場合もあります。

最後に考慮すべき点は、この構成は実稼働環境にはお勧めできません。これは開発の容易さのためだけです。

1
Roc

Angularを使用している場合は、次のことを確認する必要があります。

<base href="/"> 

タグはスタイルシートバンドルの前にあります。私はこれからコードを切り替えました:

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

これに:

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

そして問題は修正されました。 この投稿 に感謝します。

0
Patrick Graham

2018年現在、

use MiniCssExtractPlugin

for Webpack(> 4.0)はこの問題を解決します。

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

受け入れられた答えでextract-text-webpack-pluginを使用することはではなくをWebpack 4.0+に推奨します。

0
dsignr

最良かつ最も簡単な方法は、フォントファイルを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"を使用できます。

0
Jithin K Tom