css-loader — один из базовых загрузчиков Webpack,
предназначенный для обработки CSS-файлов внутри графа зависимостей
JavaScript-приложения. Он позволяет импортировать CSS напрямую в
JS-модули, преобразовывать директивы @import и
url(), а также интегрировать CSS в систему модульной сборки
Webpack.
Без css-loader Webpack воспринимает CSS-файл как
неизвестный тип ресурса. Попытка импортировать стили приводит к
ошибке:
import './styles.css';
Ошибка:
Module parse failed: Unexpected token
После подключения css-loader CSS становится полноценной
частью dependency graph.
Минимальная установка включает два загрузчика:
npm install css-loader style-loader --save-dev
css-loader — анализирует CSS и превращает его в
JavaScript-модульstyle-loader — внедряет стили в DOM через
<style>// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
Webpack применяет загрузчики справа налево.
Конструкция:
use: ['style-loader', 'css-loader']
эквивалентна:
style-loader(css-loader(styles.css))
css-loaderПреобразует CSS:
body {
background: black;
}
в JS-модуль примерно такого вида:
export default [
{
css: 'body { background: black; }'
}
];
Также анализируются:
@importurl()style-loaderПолучает результат предыдущего loader и вставляет CSS в DOM:
<style>
body {
background: black;
}
</style>
import './global.css';
Файл:
body {
margin: 0;
font-family: sans-serif;
}
После сборки стили автоматически появляются на странице.
@import@import './reset.css';
body {
color: black;
}
css-loader преобразует импорт в зависимости Webpack.
Фактически:
styles.css
└── reset.css
становится частью dependency graph.
url()Одно из важнейших назначений css-loader — анализ ссылок
на ресурсы.
.logo {
background-image: url('./logo.png');
}
Webpack:
url()Например:
background-image: url(/assets/logo.a1b2c3.png);
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|jpg|svg)$/i,
type: 'asset/resource'
}
]
}
};
src/
├── index.js
├── app.js
└── styles.css
import './styles.css';
import './app';
import './button.css';
export function createButton() {
const button = document.createElement('button');
button.className = 'button';
button.textContent = 'Click';
return button;
}
.button {
background: royalblue;
color: white;
}
Такой подход позволяет хранить стили рядом с компонентами.
Обычный CSS создаёт глобальное пространство имён.
.button {
color: red;
}
При большом количестве компонентов возникают:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
};
.button {
background: green;
color: white;
}
import styles from './button.module.css';
button.className = styles.button;
Исходный класс:
.button
превращается во что-то вроде:
.button_a6f12
или:
._button_1x8ab_3
Это исключает конфликты между компонентами.
Частая практика:
{
test: /\.module\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
Тогда:
app.css → глобальный CSSbutton.module.css → CSS Modulesmodulesoptions: {
modules: {
localIdentName: '[name]__[local]__[hash:base64:5]'
}
}
Button__button__a1b2c
Шаблоны:
| Шаблон | Значение |
|---|---|
[name] |
имя файла |
[local] |
имя класса |
[hash] |
уникальный hash |
В production обычно используют короткие имена:
localIdentName: '[hash:base64]'
Это уменьшает размер CSS.
importLoadersОпределяет количество loader’ов, применяемых к ресурсам из
@import.
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
}
Без importLoaders:
@import './reset.css';
может не пройти через postcss-loader.
{
loader: 'css-loader',
options: {
importLoaders: 1
}
}
1Один loader после css-loader должен применяться к
импортированным CSS-файлам.
Цепочка:
css-loader
postcss-loader
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'postcss-loader',
'sass-loader'
]
urlurl()По умолчанию:
url: true
options: {
url: false
}
Теперь:
background: url('./image.png');
не будет преобразовываться Webpack.
Например:
importПозволяет отключить обработку @import.
options: {
import: false
}
{
loader: 'css-loader',
options: {
sourceMap: true
}
}
Source maps позволяют:
style-loaderstyle-loader вставляет CSS через Jav * aScript:
<style>...</style>
Это подходит для development, но не для production.
Недостатки:
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].[contenthash].css'
})
]
};
Webpack создаёт отдельный CSS-файл:
main.a1b2c3.css
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
}
Через postcss-loader можно подключать:
npm install sass sass-loader --save-dev
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
SCSS
↓
sass-loader
↓
css-loader
↓
style-loader
По умолчанию css-loader использует ES Modules:
import styles from './style.css';
options: {
esModule: false
}
const styles = require('./style.css');
Полезно для SSR.
options: {
modules: {
exportOnlyLocals: true
}
}
CSS не внедряется в DOM.
Экспортируются только имена классов:
{
button: 'button_a1b2c'
}
modules: {
namedExport: true
}
.title {
color: red;
}
import { title } from './style.module.css';
style-loader в lazy-режимеuse: [
{
loader: 'style-loader',
options: {
injectType: 'lazyStyleTag'
}
},
'css-loader'
]
import styles from './style.css';
styles.use();
styles.unuse();
Это позволяет динамически подключать и отключать стили.
css-loader поддерживает Hot Module Replacement.
При изменении CSS:
Неправильно:
use: ['css-loader', 'style-loader']
Правильно:
use: ['style-loader', 'css-loader']
use: ['css-loader']
CSS обработается, но не попадёт в DOM.
url()Причина часто связана с отсутствием asset modules:
{
test: /\.(png|jpg|svg)$/i,
type: 'asset/resource'
}
Ошибка:
import styles from './style.css';
console.log(styles.button);
styles.button будет undefined, если
modules: true отключён.
В production обычно используют:
filename: '[name].[contenthash].css'
Это позволяет браузеру эффективно кешировать стили.
Обычно подключается через:
css-minimizer-webpack-pluginoptimization.minimizeПодходит для:
Подходит для:
Часто используется:
src/
├── styles/
│ ├── reset.css
│ └── globals.css
│
└── components/
└── Button/
├── Button.js
└── Button.module.css
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.module\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[hash:base64]'
},
importLoaders: 1
}
},
'postcss-loader'
]
},
{
test: /\.css$/,
exclude: /\.module\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
})
]
};