it-swarm.com.de

Webpack "OTS-Parsing-Fehler" lädt Schriftarten

Meine Webpack-Konfiguration gibt an, dass Schriftarten mit url-loader geladen werden sollten. Wenn ich versuche, die Seite mit Chrome anzuzeigen, erhalte ich die folgende Fehlermeldung:

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

Die relevanten Teile meiner Konfiguration sehen so aus:

{
  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]"',
      }
    ],
  },
}

In Safari passiert das nicht und ich habe Firefox noch nicht ausprobiert.

In der Entwicklung versende ich Dateien über webpack-dev-server, in der Produktion werden sie auf die Festplatte geschrieben und in S3 kopiert. In beiden Fällen erhalte ich dasselbe Verhalten in Chrome.

Dies ist auch bei größeren Bildern der Fall (größer als die 10-KB-Grenze in der Image Loader-Konfiguration).

52
Will Madden

TL; DR Verwenden Sie absolute Pfade zu Ihren Assets (einschließlich Ihres vollständigen Hostnamens), indem Sie Ihren output.publicPath auf z. " http://example.com/assets/ ".

Das Problem

Das Problem ist die Art und Weise, wie URLs von Chrome gelöst werden, wenn sie aus einem dynamisch geladenen CSS-Blob analysiert werden.

Wenn Sie die Seite laden, lädt der Browser die JavaScript-Datei Ihres Webpack-Bundle-Eintrags, die (wenn Sie den style-loader verwenden) auch eine Base64-kodierte Kopie Ihres CSS enthält, die in die Seite geladen wird.

 Screenshot of embedded CSS in Chrome DevTools So sieht es in Chrome DevTools aus

Das ist in Ordnung für alle Bilder oder Schriftarten, die als Daten-URIs in das CSS kodiert werden (dh der Inhalt der Datei ist in das CSS eingebettet), aber für Assets, auf die URL verweist, muss der Browser dies tun Finden und holen Sie die Datei.

Standardmäßig verwendet file-loader (an das url-loader für große Dateien delegiert wird) relative URLs, um auf Assets zu verweisen - und das ist das Problem!

 Relative URLs generated by Webpack Dies sind die von file-loader standardmäßig generierten URLs - relative URLs

Wenn Sie relative URLs verwenden, löst Chrome diese relativ zur enthaltenen CSS-Datei auf. Normalerweise ist das in Ordnung, aber in diesem Fall befindet sich die enthaltende Datei unter blob://... und alle relativen URLs werden auf dieselbe Weise referenziert. Das Endergebnis ist, dass Chrome versucht, sie aus der übergeordneten HTML-Datei zu laden, und am Ende versucht, die HTML-Datei als Inhalt der Schriftart zu analysieren, was offensichtlich nicht funktioniert.

Die Lösung

Erzwingen Sie die Verwendung von absoluten Pfaden einschließlich des Protokolls ("http" oder "https") für den file-loader.

Ändern Sie Ihre Webpack-Konfiguration so, dass sie Folgendes enthält:

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

Die URLs, die es generiert, sehen nun so aus:

 enter image description here Absolute URLs!

Diese URLs werden von Chrome und allen anderen Browsern korrekt analysiert.

extract-text-webpack-plugin verwenden

Wenn Sie Ihr CSS in eine separate Datei extrahieren, wird dieses Problem nicht auftreten, da sich Ihr CSS in einer korrekten Datei befindet und die URLs korrekt aufgelöst werden.

130
Will Madden

Wenn Sie here von @mcortesi nicht ausgewählt haben, werden die CSS-Dateien ohne Verwendung von BLOB erstellt, wenn Sie die sourceMaps aus der Abfrage des css loader entfernen

13
Nadav SInai

Für mich war das Problem mein Regex-Ausdruck. Das Folgende hat den Trick gebracht, um Bootstrap zum Laufen zu bringen:

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

Wie bei @ user3006381 oben bestand mein Problem nicht nur aus relativen URLs, sondern das Webpack platzierte die Dateien so, als wären es Javascript-Dateien. Ihr Inhalt war alles im Wesentlichen:

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

im fonts-Verzeichnis statt der echten Schriftarten befanden sich die Font-Dateien im Ausgabeordner unter Hash-Codes. Um dies zu beheben, musste ich den Test für meinen URL-Loader (in meinem Fall meinen Bildprozessor) ändern, um den Schriftartenordner nicht zu laden. Ich musste output.publicPath in webpack.config.js immer noch als @ will-madden-Notizen in seiner hervorragenden Antwort festlegen.

4
Adam McCormick

Ich hatte das gleiche Problem, aber aus verschiedenen Gründen. 

Nachdem Will Maddens Lösung nicht geholfen hatte, versuchte ich jede alternative Lösung, die ich über die Intertubes finden konnte - auch ohne Erfolg. Ich erkundigte mich noch einmal, dass ich gerade eine der Schriftdateien geöffnet habe. Der ursprüngliche Inhalt der Datei wurde von Webpack irgendwie überschrieben, um Konfigurationsinformationen einzubeziehen, die wahrscheinlich aus dem vorherigen Basteln mit dem Dateilader stammen. Ich habe die beschädigten Dateien durch die Originale ersetzt, und voilà verschwanden die Fehler (sowohl für Chrome als auch für Firefox).

2
user3006381

Ich weiß, dass dies nicht die genaue Frage der OP beantwortet, aber ich bin mit dem gleichen Symptom, aber einer anderen Ursache hierher gekommen: 

Ich hatte die .scss-Dateien von Slick Slider wie folgt:

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

Bei näherer Betrachtung stellte sich heraus, dass die Schriftart versucht wurde, die Schriftart von einem ungültigen Ort (<Host>/assets/css/fonts/slick.woff) zu laden, wie sie vom Stylesheet aus referenziert wurde.

Am Ende habe ich einfach den /font/ in meinen assets/css/ kopiert und das Problem wurde für mich gelöst.

1
bpylearner

Da Sie url-loader verwenden:

Der URL-Loader funktioniert wie der File-Loader, kann jedoch eine DataURL zurückgeben, wenn die Datei kleiner als ein Byte-Limit ist.

Eine andere Lösung für dieses Problem wäre also, die Grenze so hoch zu setzen, dass die Zeichensatzdateien als DataURL enthalten sind, beispielsweise zu 100000, die mehr oder weniger 100Kb sind:

{
  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',
      },
    ],
  },
}

Berücksichtigen Sie immer, auf was die Begrenzungsnummer steht:

Byte-Limit für Inline-Dateien als Daten-URL

Auf diese Weise müssen Sie nicht die gesamte URL der Assets angeben. Was schwierig sein kann, wenn Webpack nicht nur von localhost aus antworten soll.

Nur eine letzte Überlegung, diese Konfiguration wird für die Produktion NICHT EMPFOHLEN. Dies ist nur für die Entwicklungsfreundlichkeit.

1
Roc

Wenn Sie Angular verwenden, müssen Sie dies überprüfen 

<base href="/"> 

das Tag kommt vor dem Stylesheet-Bundle. Ich habe meinen Code von hier aus geändert:

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

zu diesem:

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

und das Problem wurde behoben ... Danke an diesen Beitrag für das Öffnen meiner Augen.

0
Patrick Graham

Ab 2018 

use MiniCssExtractPlugin

für Webpack (> 4.0) wird dieses Problem gelöst. 

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

Die Verwendung von extract-text-webpack-plugin in der akzeptierten Antwort wird NICHT für Webpack 4.0+ empfohlen.

0
dsignr

Die beste und einfachste Methode besteht darin, die Schriftartdatei mit base64 zu codieren. Und verwenden Sie es in Schriftart. Wechseln Sie zum Codieren in den Ordner mit der Schriftartdatei und verwenden Sie den Befehl im Terminal:

base64 Roboto.ttf > basecodedtext.txt

Sie erhalten eine Ausgabedatei mit dem Namen basecodedtext.txt. Öffnen Sie diese Datei. Entfernen Sie alle Leerzeichen darin.

Kopieren Sie diesen Code und fügen Sie der CSS-Datei die folgende Zeile hinzu:

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

Dann können Sie den font-family: "font-name" in Ihrem CSS verwenden.

0
Jithin K Tom