До появления Webpack 5 обработка изображений, шрифтов, SVG-файлов и других статических ресурсов выполнялась через отдельные загрузчики:
file-loaderurl-loaderraw-loaderТакой подход создавал избыточную конфигурацию, требовал установки дополнительных пакетов и усложнял поддержку проекта.
Webpack 5 внедрил встроенный механизм Asset Modules, который заменяет большую часть возможностей этих загрузчиков без необходимости их отдельной установки.
Asset Modules позволяют:
Webpack 5 поддерживает пять основных типов ресурсов:
| Тип | Назначение |
|---|---|
asset/resource |
Генерация отдельного файла |
asset/inline |
Встраивание файла в Base64 |
asset/source |
Получение содержимого файла как строки |
asset/bytes |
Получение бинарных данных |
asset |
Автоматический выбор между inline и resource |
Тип asset/resource заменяет
file-loader.
Webpack копирует файл в директорию сборки и возвращает путь к нему.
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset/resource'
}
]
}
};
import logo fr om './images/logo.png';
console.log(logo);
Webpack вернёт строку:
/dist/8f3a2c1e.png
dist/
├── main.js
├── 8f3a2c1e.png
Webpack позволяет управлять структурой файлов через
generator.
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg)$/i,
type: 'asset/resource',
generator: {
filename: 'images/[hash][ext][query]'
}
}
]
}
};
| Плейсхолдер | Значение |
|---|---|
[name] |
Имя файла |
[ext] |
Расширение |
[hash] |
Хеш файла |
[contenthash] |
Хеш содержимого |
[query] |
Query-строка |
Исходный файл:
src/assets/logo.png
После сборки:
dist/images/3f2c1d8a.png
Тип asset/inline заменяет url-loader в
режиме Base64.
Файл не создаётся отдельно — он встраивается прямо в bundle.
module.exports = {
module: {
rules: [
{
test: /\.svg$/i,
type: 'asset/inline'
}
]
}
};
import icon fr om './icon.svg';
console.log(icon);
Webpack вернёт:
data:image/svg+xml;base64,...
Подходит для:
Base64 увеличивает размер данных примерно на 30%.
Поэтому крупные файлы:
Тип asset/source заменяет raw-loader.
Webpack загружает содержимое файла как строку.
module.exports = {
module: {
rules: [
{
test: /\.txt$/i,
type: 'asset/source'
}
]
}
};
import text fr om './info.txt';
console.log(text);
"Hello Webpack"
Частые сценарии:
Тип asset/bytes предоставляет доступ к бинарным
данным.
Webpack возвращает Uint8Array.
module.exports = {
module: {
rules: [
{
test: /\.bin$/,
type: 'asset/bytes'
}
]
}
};
import data fr om './file.bin';
console.log(data);
Uint8Array(...)
Тип asset автоматически решает:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|svg)$/i,
type: 'asset'
}
]
}
};
Webpack анализирует размер файла:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024
}
}
}
]
}
};
maxSize: 8 * 1024
означает:
8 KB
Если файл меньше:
Если больше:
| Характеристика | asset/resource | asset |
|---|---|---|
| Всегда создаёт файл | Да | Нет |
| Может inline | Нет | Да |
| Аналог file-loader | Да | Частично |
| Аналог url-loader | Нет | Да |
module.exports = {
output: {
assetModuleFilename: 'assets/[hash][ext][query]'
}
};
dist/
└── assets/
├── a12bc3.png
├── f9de21.svg
Если указан generator.filename, он имеет приоритет
над:
output.assetModuleFilename
{
test: /\.(png|jpg|gif)$/i,
type: 'asset/resource',
generator: {
filename: 'images/[name].[contenthash][ext]'
}
}
{
test: /\.(woff2?|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash][ext]'
}
}
{
test: /\.svg$/i,
type: 'asset'
}
Asset Modules работают не только в JavaScript.
.logo {
background-image: url('./images/logo.png');
}
Webpack автоматически обработает файл через Asset Modules.
module.exports = {
output: {
publicPath: '/static/'
}
};
/static/images/logo.png
{
test: /\.(png|jpg)$/i,
type: 'asset/resource',
generator: {
publicPath: '/cdn/'
}
}
generator: {
filename: 'images/[hash][ext]',
publicPath: 'https://cdn.site.com/'
}
Иногда необходимо получить URL файла без его автоматической обработки.
Webpack 5 поддерживает:
const image = new URL('./logo.png', import.meta.url);
URL {
href: '/dist/logo.png'
}
Webpack может исключать неиспользуемые ресурсы из сборки.
import './logo.png';
Если импорт нигде не используется и не имеет side effects, ресурс может быть удалён.
Не требуется:
npm install file-loader url-loader raw-loader
Webpack 4:
{
test: /\.png$/,
use: [
{
loader: 'url-loader',
options: {
lim it: 8192
}
}
]
}
Webpack 5:
{
test: /\.png$/,
type: 'asset'
}
Встроенная реализация работает быстрее сторонних loader-пакетов.
{
test: /\.(png|jpg)$/i,
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
outputPath: 'images'
}
}
{
test: /\.(png|jpg)$/i,
type: 'asset/resource',
generator: {
filename: 'images/[name].[hash][ext]'
}
}
{
test: /\.svg$/,
loader: 'url-loader',
options: {
lim it: 4096
}
}
{
test: /\.svg$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024
}
}
}
{
test: /\.txt$/,
use: 'raw-loader'
}
{
test: /\.txt$/,
type: 'asset/source'
}
Asset Modules можно комбинировать с загрузчиками.
{
test: /\.(png|jpg)$/i,
type: 'asset/resource',
use: [
{
loader: 'image-webpack-loader'
}
]
}
module.exports = {
module: {
rules: [
{
oneOf: [
{
test: /\.svg$/,
type: 'asset/inline'
},
{
test: /\.(png|jpg)$/i,
type: 'asset/resource'
}
]
}
]
}
};
Преимущества:
Недостатки:
Преимущества:
Недостатки:
generator: {
filename: 'images/[name].[contenthash][ext]'
}
При изменении файла:
logo.png
изменяется:
logo.a13d82.png
Браузер получает новую версию вместо кэшированной.
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024
}
},
generator: {
filename: 'images/[contenthash][ext]'
}
},
{
test: /\.svg$/i,
type: 'asset/inline'
},
{
test: /\.(woff2?|ttf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext]'
}
},
{
test: /\.txt$/i,
type: 'asset/source'
}
]
}
};
Ошибка:
test: /\.png/
Лучше:
test: /\.png$/i
Неверно:
{
test: /\.png$/,
loader: 'file-loader',
type: 'asset/resource'
}
Asset Modules заменяют старые loaders, поэтому совместное использование обычно не требуется.
Ошибка:
maxSize: 500 * 1024
Проблемы:
| Тип ресурса | Рекомендуемый тип |
|---|---|
| Большие изображения | asset/resource |
| Иконки SVG | asset/inline |
| Шрифты | asset/resource |
| Markdown | asset/source |
| Небольшие картинки | asset |
Для production чаще всего используются:
type: 'asset'
и:
contenthash
Это обеспечивает:
const path = require('path');
module.exports = {
mode: 'production',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[contenthash].js',
clean: true,
assetModuleFilename: 'assets/[hash][ext][query]'
},
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024
}
},
generator: {
filename: 'images/[contenthash][ext]'
}
},
{
test: /\.svg$/i,
type: 'asset/inline'
},
{
test: /\.(woff2?|ttf|eot)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash][ext]'
}
},
{
test: /\.(txt|md)$/i,
type: 'asset/source'
}
]
}
};