Asset modules allow you to use asset files (fonts, icons, images, etc.) without configuring additional loaders.
Asset Module Types
Webpack 5 provides four asset module types:
| Type | Description | Old Equivalent |
|---|
asset/resource | Emits file and exports URL | file-loader |
asset/inline | Exports data URI | url-loader |
asset/source | Exports source code | raw-loader |
asset | Auto-chooses between resource and inline | url-loader with limit |
Asset modules are built into webpack 5. No need to install additional loaders.
Basic Usage
Configure asset module types
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif|svg)$/,
type: 'asset/resource'
}
]
}
};
Import assets in your code
import logo from './images/logo.png';
const img = document.createElement('img');
img.src = logo;
document.body.appendChild(img);
Configure output location
module.exports = {
output: {
assetModuleFilename: 'assets/[hash][ext][query]'
}
};
asset/resource
Emits files to the output directory and returns the URL:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/,
type: 'asset/resource'
}
]
},
output: {
assetModuleFilename: 'images/[hash][ext][query]'
}
};
Usage:
import imageUrl from './photo.jpg';
// imageUrl is: 'images/a1b2c3d4.jpg'
Use asset/resource for large images, videos, and other files that should be loaded separately.
asset/inline
Inlines assets as data URIs:
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
type: 'asset/inline'
}
]
}
};
Usage:
import svgData from './icon.svg';
// svgData is: 'data:image/svg+xml;base64,...'
Inlining large files increases bundle size. Only inline small assets (< 8-10 KB).
asset/source
Imports the raw source code of the asset:
module.exports = {
module: {
rules: [
{
test: /\.txt$/,
type: 'asset/source'
}
]
}
};
Usage:
import textContent from './data.txt';
// textContent is the text file content as a string
console.log(textContent);
asset (Automatic)
Automatically chooses between inline and resource based on file size:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8kb
}
}
}
]
}
};
Behavior:
- Files < 8 KB: Inlined as data URI
- Files ≥ 8 KB: Emitted as separate files
The asset type is the most versatile. It optimizes automatically based on file size.
Custom Output Filenames
Global Configuration
module.exports = {
output: {
assetModuleFilename: 'assets/[name]-[hash][ext][query]'
}
};
Per-Rule Configuration
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg)$/,
type: 'asset/resource',
generator: {
filename: 'images/[hash][ext][query]'
}
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext]'
}
}
]
}
};
Filename Placeholders
| Placeholder | Description |
|---|
[name] | Original filename |
[hash] | Content hash |
[ext] | Extension with dot |
[query] | Query string |
[path] | Original path |
[contenthash] | Content hash (alias) |
Example:
generator: {
filename: 'assets/[path][name]-[hash:8][ext]'
}
Common Asset Types
Images
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024
}
},
generator: {
filename: 'images/[hash][ext][query]'
}
}
]
}
};
SVG
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
type: 'asset/inline',
generator: {
dataUrl: content => {
content = content.toString();
return `data:image/svg+xml,${encodeURIComponent(content)}`;
}
}
}
]
}
};
Fonts
module.exports = {
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext]'
}
}
]
}
};
Usage in CSS:
@font-face {
font-family: 'MyFont';
src: url('./fonts/myfont.woff2') format('woff2');
}
Data Files
module.exports = {
module: {
rules: [
{
test: /\.(json|xml|csv)$/,
type: 'asset/source'
}
]
}
};
Public Path
Set the base path for assets in production:
module.exports = {
output: {
publicPath: 'https://cdn.example.com/',
assetModuleFilename: 'assets/[hash][ext]'
}
};
Result:
import logo from './logo.png';
// logo is: 'https://cdn.example.com/assets/a1b2c3d4.png'
The publicPath is prepended to all asset URLs. Use it when serving assets from a CDN.
Custom Data URL
Customize how data URIs are generated:
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
type: 'asset/inline',
generator: {
dataUrl: content => {
const svgContent = content.toString();
// Optimize or transform SVG
return `data:image/svg+xml;utf8,${encodeURIComponent(svgContent)}`;
}
}
}
]
}
};
Migration from Loaders
From file-loader
Before:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: ['file-loader']
}
]
}
};
After:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
type: 'asset/resource'
}
]
}
};
From url-loader
Before:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
}
};
After:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8192
}
}
}
]
}
};
From raw-loader
Before:
module.exports = {
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
]
}
};
After:
module.exports = {
module: {
rules: [
{
test: /\.txt$/,
type: 'asset/source'
}
]
}
};
Asset modules are simpler and faster than the old loader approach. Migrate when upgrading to webpack 5.
Complete Example
const path = require('path');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
assetModuleFilename: 'assets/[hash][ext][query]',
publicPath: '/'
},
module: {
rules: [
// Images - auto inline if < 8kb
{
test: /\.(png|jpg|jpeg|gif|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024
}
},
generator: {
filename: 'images/[hash][ext][query]'
}
},
// SVG - inline as data URI
{
test: /\.svg$/,
type: 'asset/inline'
},
// Fonts - always separate files
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext]'
}
},
// Text/data files - raw content
{
test: /\.(txt|md)$/,
type: 'asset/source'
}
]
}
};