tools.less

  • Type: Object | Function
  • Default:
const defaultOptions = {
  lessLoaderOptions: {
    lessOptions: {
      javascriptEnabled: true,
    },
    // CSS Source Map enabled by default in development environment
    sourceMap: isDev,
  },
};

tools.less modifies the options of @rsbuild/plugin-less. It accepts the full plugin options:

OptionDescription
lessLoaderOptionsOptions passed to less-loader, object or function
includeFiles handled by less-loader, defaults to /\.less$/
excludeFiles that less-loader should skip
parallelWhether to compile Less modules in worker threads, defaults to false

Modifying less-loader options

When lessLoaderOptions is an Object, it is merged with the default config through Object.assign in a shallow way. It should be noted that lessOptions is merged through deepMerge in a deep way. For example:

export default {
  tools: {
    less: {
      lessLoaderOptions: {
        lessOptions: {
          javascriptEnabled: false,
        },
      },
    },
  },
};

When lessLoaderOptions is a Function, the default config is passed as the first parameter, which can be directly modified or returned as the final result. The second parameter provides some utility functions that can be called directly. For example:

export default {
  tools: {
    less: {
      lessLoaderOptions(config) {
        // Modify the config of lessOptions
        config.lessOptions = {
          javascriptEnabled: false,
        };
      },
    },
  },
};

Parallel compilation

Less compilation is pure JavaScript and runs on the Node.js main thread by default. With parallel enabled, Less modules are compiled in a pool of worker threads, which shortens the build when a project has many Less files.

export default {
  tools: {
    less: {
      parallel: true,
    },
  },
};
Tip

Options sent to worker threads must satisfy the structured clone algorithm. With parallel enabled, lessLoaderOptions therefore cannot contain functions, such as an additionalData function or a custom implementation.

Modifying Less Version

In some scenarios, if you need to use a specific version of Less instead of the built-in Less v4 in Modern.js, you can install the desired Less version in your project and set it up using the implementation option of the less-loader.

export default {
  tools: {
    less: {
      lessLoaderOptions: {
        implementation: require('less'),
      },
    },
  },
};

Util Function

addExcludes

  • Type: (excludes: RegExp | RegExp[]) => void

Used to specify which files less-loader does not compile, You can pass in one or more regular expressions to match the path of less files, for example:

export default {
  tools: {
    less: {
      lessLoaderOptions(config, { addExcludes }) {
        addExcludes(/node_modules/);
      },
    },
  },
};

The plugin's exclude option is the recommended equivalent:

export default {
  tools: {
    less: {
      exclude: /node_modules/,
    },
  },
};

Legacy form

Do not mix the two layers

As soon as an object contains a plugin-level key (lessLoaderOptions, include, exclude, ...), the whole object is parsed as plugin options and any loader option in it has no effect. For example, lessOptions in tools.less: { parallel: true, lessOptions: { ... } } is ignored and must be moved under lessLoaderOptions; a hint is printed in development.

In earlier versions, tools.less took the less-loader options directly, e.g. tools.less: { lessOptions: {} } or tools.less(config, { addExcludes }) {}. This form still works: Modern.js wraps it into lessLoaderOptions and produces exactly the same config as before. A migration hint is printed in development, and the legacy form will be removed in the next major version.

// legacy
export default {
  tools: {
    less: {
      lessOptions: { javascriptEnabled: false },
    },
  },
};

// current
export default {
  tools: {
    less: {
      lessLoaderOptions: {
        lessOptions: { javascriptEnabled: false },
      },
    },
  },
};