创见博客
用 webpack 处理样式资源:CSS、Less、Sass 全解析
七崽爱吃小饼干2026/09/15阅读 0

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 之外的额外依赖):

bash
npm install css-loader style-loader --save-dev

2. 配置 loader

js
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
};

3. 理解执行顺序

use 数组中的 loader **从右到左(从后到前)**执行,所以上面的配置实际流程是:

  1. css-loader:把 CSS 文件解析成 JS 模块,处理其中的 @import 和 url()。
  2. style-loader:把解析后的 CSS 通过 <style> 标签动态插入到页面 <head> 中。

之后在入口文件中引入样式即可:

js
import './style.css';

4. 用 CSS Modules 隔离样式

给 css-loader 传入 modules 选项,即可开启 CSS Modules,让类名局部作用域化,避免全局污染:

js
{
  test: /\.css$/i,
  use: [
    'style-loader',
    {
      loader: 'css-loader',
      options: {
        modules: true,
      },
    },
  ],
}

使用时:

js
import styles from './style.css';

const el = document.createElement('div');
el.className = styles.title;

二、处理 Less

Less 需要额外安装 less 和 less-loader:

bash
npm install less less-loader --save-dev

配置时注意顺序,less-loader 在最右侧最先执行:

js
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:

bash
npm install sass sass-loader --save-dev
js
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 选项:

js
{
  loader: 'sass-loader',
  options: {
    additionalData: `@use "@/styles/variables.scss" as *;`,
  },
}

四、接入 PostCSS

PostCSS 是一个用 JavaScript 转换 CSS 的工具,配合 autoprefixer 可以自动补全浏览器前缀,配合 postcss-preset-env 可以提前使用新语法:

bash
npm install postcss postcss-loader autoprefixer --save-dev

postcss-loader 要放在 css-loader 之后、预处理器 loader(less-loader/sass-loader)之前执行:

js
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:

js
module.exports = {
  plugins: [
    require('autoprefixer'),
  ],
};

五、生产环境:抽离与压缩 CSS

开发环境下用 style-loader 把样式插入页面很方便,但生产环境更希望 CSS 是独立文件,便于并行加载和浏览器缓存。此时应使用 mini-css-extract-plugin 替换 style-loader:

bash
npm install mini-css-extract-plugin css-minimizer-webpack-plugin --save-dev
js
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:

js
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 的完整配置如下:

js
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、该放在什么位置。

评论
0/100