Подтвердить что ты не робот

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.

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

4b9b3361

Ответ 1

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

Проблема

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

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

Снимок экрана встроенного CSS в Chrome DevToolsЭто то, как он выглядит в Chrome DevTools

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

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

Относительные URL-адреса, созданные WebpackЭто URL-адреса, созданные по умолчанию file-loader - относительные 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-адреса, которые он создает, будут выглядеть следующим образом:

введите описание изображения здесьАбсолютные URL-адреса!

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

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

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

Ответ 2

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

Ответ 3

Для меня проблемой было выражение моего выражения. Ниже приведен трюк, чтобы заставить загрузчик работать:

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

Ответ 4

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

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

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

Ответ 5

У меня возникла одна и та же проблема, но по разным причинам.

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

Ответ 6

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

У меня были .scss файлы Slick Slider, включенные вот так:

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

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

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

Ответ 7

Так как вы используете 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.

Еще одно замечание: эта конфигурация НЕ РЕКОМЕНДУЕТСЯ для производства. Это просто для удобства разработки.

Ответ 8

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

<base href="/"> 
Тег

подходит к вашему списку стилей. Я переключил свой код:

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

:

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

и проблема была исправлена. Благодаря этому сообщению для открытия моих глаз.

Ответ 9

По состоянию на 2018 г.

use MiniCssExtractPlugin

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

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

Использование extract-text-webpack-plugin в принятом ответе НЕ рекомендуется для Webpack 4. 0+.

Ответ 10

Лучший и самый простой способ - закодировать файл шрифта в 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');
}  

Затем вы можете использовать font-family: "font-name" в вашем CSS.