web-dev-qa-db-fra.com

Webpack "Erreur d'analyse OTS" lors du chargement des polices

La configuration de mon WebPack spécifie que les polices doivent être chargées à l'aide de url-loader. Lorsque j'essaie d'afficher la page à l'aide de Chrome, l'erreur suivante apparaît:

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

Les parties pertinentes de ma configuration ressemblent à ceci:

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

Cela ne se produit pas dans Safari, et je n'ai pas essayé Firefox.

En développement, je sers des fichiers via webpack-dev-server; en production, ils sont écrits sur un disque et copiés vers S3; Dans les deux cas, j'obtiens le même comportement sous Chrome.

Cela se produit également avec des images plus grandes (supérieures à la limite de 10 Ko dans la configuration du chargeur d’images).

52
Will Madden

TL; DR Utilisez des chemins d'accès absolus vers vos actifs (y compris votre nom d'hôte complet) en définissant votre output.publicPath sur p. Ex. " http://example.com/assets/ ".

Le problème

Le problème est la manière dont Chrome corrige les URL lorsqu'elles sont analysées à partir d'un blob CSS chargé dynamiquement.

Lorsque vous chargez la page, le navigateur charge le fichier JavaScript de l'entrée de l'ensemble Webpack, qui (lorsque vous utilisez le style-loader) contient également une copie codée en Base64 de votre CSS, qui est chargée dans la page.

 Screenshot of embedded CSS in Chrome DevTools Voici à quoi cela ressemble dans Chrome DevTools

C’est bien pour toutes les images ou polices codées dans le CSS en tant que URI de données (le contenu du fichier est incorporé dans le CSS), mais pour les actifs référencés par URL, le navigateur trouver et récupérer le fichier.

Désormais, par défaut, le file-loader (auquel url-loader est délégué pour les fichiers volumineux) utilisera relative URL pour faire référence à des actifs - et c'est le problème! _

 Relative URLs generated by Webpack Il s'agit des URL générées par file-loader par défaut - URL relatives

Lorsque vous utilisez des URL relatives, Chrome les résoudra par rapport au fichier CSS contenant. D'habitude c'est bien, mais dans ce cas, le fichier contenant est à blob://... et toutes les URL relatives sont référencées de la même manière. Le résultat final est que Chrome tente de les charger à partir du fichier HTML parent et finit par essayer d'analyser le fichier HTML en tant que contenu de la police, ce qui ne fonctionnera évidemment pas.

La solution

Forcer le file-loader à utiliser des chemins absolus incluant le protocole ("http" ou "https").

Changez la configuration de votre webpack pour inclure quelque chose d’équivalent à:

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

Maintenant, les URL qu'il génère ressemblent à ceci:

 enter image description here _ {URL absolues!

Ces URL seront correctement analysées par Chrome et tous les autres navigateurs.

Utiliser extract-text-webpack-plugin

Il est à noter que si vous extrayez votre CSS dans un fichier séparé, vous ne rencontrerez pas ce problème car votre CSS sera dans un fichier approprié et les URL seront correctement résolues.

130
Will Madden

As aswerwer here by @mcortesi si vous supprimez les sourcesMaps de la requête du chargeur CSS, le CSS sera construit sans utilisation de blob et les URL de données seront analysées correctement

13
Nadav SInai

Pour moi, le problème était mon expression de regex. Les astuces suivantes ont permis de faire fonctionner bootstrap:

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

Comme avec @ user3006381 ci-dessus, mon problème ne concernait pas que des URL relatives, mais que Webpack plaçait les fichiers comme s'il s'agissait de fichiers javascript. Leur contenu était essentiellement:

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

dans le répertoire des polices à la place des polices réelles et les fichiers de polices étaient dans le dossier de sortie sous des codes de hachage. Pour résoudre ce problème, je devais changer le test sur mon chargeur d’URL (dans mon cas, mon processeur d’image) pour ne pas charger le dossier des polices. Il me restait encore à définir output.publicPath dans webpack.config.js comme @ will-madden notes dans son excellente réponse.

4
Adam McCormick

J'ai rencontré le même problème, mais pour des raisons différentes. 

Après que la solution de Will Madden n'ait pas aidé, j'ai essayé tous les correctifs alternatifs que je pouvais trouver via les Intertubes - également sans succès. En explorant plus avant, il m'est arrivé d’ouvrir un des fichiers de polices en question. Le contenu original du fichier avait en quelque sorte été écrasé par Webpack afin d'inclure une sorte d'informations de configuration, provenant probablement d'un bricolage précédent avec le chargeur de fichiers. J'ai remplacé les fichiers corrompus par les originaux et voilà, les erreurs ont disparu (pour Chrome et Firefox).

2
user3006381

Je sais que cela ne répond pas à la question exacte des OP mais je suis venu ici avec le même symptôme mais une cause différente: 

J'ai eu les fichiers .scss de Slick Slider inclus comme ceci:

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

En y regardant de plus près, il s’est avéré qu’il essayait de charger la police à partir d’un emplacement non valide (<Host>/assets/css/fonts/slick.woff), comme indiqué dans la feuille de style.

J'ai fini par copier simplement le /font/ dans mon assets/css/ et le problème a été résolu pour moi.

1
bpylearner

Depuis que vous utilisez url-loader :

Le chargeur d'URL fonctionne comme le chargeur de fichiers, mais peut renvoyer un DataURL si le fichier est inférieur à une limite d'octets.

Une autre solution à ce problème consisterait donc à augmenter suffisamment la limite pour que les fichiers de polices soient inclus en tant que DataURL, par exemple pour 100000 qui sont plus ou moins 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',
      },
    ],
  },
}

Toujours en tenant compte de ce que le nombre limite représente:

Limite d'octet pour les fichiers en ligne en tant qu'URL de données

De cette manière, vous n'avez pas besoin de spécifier l'URL complète des ressources. Ce qui peut être difficile lorsque vous voulez que Webpack ne réponde pas seulement de localhost.

Une dernière considération, cette configuration n’est PAS RECOMMANDÉE pour la production. Ceci est juste pour la facilité de développement.

1
Roc

Si vous utilisez Angular, vous devez vérifier que votre 

<base href="/"> 

tag vient avant votre paquet de feuille de style. J'ai changé mon code de ceci:

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

pour ça:

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

et le problème a été résolu . Merci à ce post pour ouvrir les yeux.

0
Patrick Graham

À partir de 2018, 

use MiniCssExtractPlugin

pour Webpack (> 4.0) résoudra ce problème. 

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

Utiliser extract-text-webpack-plugin dans la réponse acceptée est ET NON PAS recommandé pour Webpack 4.0+.

0
dsignr

La méthode la plus simple et la plus simple consiste à coder en base64 le fichier de polices. Et utilisez-le dans font-face. Pour le codage, allez dans le dossier contenant le fichier de polices et utilisez la commande dans le terminal:

base64 Roboto.ttf > basecodedtext.txt

Vous obtiendrez un fichier de sortie nommé basecodedtext.txt. Ouvrez ce fichier. Supprimer tous les espaces blancs dans cela.

Copiez ce code et ajoutez la ligne suivante au fichier CSS:

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

Ensuite, vous pouvez utiliser le font-family: "font-name" dans votre CSS.

0
Jithin K Tom