A Less loader for webpack that compiles Less to CSS with advanced webpack integration features
npx @tessl/cli install tessl/npm-less-loader@12.3.0Less Loader is a webpack loader that compiles Less stylesheets to CSS with comprehensive webpack integration. It provides webpack-specific import resolution, dependency tracking, source map generation, and flexible configuration options for Less compilation within webpack build processes.
npm install less less-loader --save-devThe less-loader is used as a webpack loader in configuration, not imported directly:
// webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.less$/i,
use: ['style-loader', 'css-loader', 'less-loader']
}]
}
};For advanced use with TypeScript types:
import type { LoaderContext } from 'webpack';Basic webpack configuration:
// webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}]
}
};With options:
// webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.less$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
lessOptions: {
strictMath: true,
noIeCompat: true
},
additionalData: '@primary-color: #1890ff;',
sourceMap: true
}
}
]
}]
}
};Less Loader integrates Less CSS compilation into webpack's module system through several key components:
Configure less-loader behavior through webpack loader options.
interface LoaderOptions {
lessOptions?: LessOptions | ((loaderContext: LoaderContext) => LessOptions);
additionalData?: string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);
sourceMap?: boolean;
webpackImporter?: boolean | "only";
implementation?: string | object;
lessLogAsWarnOrErr?: boolean;
}Control Less compilation behavior through lessOptions.
interface LessOptions {
paths?: string[];
filename?: string;
plugins?: LessPlugin[];
strictImports?: boolean;
strictMath?: boolean;
strictUnits?: boolean;
compress?: boolean;
sourceMap?: object;
javascriptEnabled?: boolean;
[key: string]: any;
}Usage Examples:
// Object configuration
{
loader: 'less-loader',
options: {
lessOptions: {
strictMath: true,
paths: [path.resolve(__dirname, 'styles')],
plugins: [new LessPluginCleanCSS({ advanced: true })]
}
}
}
// Function configuration for dynamic options
{
loader: 'less-loader',
options: {
lessOptions: (loaderContext) => {
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (relativePath.startsWith('theme/')) {
return {
modifyVars: {
'@primary-color': '#1890ff',
'@border-radius-base': '6px'
}
};
}
return { strictMath: true };
}
}
}Prepend or append Less code to entry files.
type AdditionalData = string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);Usage Examples:
// String injection
{
loader: 'less-loader',
options: {
additionalData: '@env: production; @primary-color: #1890ff;'
}
}
// Synchronous function injection
{
loader: 'less-loader',
options: {
additionalData: (content, loaderContext) => {
const { resourcePath } = loaderContext;
if (resourcePath.includes('variables')) {
return '@theme: dark;\n' + content;
}
return '@theme: light;\n' + content;
}
}
}
// Asynchronous function injection
{
loader: 'less-loader',
options: {
additionalData: async (content, loaderContext) => {
const config = await loadThemeConfig();
return `@theme-vars: ${JSON.stringify(config)};\n${content}`;
}
}
}Enable or disable source map generation.
type SourceMapOption = boolean;Usage Examples:
// Explicit source map control
{
loader: 'less-loader',
options: {
sourceMap: true // Force enable regardless of devtool setting
}
}
// Source maps follow webpack devtool setting (default behavior)
{
loader: 'less-loader'
// sourceMap option omitted - follows webpack devtool configuration
}Control webpack-style import resolution behavior.
type WebpackImporter = boolean | "only";Usage Examples:
// Default webpack importer (recommended)
{
loader: 'less-loader'
// webpackImporter: true (default)
}
// Disable webpack importer for performance
{
loader: 'less-loader',
options: {
webpackImporter: false // Use only Less native resolution
}
}
// Use only webpack importer
{
loader: 'less-loader',
options: {
webpackImporter: "only" // Force webpack resolution only
}
}Specify custom Less implementation.
type Implementation = string | object;Usage Examples:
// Use specific Less version by package name
{
loader: 'less-loader',
options: {
implementation: 'less' // Package name
}
}
// Use specific Less version by require
{
loader: 'less-loader',
options: {
implementation: require('less') // Direct object reference
}
}
// Use Less implementation by resolve path
{
loader: 'less-loader',
options: {
implementation: require.resolve('less') // Resolved path
}
}Control how Less warnings and errors are handled.
type LessLogAsWarnOrErr = boolean;Usage Examples:
// Default behavior - Less errors as logs
{
loader: 'less-loader'
// lessLogAsWarnOrErr: false (default)
}
// Enhanced error handling - Less errors as webpack errors
{
loader: 'less-loader',
options: {
lessLogAsWarnOrErr: true // Convert Less logs to webpack warnings/errors
}
}interface LoaderContext {
resourcePath: string;
rootContext: string;
getOptions(): LoaderOptions;
async(): (error?: Error | null, content?: string, sourceMap?: object) => void;
addDependency(file: string): void;
emitError(error: Error): void;
emitWarning(error: Error): void;
sourceMap: boolean;
getResolve(options?: object): (context: string, request: string) => Promise<string>;
getLogger(name: string): WebpackLogger;
}
interface WebpackLogger {
error(message: string): void;
warn(message: string): void;
log(message: string): void;
debug(message: string): void;
}
interface LessPlugin {
install(less: any, pluginManager: any): void;
minVersion?: number[];
}
interface LessOptions {
/** Import search paths */
paths?: string[];
/** Input filename for error reporting */
filename?: string;
/** Less plugins array */
plugins?: LessPlugin[];
/** Enforce strict imports */
strictImports?: boolean;
/** Enforce strict math operations */
strictMath?: boolean;
/** Enforce strict unit operations */
strictUnits?: boolean;
/** Enable output compression */
compress?: boolean;
/** Source map configuration */
sourceMap?: object;
/** Enable JavaScript evaluation in Less */
javascriptEnabled?: boolean;
/** Variables to modify */
modifyVars?: Record<string, string>;
/** Global variables */
globalVars?: Record<string, string>;
/** Disable Internet Explorer compatibility */
noIeCompat?: boolean;
/** Math operation mode */
math?: 'always' | 'strict' | 'parens-division' | 'parens' | 'strict-legacy';
/** Additional Less options */
[key: string]: any;
}
interface LoaderOptions {
/** Less compilation options */
lessOptions?: LessOptions | ((loaderContext: LoaderContext) => LessOptions);
/** Additional data to prepend to Less files */
additionalData?: string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);
/** Enable source map generation */
sourceMap?: boolean;
/** Control webpack import resolution */
webpackImporter?: boolean | "only";
/** Override Less implementation */
implementation?: string | object;
/** Treat Less logs as webpack warnings/errors */
lessLogAsWarnOrErr?: boolean;
}