I managed configure webpack to output CSS and JS into respective sub-directories, i.e. public/asests/css
and public/assets/js
. However, I don't know how to do the same for images and fonts.
In other words, I want to output images in public/assets/images
folder and fonts into public/assets/fonts
folder.
Here's my webpack config file:
var path = require('path');
var ExtractCSS = require('extract-text-webpack-plugin');
module.exports = {
context: path.resolve('private/js'),
resolve: ['', '.js', '.jsx', '.es6', '.json'],
entry: {
homepage: './homepage'
},
output: {
path: path.resolve('public/assets'),
publicPath: '/public/assets/',
filename: 'js/[name].js'
},
plugins: [
new ExtractCSS('css/[name].css')
],
devServer: {
contentBase: 'public'
},
module: {
loaders: [
{
test: /\.(es6|js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.css$/,
exclude: /node_modules/,
loader: ExtractCSS.extract('style-loader', 'css-loader')
},
{
test: /\.less$/,
exclude: /node_modules/,
loader: ExtractCSS.extract('style-loader', 'css-loader!less-loader')
},
{
test: /\.(jpg|jpeg|gif|png|woff|woff2|eot|ttf|svg)$/,
exclude: /node_modules/,
loader: 'url-loader?limit=1024'
}
]
}
}
I could figure this out by referring to url-loader & file-loader documentation on GitHub.
All, I needed to do was to add a name query-string parameter in loader to specify full path. I also learned that you can specify how files should be named in output location.
{ test: /\.(jpg|jpeg|gif|png)$/, exclude: /node_modules/, loader:'url-loader?limit=1024&name=images/[name].[ext]' }, { test: /\.(woff|woff2|eot|ttf|svg)$/, exclude: /node_modules/, loader: 'url-loader?limit=1024&name=fonts/[name].[ext]' }
{ test: /\.(ttf|eot|svg|woff2?)(\?v=[a-z0-9=\.]+)?$/i, include: folders.npm, loader: 'file?name=fonts/[name].[ext]' }, { test: /\.(jpe?g|png|gif|svg|ico)$/i, include: folders.src, loaders: [ 'file?name=images/[sha512:hash:base64:7].[ext]', 'image-webpack?progressive=true&optimizationLevel=7&interlaced=true' ] }
This is what I use in production. I often come across situation where *.svg pictures are used and SVG fonts for IE fallback. Here I assume font are always inside node_modules. I have also seen devs doing test: /fonts\/[w+].(svg|eot ....)
.
Webpack 5 case-
Keeping it here just in case someone is looking for a Webpack 5 solution to the requirement of outputting image/font assets into separate directories into the output path.
Webpack 5 replaces raw-loader
, url-loader
and file-loader
with Assets Module and it has 4 new modules to handle assets. Read in more details here - https://webpack.js.org/guides/asset-modules/
To our problem statement, the following configuration outputs all fonts/svgs into the directory fonts
. But if certain files are less than 8KB, it throws them inline.
{
test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
type: 'asset', // <-- Assets module - asset
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8kb
}
},
generator: { //If emitting file, the file path is
filename: 'fonts/[hash][ext][query]'
}
}
Similarly we could do the same for images -
{
test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
type: 'asset/resource', //<-- Assets module - asset/resource
generator: {
filename: 'images/[hash][ext][query]'
}
}
Outputs all images to images
directory irrespective of file size.
I was able to solve this with file-loader
If you're using the Webpack 4, you would use use
instead of loader
.
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader?name=fonts/[name].[ext]']
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With