webpack 本身只认识 JavaScript 和 JSON,无法直接处理 CSS、Less、Sass 这类样式资源。要让样式参与构建流程,就必须借助对应的 loader。本文从最基础的 CSS 入手,逐步扩展到 Less、Sass、PostCSS,以及生产环境下的样式抽离与压缩。
一、处理 CSS
1. 安装依赖
处理 CSS 需要 css-loader 和 style-loader 两个 loader(webpack 5 不再需要 style-loader/css-loader 之外的额外依赖):
npm install css-loader style-loader --save-dev
2. 配置 loader
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
};
3. 理解执行顺序
use 数组中的 loader **从右到左(从后到前)**执行,所以上面的配置实际流程是:
css-loader:把 CSS 文件解析成 JS 模块,处理其中的@import和url()。style-loader:把解析后的 CSS 通过<style>标签动态插入到页面<head>中。
之后在入口文件中引入样式即可:
import './style.css';
4. 用 CSS Modules 隔离样式
给 css-loader 传入 modules 选项,即可开启 CSS Modules,让类名局部作用域化,避免全局污染:
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
}
使用时:
import styles from './style.css';
const el = document.createElement('div');
el.className = styles.title;
二、处理 Less
Less 需要额外安装 less 和 less-loader:
npm install less less-loader --save-dev
配置时注意顺序,less-loader 在最右侧最先执行:
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: ['style-loader', 'css-loader', 'less-loader'],
},
],
},
};
less-loader 会先调用 Less 编译器把 .less 编译成标准 CSS,再交给 css-loader 解析,最后交给 style-loader 注入页面。
三、处理 Sass / SCSS
Sass 的官方实现是 sass,对应的 loader 是 sass-loader:
npm install sass sass-loader --save-dev
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
],
},
};
注意正则 /\.s[ac]ss$/i 同时匹配 .sass 和 .scss 两种后缀。sass-loader 内部通过 sass 完成编译。
如果需要全局注入变量(例如主题色),可以使用 additionalData 选项:
{
loader: 'sass-loader',
options: {
additionalData: `@use "@/styles/variables.scss" as *;`,
},
}
四、接入 PostCSS
PostCSS 是一个用 JavaScript 转换 CSS 的工具,配合 autoprefixer 可以自动补全浏览器前缀,配合 postcss-preset-env 可以提前使用新语法:
npm install postcss postcss-loader autoprefixer --save-dev
postcss-loader 要放在 css-loader 之后、预处理器 loader(less-loader/sass-loader)之前执行:
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader', 'postcss-loader'],
},
{
test: /\.less$/i,
use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'],
},
],
},
};
在项目根目录创建 postcss.config.js:
module.exports = {
plugins: [
require('autoprefixer'),
],
};
五、生产环境:抽离与压缩 CSS
开发环境下用 style-loader 把样式插入页面很方便,但生产环境更希望 CSS 是独立文件,便于并行加载和浏览器缓存。此时应使用 mini-css-extract-plugin 替换 style-loader:
npm install mini-css-extract-plugin css-minimizer-webpack-plugin --save-dev
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
],
optimization: {
minimizer: [
'...', // 保留 webpack 默认的 JS 压缩
new CssMinimizerPlugin(),
],
},
};
这样 CSS 会被抽离成独立文件,并通过 [contenthash] 获得长久缓存能力。
六、用 asset modules 处理样式中的图片
样式里经常引用图片、字体等资源。webpack 5 内置了 asset modules,无需再安装 file-loader / url-loader:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024, // 小于 8KB 内联为 base64
},
},
generator: {
filename: 'images/[hash][ext][query]',
},
},
{
test: /\.(woff2?|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[hash][ext][query]',
},
},
],
},
};
asset/resource:始终输出为独立文件。asset/inline:始终内联为 base64。asset:根据maxSize自动在两者之间选择。
七、完整配置示例
把以上内容整合,一个支持 CSS / Less / Sass 的完整配置如下:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const isProduction = process.env.NODE_ENV === 'production';
const styleLoader = isProduction ? MiniCssExtractPlugin.loader : 'style-loader';
module.exports = {
mode: isProduction ? 'production' : 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true,
},
module: {
rules: [
{
test: /\.css$/i,
use: [styleLoader, 'css-loader', 'postcss-loader'],
},
{
test: /\.less$/i,
use: [styleLoader, 'css-loader', 'postcss-loader', 'less-loader'],
},
{
test: /\.s[ac]ss$/i,
use: [styleLoader, 'css-loader', 'postcss-loader', 'sass-loader'],
},
{
test: /\.(png|jpe?g|gif|svg)$/i,
type: 'asset',
parser: { dataUrlCondition: { maxSize: 8 * 1024 } },
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
],
};
小结
处理样式资源的关键,是理解 loader 的执行顺序:预处理器 loader(less-loader / sass-loader)先把 Less/Sass 编译成标准 CSS,postcss-loader 做兼容性处理,css-loader 解析成模块,最后由 style-loader 或 MiniCssExtractPlugin.loader 决定样式如何落地。记住这条链路,无论面对哪种样式方案,都能快速定位该用哪个 loader、该放在什么位置。