Webpack "Ots Parsing Error" Loading Fonts

Webpack 5 issues with fonts getting Failed to decode & OTS parsing error

tl;dr;

  use: {
loader: 'file-loader',

All constructions like the above have to be replaced with the type: asset/resource (the entire use block).

Here is an example of what I did to solve the exact same issue on the project I work on.

Before:

        {
test: /\.eot(\?v=\d+.\d+.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name].[ext]',
},
},
],
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff',
name: '[name].[ext]',
},
},
],
},
{
test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream',
name: '[name].[ext]',
},
},
],
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml',
name: '[name].[ext]',
},
},
],
},
{
test: /\.(jpe?g|png|gif|ico)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},

After:

        {
test: /\.(jpe?g|svg|png|gif|ico|eot|ttf|woff2?)(\?v=\d+\.\d+\.\d+)?$/i,
type: 'asset/resource',
},

The file-loader and url-loader have been deprecated and are conflicting with css-loader 6.x.

Consider removing the file-loader and url-loader and use the Asset Modules built into Webpack 5.

Another option might be to stick to the css-loader 5.x, but not recommended.

Webpack OTS parsing error loading fonts

TL;DR Use absolute paths to your assets (including your complete hostname) by setting your output.publicPath to e.g. "http://example.com/assets/".

The problem

The problem is the way that URLs are resolved by Chrome when they're parsed from a dynamically loaded CSS blob.

When you load the page, the browser loads your Webpack bundle entry JavaScript file, which (when you're using the style-loader) also contains a Base64 encoded copy of your CSS, which gets loaded into the page.

Screenshot of embedded CSS in Chrome DevTools
This is what it looks like in Chrome DevTools

That's fine for all the images or fonts which are encoded into the CSS as data URIs (i.e. the content of the file is embedded in the CSS), but for assets referenced by URL, the browser has to find and fetch the file.

Now by default the file-loader (which url-loader delegates to for large files) will use relative URLs to reference assets - and that's the problem!

Relative URLs generated by Webpack
These are the URLs generated by file-loader by default - relative URLs

When you use relative URLs, Chrome will resolve them relative to the containing CSS file. Ordinarily that's fine, but in this case the containing file is at blob://... and any relative URLs are referenced the same way. The end result is that Chrome attempts to load them from the parent HTML file, and ends up trying to parse the HTML file as the content of the font, which obviously won't work.

The Solution

Force the file-loader to use absolute paths including the protocol ("http" or "https").

Change your webpack config to include something equivalent to:

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

Now the URLs that it generates will look like this:

Sample Image
Absolute URLs!

These URLs will be correctly parsed by Chrome and every other browser.

Using extract-text-webpack-plugin

It's worth noting that if you're extracting your CSS to a separate file, you won't have this problem because your CSS will be in a proper file and URLs will be correctly resolved.

Webpack: OTS parsing error: invalid version tag while loading *.eot font

The solution here is pretty simple, actually: it's ~2017~ 2022, and Microsoft no longer supports eot, the svg format no longer exists, and ttf/otf are system fonts, not webfonts, don't use them when you also use WOFF (WOFF literally wraps them byte for byte, but with table-level compression). "Which format should I use for modern sites on browsers that are still supported by their manufacturers?" "You only need WOFF2" (with WOFF for ancient browser fallback).

The second part of the solution is "for the love of your users do not put your static assets inside of your JS app bundle", because the browser can't cache them that way, and everytime you update your font or your code, your users now have to redownload the entire bundle, wasting tons of your bandwidth, and their time. Keep those files hosted like normal static asset, using a normal static server (AWS, github pages, take your pick). There shouldn't really be a need to make webpack aware of the fact that your html file is going to be loading a .css file that is going to be loading a webfont. Your style code should simply be able to assume "that works".

Create React App: Failed to decode downloaded font | OTS parsing error

Files in the src folder are not directly served by your server. These files are bundled together with the build process first, and any files that are not imported will not end up in the build.

For these types of files, you can place them in the public folder, and the will end up in the build untouched and can be served by your server.

For more info see the CRA page on the public folder



Related Topics



Leave a reply



Submit