Load fonts with Webpack and font-face
Solution 1
After trying a lot of stuff the next loader made the work. Instead of file-loader, I used url-loader . You need url-loader installed.
{ test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000' }
Solution 2
With webpack 4 this is what solved the issue for me (diff):
{
test: /\.svg$/,
use: ['svg-loader']
},
{
test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/,
use: ['file-loader']
}
{ test: /\.(png|woff|woff2|eot|ttf|svg)$/, use: ['url-loader?limit=100000'] }
I had to remove svg-loader
and file-loader
in favor of url-loader
My app.scss
file looks like this:
$fa-font-path: '~font-awesome/fonts';
@import '~font-awesome/scss/font-awesome';
$icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/";
@import '~bootstrap-sass/assets/stylesheets/bootstrap';
And in my app.js
I import the app.scss
:
import './app.scss';
So, after the changes, my webpack config looks like this:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpackConfig = require('./webpack.config');
module.exports = {
entry: {
app: './client/app/app.js'
},
devtool: 'source-map',
mode: 'development',
plugins: [
new HtmlWebpackPlugin({
title: 'Development',
template: 'client/index.html'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
},
{ test: /\.(png|woff|woff2|eot|ttf|svg)$/, use: ['url-loader?limit=100000'] }
]
}
};
Solution 3
According to Webpack's Documentation, you need to update your webpack.config.js
to handle font files. See the last loader i.e.
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
}
We will include all kinds of file format for webpack. The final webpack.config.js
file will look something like this.
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
};
Then, you will have to import the fonts to your entry file. In this case ./src/index.js
. With the loader configured and fonts in place, you can incorporate them via an @font-face
declaration. The local url(...)
directive will be picked up by webpack just as it was with the image.
Solution 4
I was having the same problem. In my case, the 'src' of the font became src="[object Module]".
Disabling esModule on webpack was the solution:
{
test: /\.(png|jpe?g|gif|svg|ttf|woff|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[contenthash].[ext]',
outputPath: 'static/img',
esModule: false // <- here
}
}
]
}
More info on it here.
Solution 5
I got some issues with my font faces when I updated from Webpack 4.x.x to latest 5.52.1
The content of my exported .woff / .woff2 / .ttf ...
looked something like this:
export default __webpack_public_path__ + "glyphicons-halflings-regular.woff2";
The solution for me was to simply remove my previous file-loader
entirely. It seems the files were being processed multiple times, which caused the error.
Before:
...
module: {
rules: [
{
test: /\.(png|jpg|gif|ico|woff|woff2|ttf|svg|eot)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
useRelativePath: true
}
}
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: { url: false }
}
]
}
]
}
...
After:
...
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: { url: false }
}
]
}
]
}
...
For more information: https://webpack.js.org/guides/asset-modules/
Ebenizer Pinedo
Updated on July 17, 2022Comments
-
Ebenizer Pinedo almost 2 years
I'm trying to load a font in my CSS file using
@font-face
but the font never loads. This is my directory structure.Then in
webpack.config.js
I have the loader to get fonts.var path = require('path'); var webpack = require('webpack'); module.exports = { devtool: 'eval', entry: [ "./index.js" ], output: { path: __dirname+"/build", filename: "main.js" }, plugins: [ new webpack.NoErrorsPlugin(), new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ], resolve: { extensions: ['', '.js', '.jsx'] }, module: { loaders: [ { test: /\.js$/, loaders: ['react-hot', 'babel-loader'], exclude: /node_modules/ }, { test: /\.jsx?$/, loaders: ['react-hot', 'babel-loader'], exclude: /node_modules/ }, { test: /\.svg$/, loader: "raw" }, { test: /\.css$/, loader: "style-loader!css-loader" }, { test: /\.(eot|svg|ttf|woff|woff2)$/, loader: 'file?name=src/css/[name].[ext]'} ] } };
Inside my CSS file I have this:
@font-face { font-family: 'Darkenstone'; src: url('./Darkenstone.woff') format('woff'); } body { background-color: green; font-size: 24px; font-family: 'Darkenstone'; }
Finally, I'm calling my CSS file in my
index.js
with:import './src/css/master.css';
Everything works but de font never loads.
-
Ebenizer Pinedo over 6 yearsIn my output path (webpack.config.js) I have "build", so with that loader I get another build folder inside build. Something like build/build.
-
Esben over 6 yearsOh okay, I have removed build/ from the loader. That should put the font in the root of your build folder, yeah? Then add
publicPath: 'build/'
tooutput
. You can open index.html and find the style tag and see what the url of the font is, it should bebuild/Darkenstone.woff
-
Ebenizer Pinedo over 6 yearsI get this error in mi console: 95% emitError: EACCES: permission denied, open '/Darkenstone.woff' at Error (native) I've removed Path: __dirname+"/build" to add publicPath, is this ok?
-
Esben over 6 yearsNo, you should have both
path: __dirname + '/build'
andpublicPath: 'build/'
. Please add the contents ofindex.html
to your question. -
Ebenizer Pinedo over 6 yearsActually I've resolved my problem with a different loader, it's in the answer below, but thank you so much for your help ;)
-
Eru almost 6 yearsInline Base64 is not a good idea, as outer resources can be cached more efficiently. And as an addition it interprets 30% slower on Mobile devices which is a huge difference.
-
mykeels almost 4 years
BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix
So, it should be: ``` {test: /\.(eot|svg|ttf|woff|woff2)$/, loader: 'file-loader?name=[name].[ext]'} ``` -
Dex over 3 yearsthat did the trick for me, but using url-loader, not file-loader. I'm using webpack 4.43.0
-
Narges Moemenyan over 3 yearsyou saved my life after a couple of hours struggling with this error!
-
Julian Kleine over 3 yearsThis answer doesn't provide a solution that actually tackles the issue. Just suggesting to update a version is all right, but possibly not the issue here, as you also add a long config, please give an explanation as well and what is possibly different in this config.
-
Sfili_81 almost 3 yearsPlease only link answer isn't useful even if it answer the question. Please add the relevant part of the link into your answer
-
trusktr over 2 yearsThis is the correct answer as of Webpack 5. Anything else involving a loader is outdated. file-loader is deprecated: v4.webpack.js.org/loaders/file-loader
-
trusktr over 2 yearsThis is no longer the answer if you're using Webpack 5 and up. See @arbob's answer that includes "asset/resource" in it.
-
rgoldfinger over 2 yearsThis saved me when trying to add custom font loading to a Next.js project. Thank you!
-
Angel Auñón about 2 yearsWorked perfectly
-
ghosh almost 2 yearsUpdate: Compiling RuleSet failed: Query arguments on 'loader' has been removed in favor of the 'options' property. So that just needs a change