less-loader

免责声明 less-loader是一个由社区成员维护的第三方包,它可能不具备与 webpack 相同的支持、安全策略或许可证,并且不受 webpack 维护。

npm node tests cover discussion size

webpack 的 Less 加载器,用于将 Less 文件编译为 CSS。

入门

首先,你需要安装 lessless-loader

npm install less less-loader --save-dev

yarn add -D less less-loader

pnpm add -D less less-loader

然后将加载器添加到你的 webpack 配置中。例如:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          // compiles Less to CSS
          "style-loader",
          "css-loader",
          "less-loader",
        ],
      },
    ],
  },
};

最后,使用你通常使用的方法运行 webpack(例如,通过 CLI 或 npm 脚本)。

选项

lessOptions

类型

type lessOptions = import('less').options | ((loaderContext: LoaderContext) => import('less').options})

默认值: { relativeUrls: true }

你可以通过加载器选项中的 lessOptions 属性,向 less-loader 传递任何 Less 特定的选项。有关所有可用(以连字符分隔命名)的选项,请参阅 Less 文档

由于我们是以编程方式将这些选项传递给 Less,因此你需要在此处使用驼峰命名法。

object

使用一个对象直接将选项传递给 Less。

webpack.config.js

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

function

允许根据加载器上下文动态设置 Less 选项。

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "less-loader",
            options: {
              lessOptions: (loaderContext) => {
                // More information about available properties https://webpack.js.cn/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"],
                };
              },
            },
          },
        ],
      },
    ],
  },
};

additionalData

类型

type additionalData =
  | string
  | ((content: string, loaderContext: LoaderContext) => string);

默认值:undefined

在实际入口文件前或后附加 Less 代码。在这种情况下,less-loader 不会覆盖源文件,而只是在入口内容前 附加

当你的某些 Less 变量依赖于环境时,这尤其有用。

由于你正在注入代码,这会破坏你入口文件中的源映射。通常有比这更简单的解决方案,例如多个 Less 入口文件。

string

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

function

Sync
module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "less-loader",
            options: {
              additionalData: (content, loaderContext) => {
                // More information about available properties https://webpack.js.cn/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

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

                return "@value: 200px;" + content;
              },
            },
          },
        ],
      },
    ],
  },
};
Async
module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "less-loader",
            options: {
              additionalData: async (content, loaderContext) => {
                // More information about available properties https://webpack.js.cn/api/loaders/
                const { resourcePath, rootContext } = loaderContext;
                const relativePath = path.relative(rootContext, resourcePath);

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

                return "@value: 200px;" + content;
              },
            },
          },
        ],
      },
    ],
  },
};

sourceMap

类型

type sourceMap = boolean;

默认值:取决于 compiler.devtool 的值

默认情况下,源映射的生成取决于 devtool 选项。除了 evalfalse 值之外,所有值都启用源映射生成。

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,
            },
          },
        ],
      },
    ],
  },
};

webpackImporter

类型

type webpackImporter = boolean | "only";

默认值:true

启用或禁用默认的 webpack 导入器。

这在某些情况下可以提高性能。请谨慎使用,因为别名和从 node_modules 导入的 @import 将不起作用。

webpack.config.js

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

implementation

类型

type implementation = object | string;

less-loader 兼容 Less 3 和 Less 4 版本

特殊的 implementation 选项决定使用哪个 Less 实现。它会覆盖本地安装的 Less peerDependency 版本。

此选项仅对下游工具作者有用,可简化 Less 3 到 4 的过渡。

object

使用 Less 实例的示例

webpack.config.js

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

string

使用已解析的 Less 模块路径的示例

webpack.config.js

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

lessLogAsWarnOrErr

类型

type lessLogAsWarnOrErr = boolean;

默认值:false

Less 警告和错误将被视为 webpack 警告和错误,而不是静默记录。

warning.less

div {
  &:extend(.body1);
}

如果 lessLogAsWarnOrErr 设置为 false,它将只是一条日志,webpack 将成功编译;但如果将此选项设置为 true,webpack 将因警告(或错误)而编译失败,并且如果配置得当,可能会中断构建。

webpack.config.js

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

示例

普通用法

less-loadercss-loaderstyle-loader 链式调用,以立即将所有样式应用于 DOM。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          {
            loader: "style-loader", // Creates style nodes from JS strings
          },
          {
            loader: "css-loader", // Translates CSS into CommonJS
          },
          {
            loader: "less-loader", // Compiles Less to CSS
          },
        ],
      },
    ],
  },
};

遗憾的是,Less 并非所有选项都一对一地映射到驼峰命名法。如有疑问,请检查其可执行文件并搜索连字符分隔的选项。

源映射

要为 CSS 启用源映射,您需要在加载器选项中传递 sourceMap 属性。如果未传递此属性,加载器将遵循 devtool 中设置的 webpack 源映射设置。

webpack.config.js

module.exports = {
  devtool: "source-map", // any "source-map"-like devtool is possible
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              sourceMap: true,
            },
          },
          {
            loader: "less-loader",
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

如果你想在 Chrome 中编辑原始 Less 文件,有一篇不错的博客文章。这篇博客文章是关于 Sass 的,但它也适用于 Less。

生产环境

通常,建议在生产环境中使用 MiniCssExtractPlugin 将样式表提取到专用文件中。这样,你的样式就不依赖于 JavaScript,从而提高了性能和可缓存性。

导入

我们首先尝试使用 Less 内置的解析逻辑,然后是 webpack 的解析逻辑。

Webpack 解析器

webpack 提供了一种高级的文件解析机制。如果 Less 无法解析 @importless-loader 会应用一个 Less 插件,将所有查询传递给 webpack 解析器。因此,你可以从 node_modules 导入 Less 模块。

@import "bootstrap/less/bootstrap";

使用 ~ 前缀(例如,@import "~bootstrap/less/bootstrap";)已弃用,并且可以从你的代码中删除(我们推荐这样做),但出于历史原因我们仍支持它。为什么可以删除它?加载器会首先尝试将 @import 解析为相对路径,如果无法解析,加载器将尝试在 node_modules 中解析 @import

默认解析器选项可以通过 resolve.byDependency 进行修改。

webpack.config.js

module.exports = {
  devtool: "source-map", // any "source-map"-like devtool is possible
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: ["style-loader", "css-loader", "less-loader"],
      },
    ],
  },
  resolve: {
    byDependency: {
      // More options can be found here https://webpack.js.cn/configuration/resolve/
      less: {
        mainFiles: ["custom"],
      },
    },
  },
};

Less 解析器

如果你指定 paths 选项,模块将在给定路径中搜索。这是 Less 的默认行为。paths 应该是一个包含绝对路径的数组。

webpack.config.js

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

插件

为了使用Less 插件,只需像这样设置 plugins 选项即可:

webpack.config.js

const CleanCSSPlugin = require('less-plugin-clean-css');

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

[!注意]

在自定义插件中访问加载器上下文可以通过 pluginManager.webpackLoaderContext 属性完成。

module.exports = {
  install: function (less, pluginManager, functions) {
    functions.add("pi", function () {
      // Loader context is available in `pluginManager.webpackLoaderContext`

      return Math.PI;
    });
  },
};

提取样式表

使用 webpack 打包 CSS 具有一些优势,例如在开发环境中引用带有哈希 URL 的图像和字体,或实现热模块替换(HMR)。

另一方面,在生产环境中,依赖 JS 执行来应用样式表不是一个好主意。渲染可能会延迟,甚至可能出现无样式内容闪烁(FOUC)的情况。因此,在最终的生产构建中将它们作为单独的文件通常仍然更好。

有两种方法可以从捆绑包中提取样式表

CSS 模块陷阱

在使用 Less 和 CSS 模块时,关于 url(...) 语句中的相对文件路径存在一个已知问题。请参阅此问题以获取解释

贡献

我们欢迎所有贡献!如果您是新用户,请在提交问题或拉取请求之前花一些时间阅读我们的贡献指南。

贡献指南

许可证

MIT