less-loader

npm node deps tests cover chat size

webpack 将 Less 编译为 CSS 的 loader。

快速开始

首先,你需要先安装 less-loader

$ npm install less-loader --save-dev

然后将该 loader 添加到 webpack 的配置中去,例如:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        loader: 'less-loader', // 将 Less 文件编译为 CSS 文件
      },
    ],
  },
};

接着使用你习惯的方式运行 webpack

可选项

名称 类型 默认值 描述

名称

类型

默认值

描述

lessOptions

{Object\|Function}

{Object\|Function} { relativeUrls: true } Less 的可选项。

名称

类型

默认值

描述

prependData

{String\|Function}

{String\|Function} undefined 在实际输入文件开头追加 Less 代码。

名称

类型

默认值

描述

appendData

{String\|Function}

{String\|Function} undefined 在实际输入文件末尾追加 Less 代码。

名称

类型

默认值

描述

sourceMap

{Boolean}

{Boolean} compiler.devtool 是否生成 source map。

名称

类型

默认值

描述

{Object} less 配置 Less 使用的实现库

lessOptions

类型: Object|Function 默认值: { relativeUrls: true }

通过 lessOptions 属性,你可以设置 loader options 中的任意特定的选项值给 less-loader。所有可用的选项值请参看 Less 命令行可选参数文档。由于我们是通过编程的方式将这些选项传递给 Less,因此您需要将破折号(dash-case)转换为驼峰值(camelCase)后传递它们。

Object

使用对象(Object)的形式传递 options 给 Less。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                strictMath: true,
              },
            },
          },
        ],
      },
    ],
  },
};

Function

允许根据 loader 的 context 来设置 options,再传递给 Less。

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              lessOptions: (loaderContext) => {
                // 更多可用的属性见 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.less') {
                  return {
                    paths: ['absolute/path/c', 'absolute/path/d'],
                  };
                }

                return {
                  paths: ['absolute/path/a', 'absolute/path/b'],
                };
              },
            },
          },
        ],
      },
    ],
  },
};

prependData

类型: String|Function 默认值: undefined

在实际输入文件的开头追加 Less 代码

当你的 Less 变量依赖环境变量时这个属性将非常有用:

ℹ 由于你注入了代码,因此它将破坏入口文件的源映射关系。通常有比这更简单的解决方案,例如多个 Less 入口文件。

String

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              prependData: `@env: ${process.env.NODE_ENV};`,
            },
          },
        ],
      },
    ],
  },
};

Function

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              prependData: (loaderContext) => {
                // 更多可用的属性见 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.less') {
                  return '@value: 100px;';
                }

                return '@value: 200px;';
              },
            },
          },
        ],
      },
    ],
  },
};

appendData

类型: String|Function 默认值: undefined

在实际输入文件末尾追加 Less 代码。

当你需要重写一些 Less 变量的时候会很有用:

ℹ 由于你注入了代码,因此它将破坏入口文件的源映射关系。通常有比这更简单的解决方案,例如多个 Less 入口文件。

String

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              appendData: `@env: ${process.env.NODE_ENV};`,
            },
          },
        ],
      },
    ],
  },
};

Function

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              appendData: (loaderContext) => {
                // 更多可用的属性见 https://webpack.js.org/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

                if (relativePath === 'styles/foo.less') {
                  return '@value: 100px;';
                }

                return '@value: 200px;';
              },
            },
          },
        ],
      },
    ],
  },
};

sourceMap

类型: Boolean 默认值: 取决于 compiler.devtool 的值

默认生成的 source map 取决于 compiler.devtool 的值。除了值等于 evalfalse 外,其他值都能生成 source map

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'less-loader',
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

implementation

类型: Object 默认值: less

⚠ less-loader 仅与 Less3 版本兼容

特殊的 implementation 选项确定要使用的 Less 实现库。 implementation 选项接受 less 作为一个模块。 当你想使用小版本的 Less 时这个选项很有用,但不要忘记了你需要安装自己的 Less 版本。

如下示例,你可以这样去设置自定义的 Less 实现器:

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              implementation: require('less'),
            },
          },
        ],
      },
    ],
  },
};

示例

常规用法

less-loadercss-loaderstyle-loader 串联起来使用可立即将所有样式应用于 DOM。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          {
            loader: 'style-loader', // 从 JS 中创建样式节点
          },
          {
            loader: 'css-loader', // 转化 CSS 为 CommonJS
          },
          {
            loader: 'less-loader', // 编译 Less 为 CSS
          },
        ],
      },
    ],
  },
};

不幸的是,Less 并没有将所有选项 1 对 1 映射为 camelCase(驼峰值)。如有疑问,请[检查执行文件](https://github.com/less/less.js/blob/3.x/bin/lessc)并搜索破折号选项。

Source maps

为了生成 CSS 的 source map, 你需要在 loader 的可选项中设置 sourceMap 属性。如果没设置的话 loader 将会继承你 webpack 中为生成 source map 设置的属性值 devtool

webpack.config.js

module.exports = {
  devtool: 'source-map', // 任何类似于 "source-map" 的  devtool 值都可以
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'less-loader',
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

如果你想在 Chrome 中修改原始的 Less 文件,可以参考这篇不错的博客。这篇博客虽然写的 Sass,但也适合于 Less。

生产环境

在生产环境中推荐使用 MiniCssExtractPlugin 来提取样式表到专门的文件中,这样你的样式就不需要依赖 JavaScript。

导入

less-loader v4 版本起,你有两种解析器可用,Less 内置解析器和 webpack 解析器。默认情况使用 webpack 解析器。

webpack 解析器

webpack 提供了一种 解析文件的高级机制less-loader 作为 Less 的插件,该插件将所有的查询结果传递给 webpack 解析器,因此你可以从 node_modules 中导入 Less 模块,只需要在它们前面加上 ~ 符号告诉 webpack 从 modules 中去查找。

@import '~bootstrap/less/bootstrap';

在其前面加上 很关键,因为 〜/ 会解析到根目录。webpack 需要区分 bootstrap〜bootstrap,因为 CSS 和 Less 文件没有用于导入相对路径文件的特殊语法。写 @import“ file” 等同于 @import“ ./file”;

非 Less 导入

使用 webpack 解析器,您可以导入任何文件类型。你只需要一个导出有效的 Less 代码的 loader。通常,您还需要设置 issuer 条件,以确保此规则仅适用于源自 Less 文件的导入:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        issuer: /\.less$/,
        use: [
          {
            loader: 'js-to-less-loader',
          },
        ],
      },
    ],
  },
};

Less 解析器

如果指定 paths 选项,将从指定的 paths 中搜索模块,这是 Less 的默认行为。paths 应该是具有绝对路径的数组。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                paths: [path.resolve(__dirname, 'node_modules')],
              },
            },
          },
        ],
      },
    ],
  },
};

插件

想要使用 插件,只需要简单设置下 plugins 选项就可以, 配置如下:

// webpack.config.js
const CleanCSSPlugin = require('less-plugin-clean-css');

module.exports = {
  ...
    {
      loader: 'less-loader',
      options: {
        lessOptions: {
          plugins: [
            new CleanCSSPlugin({ advanced: true }),
          ],
        },
      },
    },
  ...
};

提取样式表

通过 webpack 打包 CSS 有很多好处,比如给引用图片和字体文件路径添加 hash, 在开发环境可以 模块热替换。另一方面,在生产环境,根据 JS 来控制应用样式表不是一个好的方式,可能会导致延迟渲染,甚至可能会出现闪烁现象。因此,在你最终的生产环境中将它们拆分成单独的文件来存放通常是比较好的选择。

有两种从 bundle 中提取样式表的方式:

CSS modules 陷阱

Less 和 CSS modules 有一个已知的问题,关于 url(...) 语句中的相对文件路径,看下这个问题的解释

贡献

如果你还没有看过我们的贡献者指南请先花点时间看一下。

CONTRIBUTING

许可

MIT