0
# Less Loader
1
2
Less 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.
3
4
## Package Information
5
6
- **Package Name**: less-loader
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install less less-loader --save-dev`
10
11
## Core Imports
12
13
The less-loader is used as a webpack loader in configuration, not imported directly:
14
15
```javascript
16
// webpack.config.js
17
module.exports = {
18
module: {
19
rules: [{
20
test: /\.less$/i,
21
use: ['style-loader', 'css-loader', 'less-loader']
22
}]
23
}
24
};
25
```
26
27
For advanced use with TypeScript types:
28
29
```typescript
30
import type { LoaderContext } from 'webpack';
31
```
32
33
## Basic Usage
34
35
**Basic webpack configuration:**
36
37
```javascript
38
// webpack.config.js
39
module.exports = {
40
module: {
41
rules: [{
42
test: /\.less$/i,
43
use: [
44
'style-loader',
45
'css-loader',
46
'less-loader'
47
]
48
}]
49
}
50
};
51
```
52
53
**With options:**
54
55
```javascript
56
// webpack.config.js
57
module.exports = {
58
module: {
59
rules: [{
60
test: /\.less$/i,
61
use: [
62
'style-loader',
63
'css-loader',
64
{
65
loader: 'less-loader',
66
options: {
67
lessOptions: {
68
strictMath: true,
69
noIeCompat: true
70
},
71
additionalData: '@primary-color: #1890ff;',
72
sourceMap: true
73
}
74
}
75
]
76
}]
77
}
78
};
79
```
80
81
## Architecture
82
83
Less Loader integrates Less CSS compilation into webpack's module system through several key components:
84
85
- **Loader Function**: Main webpack loader that processes Less files and returns compiled CSS
86
- **Webpack File Manager**: Custom Less plugin that enables webpack-style import resolution
87
- **Options Processing**: Configuration normalization and Less options management
88
- **Source Map Integration**: Webpack-compatible source map generation and processing
89
- **Error Handling**: Enhanced error formatting with file context and webpack integration
90
91
## Capabilities
92
93
### Loader Configuration
94
95
Configure less-loader behavior through webpack loader options.
96
97
```typescript { .api }
98
interface LoaderOptions {
99
lessOptions?: LessOptions | ((loaderContext: LoaderContext) => LessOptions);
100
additionalData?: string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);
101
sourceMap?: boolean;
102
webpackImporter?: boolean | "only";
103
implementation?: string | object;
104
lessLogAsWarnOrErr?: boolean;
105
}
106
```
107
108
### Less Options Configuration
109
110
Control Less compilation behavior through lessOptions.
111
112
```typescript { .api }
113
interface LessOptions {
114
paths?: string[];
115
filename?: string;
116
plugins?: LessPlugin[];
117
strictImports?: boolean;
118
strictMath?: boolean;
119
strictUnits?: boolean;
120
compress?: boolean;
121
sourceMap?: object;
122
javascriptEnabled?: boolean;
123
[key: string]: any;
124
}
125
```
126
127
**Usage Examples:**
128
129
```javascript
130
// Object configuration
131
{
132
loader: 'less-loader',
133
options: {
134
lessOptions: {
135
strictMath: true,
136
paths: [path.resolve(__dirname, 'styles')],
137
plugins: [new LessPluginCleanCSS({ advanced: true })]
138
}
139
}
140
}
141
142
// Function configuration for dynamic options
143
{
144
loader: 'less-loader',
145
options: {
146
lessOptions: (loaderContext) => {
147
const { resourcePath, rootContext } = loaderContext;
148
const relativePath = path.relative(rootContext, resourcePath);
149
150
if (relativePath.startsWith('theme/')) {
151
return {
152
modifyVars: {
153
'@primary-color': '#1890ff',
154
'@border-radius-base': '6px'
155
}
156
};
157
}
158
159
return { strictMath: true };
160
}
161
}
162
}
163
```
164
165
### Additional Data Injection
166
167
Prepend or append Less code to entry files.
168
169
```typescript { .api }
170
type AdditionalData = string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);
171
```
172
173
**Usage Examples:**
174
175
```javascript
176
// String injection
177
{
178
loader: 'less-loader',
179
options: {
180
additionalData: '@env: production; @primary-color: #1890ff;'
181
}
182
}
183
184
// Synchronous function injection
185
{
186
loader: 'less-loader',
187
options: {
188
additionalData: (content, loaderContext) => {
189
const { resourcePath } = loaderContext;
190
if (resourcePath.includes('variables')) {
191
return '@theme: dark;\n' + content;
192
}
193
return '@theme: light;\n' + content;
194
}
195
}
196
}
197
198
// Asynchronous function injection
199
{
200
loader: 'less-loader',
201
options: {
202
additionalData: async (content, loaderContext) => {
203
const config = await loadThemeConfig();
204
return `@theme-vars: ${JSON.stringify(config)};\n${content}`;
205
}
206
}
207
}
208
```
209
210
### Source Map Control
211
212
Enable or disable source map generation.
213
214
```typescript { .api }
215
type SourceMapOption = boolean;
216
```
217
218
**Usage Examples:**
219
220
```javascript
221
// Explicit source map control
222
{
223
loader: 'less-loader',
224
options: {
225
sourceMap: true // Force enable regardless of devtool setting
226
}
227
}
228
229
// Source maps follow webpack devtool setting (default behavior)
230
{
231
loader: 'less-loader'
232
// sourceMap option omitted - follows webpack devtool configuration
233
}
234
```
235
236
### Webpack Import Resolution
237
238
Control webpack-style import resolution behavior.
239
240
```typescript { .api }
241
type WebpackImporter = boolean | "only";
242
```
243
244
**Usage Examples:**
245
246
```javascript
247
// Default webpack importer (recommended)
248
{
249
loader: 'less-loader'
250
// webpackImporter: true (default)
251
}
252
253
// Disable webpack importer for performance
254
{
255
loader: 'less-loader',
256
options: {
257
webpackImporter: false // Use only Less native resolution
258
}
259
}
260
261
// Use only webpack importer
262
{
263
loader: 'less-loader',
264
options: {
265
webpackImporter: "only" // Force webpack resolution only
266
}
267
}
268
```
269
270
### Less Implementation Override
271
272
Specify custom Less implementation.
273
274
```typescript { .api }
275
type Implementation = string | object;
276
```
277
278
**Usage Examples:**
279
280
```javascript
281
// Use specific Less version by package name
282
{
283
loader: 'less-loader',
284
options: {
285
implementation: 'less' // Package name
286
}
287
}
288
289
// Use specific Less version by require
290
{
291
loader: 'less-loader',
292
options: {
293
implementation: require('less') // Direct object reference
294
}
295
}
296
297
// Use Less implementation by resolve path
298
{
299
loader: 'less-loader',
300
options: {
301
implementation: require.resolve('less') // Resolved path
302
}
303
}
304
```
305
306
### Enhanced Error Handling
307
308
Control how Less warnings and errors are handled.
309
310
```typescript { .api }
311
type LessLogAsWarnOrErr = boolean;
312
```
313
314
**Usage Examples:**
315
316
```javascript
317
// Default behavior - Less errors as logs
318
{
319
loader: 'less-loader'
320
// lessLogAsWarnOrErr: false (default)
321
}
322
323
// Enhanced error handling - Less errors as webpack errors
324
{
325
loader: 'less-loader',
326
options: {
327
lessLogAsWarnOrErr: true // Convert Less logs to webpack warnings/errors
328
}
329
}
330
```
331
332
## Types
333
334
```typescript { .api }
335
interface LoaderContext {
336
resourcePath: string;
337
rootContext: string;
338
getOptions(): LoaderOptions;
339
async(): (error?: Error | null, content?: string, sourceMap?: object) => void;
340
addDependency(file: string): void;
341
emitError(error: Error): void;
342
emitWarning(error: Error): void;
343
sourceMap: boolean;
344
getResolve(options?: object): (context: string, request: string) => Promise<string>;
345
getLogger(name: string): WebpackLogger;
346
}
347
348
interface WebpackLogger {
349
error(message: string): void;
350
warn(message: string): void;
351
log(message: string): void;
352
debug(message: string): void;
353
}
354
355
interface LessPlugin {
356
install(less: any, pluginManager: any): void;
357
minVersion?: number[];
358
}
359
360
interface LessOptions {
361
/** Import search paths */
362
paths?: string[];
363
/** Input filename for error reporting */
364
filename?: string;
365
/** Less plugins array */
366
plugins?: LessPlugin[];
367
/** Enforce strict imports */
368
strictImports?: boolean;
369
/** Enforce strict math operations */
370
strictMath?: boolean;
371
/** Enforce strict unit operations */
372
strictUnits?: boolean;
373
/** Enable output compression */
374
compress?: boolean;
375
/** Source map configuration */
376
sourceMap?: object;
377
/** Enable JavaScript evaluation in Less */
378
javascriptEnabled?: boolean;
379
/** Variables to modify */
380
modifyVars?: Record<string, string>;
381
/** Global variables */
382
globalVars?: Record<string, string>;
383
/** Disable Internet Explorer compatibility */
384
noIeCompat?: boolean;
385
/** Math operation mode */
386
math?: 'always' | 'strict' | 'parens-division' | 'parens' | 'strict-legacy';
387
/** Additional Less options */
388
[key: string]: any;
389
}
390
391
interface LoaderOptions {
392
/** Less compilation options */
393
lessOptions?: LessOptions | ((loaderContext: LoaderContext) => LessOptions);
394
/** Additional data to prepend to Less files */
395
additionalData?: string | ((content: string, loaderContext: LoaderContext) => string | Promise<string>);
396
/** Enable source map generation */
397
sourceMap?: boolean;
398
/** Control webpack import resolution */
399
webpackImporter?: boolean | "only";
400
/** Override Less implementation */
401
implementation?: string | object;
402
/** Treat Less logs as webpack warnings/errors */
403
lessLogAsWarnOrErr?: boolean;
404
}
405
```