Webpack "ошибка" ОЦ "разбор" загрузки шрифтов

моя конфигурация 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; в обоих случаях я получаю одинаковое поведение в Хром.

Это также происходит с большими изображениями (больше, чем ограничение 10kB в конфигурации загрузчика изображений).

9 ответов


TL; DR используйте абсолютные пути к своим активам (включая полное имя хоста), установив свой output.publicPath например "http://example.com/assets/".

проблема

проблема заключается в том, как URL-адреса разрешаются Chrome, когда они анализируются из динамически загруженного CSS blob.

когда вы загружаете страницу, браузер загружает файл JavaScript записи пакета Webpack, который (когда вы используете style-loader) также содержит кодированную Base64 копию вашего CSS, которая загружается на страницу.

Screenshot of embedded CSS in Chrome DevTools Вот как это выглядит в Chrome DevTools

это нормально для всех изображений или шрифтов, которые закодированы в CSS как URIs данных (т. е. содержимое файла встроено в CSS), но для активов, на которые ссылается URL-адресом браузер должен найти и принести файл.

теперь по умолчанию file-loader (который url-loader делегаты для больших файлов) будет использовать относительные URL-адреса для ссылки на активы - и вот в чем проблема!

Relative URLs generated by Webpack это URL-адреса, созданные file-loader по умолчанию-относительные URLs

при использовании относительных 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 Абсолютные URLs!

эти URL-адреса будут правильно проанализированы Chrome и любым другим браузером.

используя extract-text-webpack-plugin

стоит отметить, что если вы извлекаете CSS в отдельный файл, у вас не будет этой проблемы, потому что ваш CSS будет в правильном файле, и URL-адреса будут правильно разрешены.


Как asnwered здесь @mcortesi если вы удалите sourceMaps из запроса загрузчика css, css будет построен без использования blob, и URL-адреса данных будут проанализированы отлично


для меня проблема заключалась в моем выражении regex. Ниже сделал трюк, чтобы заставить bootstrap работать

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

Как и с @user3006381 выше, моя проблема заключалась не только в относительных URL-адресах, но и в том, что webpack размещал файлы, как будто они были файлами javascript. Их содержание было в основном:

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

в каталоге шрифтов вместо реальных шрифтов и файлов шрифтов были в выходной папке под хэш-кодами. Чтобы исправить это, мне пришлось изменить тест на моем url-загрузчике (в моем случае мой процессор изображений), чтобы не загружать папку шрифтов. Мне все еще нужно было установить выход.publicPath в webpack.конфиг.js as @will-madden отмечает в своем отличном ответе.


Я испытал ту же проблему, но по разным причинам.

после того, как решение Уилла Мэддена не помогло, я попробовал все альтернативные исправления, которые мог найти через Intertubes-также безрезультатно. Исследуя дальше, я просто случайно открыл один из файлов шрифтов, о которых идет речь. Исходное содержимое файла каким-то образом было перезаписано Webpack, чтобы включить какую-то информацию о конфигурации, вероятно, от предыдущей возни с загрузчиком файлов. Я заменил поврежденные файлы на оригиналы и вуаля, ошибки исчезли (как для Chrome, так и для Firefox).


Я знаю, что это не отвечает на точный вопрос OPs, но я пришел сюда с тем же симптомом, но по другой причине:

у меня был .scss файлы Slick Slider включены следующим образом:

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

при ближайшем рассмотрении оказалось, что он пытался загрузить шрифт из недопустимого места (<host>/assets/css/fonts/slick.woff), как это было указано в таблице стилей.

Я закончил тем, что просто скопировал /font/ мой assets/css/ и вопрос был решен для меня.


так как вы используете url-loader:

url-загрузчик работает как файл-загрузчик, но может возвращать 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.

только одно последнее соображение, эта конфигурация не рекомендуется для производства. Это просто для удобства развития.


если вы используете Angular вам нужно проверить, чтобы убедиться, что ваш

<base href="/"> 

- тег предшествует лист стиль Комплект. Я переключил свой код с этого:

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

для этого:

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

и проблема была решена. Спасибо этот пост за то, что открыл глаза.


по состоянию на 2018 год,

use MiniCssExtractPlugin

для Webpack (>4.0) решит эту проблему.

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

используя extract-text-webpack-plugin в принятом ответе есть не рекомендуется для Webpack 4.0+.