Webpack 5 with SASS loader and MiniCSSExtractPlugin doesn't move fonts - css

I'm fairly new to Webpack 5, while my build is almost working, my fonts are not being transfered to my /dist folder. I include the fonts in my main.scss file (see below)
Am I missing something with my current config?
folder structure
- src
- assets
- sass
- fonts
src/assets/sass/main.scss
#font-face {
font-family: 'P22MackinacMedium';
src: url('../fonts/p22-mackinac-medium.eot');
src: url('../fonts/p22-mackinac-medium.eot?#iefix') format('embedded-opentype'),
url('../fonts/p22-mackinac-medium.woff2') format('woff2'),
url('../fonts/p22-mackinac-medium.woff') format('woff'),
url('../fonts/p22-mackinac-medium.ttf') format('truetype'),
url('../fonts/p22-mackinac-medium.svg#youworkforthem') format('svg');
font-weight: normal;
font-style: normal;
}
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: 'development',
entry: './src/index.js',
plugins: [new MiniCssExtractPlugin(), new HtmlWebpackPlugin({
template: 'src/index.html'
})],
output: {
filename: '[name]-[contenthash].js',
chunkFilename: '[name]-[chunkhash].js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
}
},
module: {
rules: [
{
test: /\.css$/,
use: [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
"css-loader",
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader, {
loader: 'css-loader',
options: { url: false }
},
'sass-loader'
],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
devServer: {
static: './dist',
},
};

As far as I can see this should be working out of the box, like you wrote it, since webpack 5 is using new Assets management. But, since it is not working for you, you can still try to use url-loader. Like this:
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
use: {
loader: 'url-loader',
},
},
Or you could try 'asset/inline' before installing url loader.

Related

Webpack configuration for css #font-face? Current setup changes url() to a very long string

I am bundling and minimizing my css's with webpack 5.4.0
This goes ok, except for the fonts.css file, which originally is simply this:
#font-face {
font-family: 'Kulim Park';
font-style: normal;
font-weight: 400;
src: url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.eot');
src: local(''), url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.eot?#iefix') format('embedded-opentype'),
url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.woff2') format('woff2'),
url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.woff') format('woff'),
url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.ttf') format('truetype'),
url('../fonts/kulim-park-v2-latin/kulim-park-v2-latin-regular.svg#KulimPark') format('svg');
}
#font-face {
font-family: 'Staatliches';
font-style: normal;
font-weight: 400;
src: url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.eot');
src: local('Staatliches Regular'), local('Staatliches-Regular'),
url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.eot?#iefix') format('embedded-opentype'),
url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.woff2') format('woff2'),
url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.woff') format('woff'),
url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.ttf') format('truetype'),
url('../fonts/staatliches-v5-latin/staatliches-v5-latin-regular.svg#Staatliches') format('svg');
}
The final bundle is kilometric, the url() is transformed into this (in development, in production with the "correct" part minimized)
#font-face {
font-family: 'Kulim Park';
font-style: normal;
font-weight: 400;
src: url(data:application/vnd.ms-fontobject;base64,kEoAAIxJAAACAAIABAAAAAAAAAAAAAAAAAABAJABAAAAAExQJwAAgEsAAAAAAAAAAAAAAJMAACAAAAAA3HSrPQAAAAAAAAAAAAAAAAAAAAAAABQASwB1AGwAaQBtACAAUABhAHIAawAAAA4AUgBlAGcAdQBsAGEAcgAAAEYAVgBlAHIAcwBpAG8AbgAgADEALgAwADAAMAA7ACAAdAB0AGYAYQB1AHQAbwBoAGkAbgB0ACAAKAB2ADEALgA4AC4AMwApAAAAJABLAHUAbABpAG0AIABQAGEAcgBrACAAUgBlAGcAdQBsAGEAcgAAAAAAQlNHUAAAAAAAAAAAAAAAAAAAAAADAIcAADulAEPpADWAEs3pishg2FfJaEtyb3BxIlU6Yiwvlj0Tx7en4cGPvQIuQaxIgG1JJSQGliGIUdk3GlqcHgcNRFx0xGTawgT7oKcSv0LGOIBgp/67SUixSTBAOLp3AixitjCZniGkUSZ0ZK7pGtw8aIkw+KDQEo11ZXwXGrQSlXZVee5mStSqmu0ptfSoJXlHVLUgwdIhShAkIY9nWdD6aQdYMm1k/8k06Saw34XfjmSk89dni9ec76k0/XN1AgIGqC//IeABHG5Vm/a7wNALJha++urEAA0pw9wGdf/Slb0Ol9qC5x9G1lQw2NpHmEGnTX3FnTmawqPNHEvOZ7CDF1aViYcI2E30T1rBJDRHr8OcWCPOFgjz5VIe7yZet7lCfZKNzOlGNAVwDuzHuTvxRUTGCKEw+p0CcWJIRdVcXJj/JtABvCOFpCCBXs/jsMEqd2WQ9ZapOu1g9pRMSvsWvo9kDkWcnibydGX14O2GSSkALNi1zGex257sCJgo4xLAYrzvRLfxMelGEkSMdyGUXagBW4unGlpbRsefQciOlbRyNqAbIEanIQPm5IcXPeX2b6eWE+zBuOV8hFjkotgTNoI1rcnypyzbm3RcDitI+X5pa3bS1LrS4OCudxDWlIa0ol+t/w1RK98xvgjZ8qTNvRNi3RUo4MKzjMgZTRp1QJ6BHRroEWNItLyXPS/UAOQZZBsINE4m4DDALUAfPxSn+wJM2rYA1NrwekiF2r5FLhLpgc8NbgLmAZ4FOwCbD9RqoP9BhkiYBKz3QJNBwOGJywcLtwdsV+Cxj1YSS5NgDsfzBEYExgp6Q+7B4YM2lO1gwqdVGyh2B2Ap5ypYXoFPIUyek71HYxKfDeBKgSQDPsIPQDRxHcPCncAYQBzlsKiaRfkty8BRALQC3AJcBQARwFCAgw3bqAiAE/M/lBwG5s8RnNv230X6n6rat65hAxsIGYXBNfdko2hjtlx (much longer)
Where is the error in the webpack configuration? (I paste the relevant part)
const fastGlob = require('fast-glob')
const path = require('path')
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const isDev = process.env.NODE_ENV !== 'production'
const filename = isDev ? '[name]' : '[contenthash].[name]'
const entries = {
css: [
path.resolve(__dirname, 'src/_assets/styles/base.css'),
path.resolve(__dirname, 'src/_assets/styles/fonts.css'),
path.resolve(__dirname, 'src/_assets/styles/site.css'),
path.resolve(__dirname, 'src/_assets/styles/atomic.css'),
path.resolve(__dirname, 'src/_assets/styles/theme.css'),
],
}
module.exports = {
mode: isDev ? 'development' : 'production',
stats: {
colors: true,
preset: 'minimal',
},
performance: { hints: isDev ? 'warning' : false },
devtool: isDev ? 'cheap-module-source-map' : 'source-map',
entry: entries,
output: {
path: path.resolve(__dirname, '_build/_assets'),
publicPath: '/_assets/',
},
plugins: [
new CompressionPlugin({
filename: '[path][base].gz',
algorithm: 'gzip',
test: /\.(js|css|html|svg)$/,
threshold: 10240,
minRatio: 0.8,
}),
new webpack.ids.HashedModuleIdsPlugin(),
new ManifestPlugin(),
new RemoveEmptyScriptsPlugin(),
new MiniCssExtractPlugin({
filename: `${filename}.css`,
}),
],
...(!isDev && {
optimization: {
nodeEnv: 'production',
mangleWasmImports: true,
removeAvailableModules: true,
minimizer: [
new TerserPlugin(),
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
'default',
{
discardComments: { removeAll: true },
discardUnused: { removeAll: true },
},
],
},
}),
],
},
}),
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [{ loader: 'babel-loader' }],
},
{
test: /\.css$/i,
exclude: /node_modules/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {},
},
{
loader: 'css-loader',
options: {
sourceMap: isDev,
},
},
],
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: [{ loader: 'url-loader' }],
},
],
},
resolve: {
alias: {
assets: path.resolve(__dirname, 'src/_assets'),
},
},
}
Because you're using url-loader for fonts. With webpack 5, you can use Asset Modules for loading fonts:
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},

webpack not loading #font-face

in my React app i'm implementing server side rendering so i don't want to add node_modules in my server side because of performance issue.But i want css from from node_modules which are used as UI Kit libs.so i used webpack nodeExternal in my webpack.server.config file like
const path = require('path');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.js');
const nodeExternals = require('webpack-node-externals')
let test = {
test: /\.css$/,
loader: 'css/locals?module&localIdentName=[name]__[local]___[hash:base64:5]'
}
const config = {
target:'node',
entry: './src/index.js',
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'build')
},
externals: [nodeExternals({
whitelist: [/\.(?!(?:jsx?|json)$).{1,5}$/i]
})]
}
module.exports = merge(baseConfig,config)
here webpack adding css files but it is not loading #font-face from my node_modules UI kit files.if i remove nodeExternal from webpack.server.config file then every thing is working fine but bundle.js file size getting increased.
i already added font rule in my webpack.base.config file
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CSSExtract = new ExtractTextPlugin('styles.css');
module.exports ={
module: {
rules: [{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
}, {
test: /\.s?css$/,
use: CSSExtract.extract({
use: [
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
})
},{
test: /\.(gif|svg|jpg|png|ttf|eot|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader: 'url-loader?limit=100000&name=fonts/[name].[ext]'
}
],
},
devtool: 'inline-source-map',
plugins: [
CSSExtract
]
}
i tried with file-loader also but same problem
it showing me error
#font-face {
^
SyntaxError: Invalid or unexpected token
How can i add css files from node_modules with #font-face
here is webpack set up:
{
test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "file-loader",
options: {
name: "[name].[contenthash].[ext]",
outputPath: "fonts/",
},
},
],
},
then you have to import them to the css or scss main file.
#font-face {
font-family: "Montserrat";
src: url("../../assets/fonts/Montserrat-Light.ttf");
font-weight: lighter;
font-style: normal;
}

Load fonts with Webpack and font-face

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.
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' }
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'] }
]
}
};
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.
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/
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.
This took me a little while to figure out so I'm posting here in case this helps anyone in the future.
If you're using regular css on a node js / webpack build this solution worked for me:
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"],
},
},
},
{
test: /\.html$/,
exclude: /node_modules/,
use: "html-loader",
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
generator: {
filename: "assets/[name][ext][query]",
},
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: "asset/resource",
generator: {
filename: "fonts/[name][ext][query]",
},
},
],
},
Add the import statement needed in your .js file:
// images references in the manifest
import "../../assets/icon-16.png";
import "../../assets/icon-32.png";
import "../../assets/icon-64.png";
import "../../assets/icon-80.png";
import "../../assets/icon-25.png";
import "../../assets/icon-48.png";
//fonts referenced in the css
import "../../Fonts/opensans-regular-webfont.eot";
import "../../Fonts/opensans-regular-webfont.svg";
import "../../Fonts/opensans-regular-webfont.ttf";
import "../../Fonts/opensans-regular-webfont.woff";
import "../../Fonts/opensans-regular-webfont.woff2";
import "../../Fonts/OpenSans-Regular.ttf";
Then all you need to do is update your .css file to point to the dist/fonts file created:
#font-face {
font-family: 'open_sansregular';
src: url('fonts/opensans-regular-webfont.eot');
src: url('fonts/Fonts/opensans-regular-webfont.eot?#iefix') format('embedded-opentype'), url('fonts/opensans-regular-webfont.woff2') format('woff2'), url('fonts/opensans-regular-webfont.woff') format('woff'), url('fonts/opensans-regular-webfont.ttf') format('truetype'), url('fonts/opensans-regular-webfont.svg#open_sansregular') format('svg');
font-weight: normal;
font-style: normal;
}
html,
body {
font-family: open_sansregular !important
}
And then build the project.
In the webpack.config.ts I needed two things:
Webpack will handle font files with this code
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
}
]
}
AND then I needed css-loader for webpack to understand #font-face and and url() and style-loader to inject the css into the DOM.
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader'
]
},
]
}
Then in your index.css file under src add (My font was called Exo):
#font-face {
font-family: "Exo";
src: local(Exo), // This names it to use in css
url('./fonts/exo-v20-latin/exo-v20-latin-regular.woff2') format('woff2'),
url('./fonts/exo-v20-latin/exo-v20-latin-regular.woff') format('woff');
font-weight: normal;
font-style: normal;
}
html, body {
font-family: Arial, Helvetica, sans-serif;
}
I recommend woff formats because they handle all modern browsers.
Make sure to add your css file to your main app index.js:
import './index.css';
Then you might want to build so those files end up in your build/dist/public folder (whatever you've named your build folder).
npm run build
OR
yarn run build
This worked for me. Hope it works for you!
Try changing your loader to
{test: /\.(eot|svg|ttf|woff|woff2)$/, loader: 'file?name=[name].[ext]'}
and add publicPath: 'build/' to your output key.
I bumped webpack version to 4.42.0 from 4.20.2 and my code started loading the font I want.
const URL_LOADER_LIMIT = 8192
module.exports = () => ({
module: {
rules: [
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
limit: URL_LOADER_LIMIT
}
}
]
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
limit: URL_LOADER_LIMIT,
mimetype: 'application/font-woff'
}
}
]
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
limit: URL_LOADER_LIMIT,
mimetype: 'application/octet-stream'
}
}
]
},
{
test: /\.mp3$/,
use: ['file-loader']
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'url-loader',
options: {
outputPath: 'images/',
name: '[name].[ext]',
limit: URL_LOADER_LIMIT,
mimetype: 'image/svg+xml'
}
}
]
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
outputPath: 'images/',
name: '[name].[ext]',
limit: URL_LOADER_LIMIT
}
}
]
}
]
}
})

Webpack: Failed to decode downloaded font

Using FontFaceObserver and getting a webpack error.
Failed to decode downloaded font
OTS parsing error: invalid version tag
Webpack config:
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': resolve('src'),
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.mp4$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('videos/[name].[hash:7].[ext]')
}
}
]
}
}
At the top of App.vue stylesheet
#font-face {
font-family: Pragmatica;
font-weight: bold;
src: url('/static/fonts/PragmaticaCond-Extrabold.woff') format('woff');
}
#font-face {
font-family: Pragmatica;
src: url('/static/fonts/Pragmatica-Book.woff') format('woff');
}
My fonts sit within static/fonts/.
Any ideas?
It was a combination of a couple things. first was the path to the font file, I was setting the path as if there was no “build” happening, Webpack was putting them under /assetsafter release build so I had to update my path from /static/fonts to /fonts as after the build static files are automagically looked under assets folder + adding regex to support versioning in my webpack loader config + adding mimetype for woff files

Using local web fonts with webpack

I'm trying to use some local web fonts in my React project. I'm including them in my main.scss file, and loading them via webpack. The bundle builds correctly, including main.scss styles. I see webpack load the font files, and copy them to public/fonts/, but my bundle file can't find the fonts.
As I understand it, your #font-face src should be in relation to where bundle will be. I'm setting this to the same path that I load the fonts with in webpack, './fonts/'. The exact error I'm seeing is:
file:///Users/myusername/Documents/folder1/folder2/folder3/APP/fonts/FoundersGroteskWeb-Regular.woff net::ERR_FILE_NOT_FOUND
I've been trying a lot of different path configurations, and using the publicPath option in webpack, but I'm going in circles at this point over what seems like a really simple reference error.
File Structure:
APP
├──webpack.config.js
├──src
├──app
├──App.jsx
├──styles
├──main.scss
├──fonts
├──allthefonts.woff
├──public
├──bundle.js
├──fonts
├──allthefonts.woff
App.jsx:
require('./styles/main.scss');
main.scss:
#font-face {
font-family: FoundersGrotesk;
src: url('./fonts/FoundersGroteskWeb-Bold.eot') format('eot'),
url('./fonts/FoundersGroteskWeb-Bold.woff') format('woff'),
url('./fonts/FoundersGroteskWeb-Bold.woff2') format('woff2');
font-weight: bold;
}
#font-face {
font-family: FoundersGrotesk_Cnd;
src: url('./fonts/FoundersGrotXCondWeb-Bold.eot') format('eot'),
url('./fonts/FoundersGrotXCondWeb-Bold.woff') format('woff'),
url('./fonts/FoundersGrotXCondWeb-Bold.woff2') format('woff2');
font-weight: bold;
}
#font-face {
font-family: FoundersGrotesk;
src: url('./fonts/FoundersGroteskWeb-Regular.eot') format('eot'),
url('./fonts/FoundersGroteskWeb-Regular.woff') format('woff'),
url('./fonts/FoundersGroteskWeb-Regular.woff2') format('woff2');
font-weight: normal;
}
webpack.config.js:
'use strict';
const webpack = require('webpack');
const PROD = JSON.parse(process.env.PROD_ENV || '0');
module.exports = {
entry: './src/app/App.jsx',
output: {
path: './src/public/',
filename: PROD ? 'bundle.min.js' : 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: '/node_modules/',
query: {
presets: ['es2015', 'react', 'stage-1']
}
},
{
test: /\.s?css$/,
loaders: ['style', 'css', 'sass']
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file-loader?name=./fonts/[name].[ext]'
}
]
}
};
Got a working solution thanks to #omerts in this thread. Solution involved using publicPath. I had been trying to use it as an option in module.exports with the fonts file-loader, not the output.
Updated webpack.config.js:
const webpack = require('webpack');
const PROD = JSON.parse(process.env.PROD_ENV || '0');
const path = require('path');
const PATHS = {
build: path.join(__dirname, './src/public')
};
module.exports = {
entry: './src/app/App.jsx',
output: {
path: PATHS.build,
filename: PROD ? 'bundle.min.js' : 'bundle.js',
publicPath: PATHS.build
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: '/node_modules/',
query: {
presets: ['es2015', 'react', 'stage-1']
}
},
{
test: /\.s?css$/,
loaders: ['style', 'css', 'sass']
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file-loader?name=/fonts/[name].[ext]'
},
{
test: /\.(jpg|png)$/,
loader: 'file-loader?name=/fonts/[name].[ext]'
}
]
},
plugins: PROD ? [
new webpack.optimize.UglifyJsPlugin({
beautify: false,
comments: false,
compress: {
warnings: false,
drop_console: true
},
mangle: {
except: ['$'],
screw_ie8: true,
keep_fnames: false
}
})
] : []
};
a better approach would be to use 'url-loader' and add the following line in loaders.
{
test: /\.(jpe?g|png|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
loader: 'url-loader?limit=100000'
}
Is it possible to just always reference the original fonts? They don't appear to get changed by file-loader anyways.
File structure
APP
├───build
│ │ build.js
│ │ build.min.js
│ │
│ └───fonts
│ allthefonts.woff
│
├───css
│ main.css
│
├───fonts
│ allthefonts.woff
│
└───js
main.js
main.css
#font-face {
font-family: All-The-Fonts;
src: url('../fonts/allthefonts.woff') format('woff');
}
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
...
output: {
path: path.resolve(__dirname, 'build'),
filename: "[name].js",
globalObject: 'this'
},
module: {
rules: [
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: './fonts/' //dont actually use these fonts but still need to process them
}
}]
}
]
},
...
};
I got it working thanks to this article: https://www.robinwieruch.de/webpack-font

Resources