Загрузчики (loaders) — механизм преобразования файлов в процессе сборки. По умолчанию Webpack понимает только JavaScript и JSON, поэтому любые другие типы ресурсов требуют дополнительной обработки.
Загрузчики позволяют:
Webpack рассматривает любой импорт как модуль. Это означает, что можно импортировать не только Jav * aScript:
import './styles/main.scss';
import logo fr om './images/logo.png';
import data from './data/users.json';
Однако без соответствующих загрузчиков большинство таких импортов вызовет ошибку.
Каждый loader представляет собой функцию преобразования.
Webpack передаёт содержимое файла загрузчику, а загрузчик возвращает преобразованный результат.
Обработка происходит по цепочке.
Пример:
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
}
};
Последовательность выполнения:
sass-loadercss-loaderstyle-loaderЗагрузчики выполняются справа налево.
Преобразует SCSS в обычный CSS.
Позволяет импортировать CSS как модуль JavaScript.
Вставляет CSS в <style> внутри HTML-страницы.
Все loaders настраиваются внутри module.rules.
Базовая структура:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
}
]
}
};
Определяет файлы, к которым применяется правило.
test: /\.js$/
Пример для SCSS:
test: /\.scss$/
Указывает используемые loaders.
Один loader:
use: 'babel-loader'
Несколько loaders:
use: [
'style-loader',
'css-loader'
]
Исключает файлы или каталоги.
Чаще всего исключается node_modules.
exclude: /node_modules/
Ограничивает область применения.
include: path.resolve(__dirname, 'src')
Один из самых важных загрузчиков.
Используется для преобразования современного JavaScript.
Установка:
npm install babel-loader @babel/core @babel/preset-env --save-dev
Конфигурация:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
};
Каждый loader может принимать параметры.
Пример:
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
options передаёт конфигурацию конкретному
загрузчику.
Позволяет импортировать CSS-файлы.
Установка:
npm install css-loader style-loader --save-dev
Конфигурация:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
}
};
Импорт:
import './styles.css';
Используется для поддержки SCSS и Sass.
Установка:
npm install sass-loader sass --save-dev
Конфигурация:
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
}
};
Поддержка Less.
Установка:
npm install less-loader less --save-dev
Конфигурация:
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
Webpack может компилировать TypeScript.
Установка:
npm install typescript ts-loader --save-dev
Конфигурация:
module.exports = {
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
}
};
Дополнительно нужен tsconfig.json.
В Webpack 5 появилась встроенная поддержка ресурсов, однако loaders всё ещё широко используются.
Ранее активно применялся file-loader.
Пример старого подхода:
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'file-loader'
}
]
}
Современный вариант:
{
test: /\.(png|jpg|gif)$/i,
type: 'asset/resource'
}
Webpack 5 заменил:
file-loaderurl-loaderraw-loaderСоздаёт отдельный файл.
{
test: /\.(png|svg)$/i,
type: 'asset/resource'
}
Преобразует файл в Base64.
{
test: /\.svg$/,
type: 'asset/inline'
}
Импортирует содержимое как строку.
{
test: /\.txt$/,
type: 'asset/source'
}
Автоматически выбирает стратегию.
{
test: /\.(png|jpg)$/i,
type: 'asset'
}
Позволяет импортировать HTML.
Установка:
npm install html-loader --save-dev
Конфигурация:
{
test: /\.html$/,
loader: 'html-loader'
}
Импорт:
import template from './template.html';
Обработка CSV-файлов.
Установка:
npm install csv-loader --save-dev
Конфигурация:
{
test: /\.csv$/,
use: 'csv-loader'
}
Обработка XML.
Установка:
npm install xml-loader --save-dev
Конфигурация:
{
test: /\.xml$/,
use: 'xml-loader'
}
Для React обычно используется Babel.
Установка:
npm install babel-loader @babel/preset-react --save-dev
Конфигурация:
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react'
]
}
}
}
Vue использует vue-loader.
Установка:
npm install vue-loader vue-template-compiler --save-dev
Конфигурация:
const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new VueLoaderPlugin()
]
};
Loader можно указать прямо в import.
import styles from 'style-loader!css-loader!./styles.css';
Такой подход считается устаревшим и редко используется в современных проектах.
Предпочтительно настраивать loaders через
module.rules.
Webpack поддерживает стадии обработки.
Выполняется до обычных loaders.
{
test: /\.js$/,
enforce: 'pre',
use: 'eslint-loader'
}
Выполняется после остальных loaders.
{
test: /\.js$/,
enforce: 'post',
use: 'some-loader'
}
Разница принципиальна.
Преобразует конкретный файл.
Примеры:
Воздействует на процесс сборки целиком.
Примеры:
Важно понимать последовательность.
Конфигурация:
use: [
'style-loader',
'css-loader',
'sass-loader'
]
Выполнение:
sass-loader
↓
css-loader
↓
style-loader
То есть Webpack идёт справа налево.
Короткая форма:
use: 'babel-loader'
Полная форма:
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
Полная форма используется чаще, поскольку позволяет задавать параметры.
Каждый loader может иметь собственные options.
{
test: /\.scss$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true
}
},
{
loader: 'sass-loader'
}
]
}
Позволяют локализовать CSS-классы.
Конфигурация:
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
Использование:
import styles from './Button.module.css';
button.className = styles.primary;
Webpack создаёт уникальные имена классов.
Для корректной отладки loaders должны поддерживать source maps.
Пример:
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
Обычно source maps включаются во всех связанных loaders.
Большое количество loaders замедляет сборку.
Основные причины:
exclude: /node_modules/
Одна из важнейших оптимизаций.
Позволяет кешировать результаты.
npm install cache-loader --save-dev
Пример:
{
test: /\.js$/,
use: [
'cache-loader',
'babel-loader'
]
}
Параллельная обработка.
npm install thread-loader --save-dev
Пример:
{
test: /\.js$/,
use: [
'thread-loader',
'babel-loader'
]
}
Loader — обычная Node.js-функция.
Простейший пример:
module.exports = function(source) {
return source.replace('Hello', 'Hi');
};
{
test: /\.txt$/,
use: path.resolve(__dirname, 'loaders/my-loader.js')
}
Webpack поддерживает асинхронную обработку.
Пример:
module.exports = function(source) {
const callback = this.async();
setTimeout(() => {
callback(null, source);
}, 1000);
};
Внутри loader доступен объект this.
Полезные свойства:
| Свойство | Назначение |
|---|---|
| this.resourcePath | Путь к файлу |
| this.query | Параметры |
| this.async() | Асинхронный режим |
| this.emitFile() | Создание файлов |
Пример:
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
Внутри loader параметры доступны через:
this.getOptions()
Специальный метод pitch.
module.exports.pitch = function() {
console.log('pitch');
};
module.exports = function(source) {
return source;
};
pitch выполняется слева направо, а обычные loaders —
справа налево.
SCSS:
SCSS
↓ sass-loader
CSS
↓ css-loader
JS Module
↓ style-loader
STYLE tag
Частая проблема:
use: [
'sass-loader',
'css-loader'
]
Такой порядок неправильный.
sass-loader требует установленного
sass.
Некоторые loaders несовместимы между собой или требуют определённой последовательности.
В production чаще используется извлечение CSS в отдельные файлы.
Установка:
npm install mini-css-extract-plugin --save-dev
Конфигурация:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css'
})
]
};
Часто loaders отличаются в зависимости от режима.
use: [
'style-loader',
'css-loader'
]
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
Webpack ищет loaders:
node_modules;resolveLoader.Пример:
resolveLoader: {
modules: ['node_modules', 'custom-loaders']
}
Позволяет импортировать файл как строку.
Ранее:
{
test: /\.txt$/,
use: 'raw-loader'
}
Современный вариант:
{
test: /\.txt$/,
type: 'asset/source'
}
Ранее использовался для inline Base64.
{
test: /\.(png|jpg)$/i,
use: {
loader: 'url-loader',
options: {
lim it: 8192
}
}
}
В Webpack 5 заменён Asset Modules.
Loaders являются фундаментом экосистемы Webpack.
Именно они позволяют:
Без loaders Webpack был бы лишь упаковщиком JavaScript-файлов.