UNPKG

15.7 kBMarkdownView Raw
1<div align="center">
2 <a href="https://github.com/webpack/webpack">
3 <img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
4 </a>
5</div>
6
7[![npm][npm]][npm-url]
8[![node][node]][node-url]
9[![tests][tests]][tests-url]
10[![cover][cover]][cover-url]
11[![discussion][discussion]][discussion-url]
12[![size][size]][size-url]
13
14# less-loader
15
16A Less loader for webpack. Compiles Less to CSS.
17
18## Getting Started
19
20To begin, you'll need to install `less` and `less-loader`:
21
22```console
23npm install less less-loader --save-dev
24```
25
26or
27
28```console
29yarn add -D less less-loader
30```
31
32or
33
34```console
35pnpm add -D less less-loader
36```
37
38Then add the loader to your `webpack` config. For example:
39
40**webpack.config.js**
41
42```js
43module.exports = {
44 module: {
45 rules: [
46 {
47 test: /\.less$/i,
48 use: [
49 // compiles Less to CSS
50 "style-loader",
51 "css-loader",
52 "less-loader",
53 ],
54 },
55 ],
56 },
57};
58```
59
60And run `webpack` via your preferred method.
61
62## Options
63
64- **[`lessOptions`](#lessoptions)**
65- **[`additionalData`](#additionalData)**
66- **[`sourceMap`](#sourcemap)**
67- **[`webpackImporter`](#webpackimporter)**
68- **[`implementation`](#implementation)**
69
70### `lessOptions`
71
72Type:
73
74```ts
75type lessOptions = import('less').options | ((loaderContext: LoaderContext) => import('less').options})
76```
77
78Default: `{ relativeUrls: true }`
79
80You can pass any Less specific options to the `less-loader` through the `lessOptions` property in the [loader options](https://webpack.js.org/configuration/module/#rule-options-rule-query). See the [Less documentation](http://lesscss.org/usage/#command-line-usage-options) for all available options in dash-case. Since we're passing these options to Less programmatically, you need to pass them in camelCase here:
81
82#### `object`
83
84Use an object to pass options through to Less.
85
86**webpack.config.js**
87
88```js
89module.exports = {
90 module: {
91 rules: [
92 {
93 test: /\.less$/i,
94 use: [
95 {
96 loader: "style-loader",
97 },
98 {
99 loader: "css-loader",
100 },
101 {
102 loader: "less-loader",
103 options: {
104 lessOptions: {
105 strictMath: true,
106 },
107 },
108 },
109 ],
110 },
111 ],
112 },
113};
114```
115
116#### `function`
117
118Allows setting the options passed through to Less based off of the loader context.
119
120```js
121module.exports = {
122 module: {
123 rules: [
124 {
125 test: /\.less$/i,
126 use: [
127 "style-loader",
128 "css-loader",
129 {
130 loader: "less-loader",
131 options: {
132 lessOptions: (loaderContext) => {
133 // More information about available properties https://webpack.js.org/api/loaders/
134 const { resourcePath, rootContext } = loaderContext;
135 const relativePath = path.relative(rootContext, resourcePath);
136
137 if (relativePath === "styles/foo.less") {
138 return {
139 paths: ["absolute/path/c", "absolute/path/d"],
140 };
141 }
142
143 return {
144 paths: ["absolute/path/a", "absolute/path/b"],
145 };
146 },
147 },
148 },
149 ],
150 },
151 ],
152 },
153};
154```
155
156### `additionalData`
157
158Type:
159
160```ts
161type additionalData =
162 | string
163 | ((content: string, loaderContext: LoaderContext) => string);
164```
165
166Default: `undefined`
167
168Prepends/Appends `Less` code to the actual entry file.
169In this case, the `less-loader` will not override the source but just **prepend** the entry's content.
170
171This is especially useful when some of your Less variables depend on the environment:
172
173> Since you're injecting code, this will break the source mappings in your entry file. Often there's a simpler solution than this, like multiple Less entry files.
174
175#### `string`
176
177```js
178module.exports = {
179 module: {
180 rules: [
181 {
182 test: /\.less$/i,
183 use: [
184 "style-loader",
185 "css-loader",
186 {
187 loader: "less-loader",
188 options: {
189 additionalData: `@env: ${process.env.NODE_ENV};`,
190 },
191 },
192 ],
193 },
194 ],
195 },
196};
197```
198
199#### `function`
200
201##### `Sync`
202
203```js
204module.exports = {
205 module: {
206 rules: [
207 {
208 test: /\.less$/i,
209 use: [
210 "style-loader",
211 "css-loader",
212 {
213 loader: "less-loader",
214 options: {
215 additionalData: (content, loaderContext) => {
216 // More information about available properties https://webpack.js.org/api/loaders/
217 const { resourcePath, rootContext } = loaderContext;
218 const relativePath = path.relative(rootContext, resourcePath);
219
220 if (relativePath === "styles/foo.less") {
221 return "@value: 100px;" + content;
222 }
223
224 return "@value: 200px;" + content;
225 },
226 },
227 },
228 ],
229 },
230 ],
231 },
232};
233```
234
235##### `Async`
236
237```js
238module.exports = {
239 module: {
240 rules: [
241 {
242 test: /\.less$/i,
243 use: [
244 "style-loader",
245 "css-loader",
246 {
247 loader: "less-loader",
248 options: {
249 additionalData: async (content, loaderContext) => {
250 // More information about available properties https://webpack.js.org/api/loaders/
251 const { resourcePath, rootContext } = loaderContext;
252 const relativePath = path.relative(rootContext, resourcePath);
253
254 if (relativePath === "styles/foo.less") {
255 return "@value: 100px;" + content;
256 }
257
258 return "@value: 200px;" + content;
259 },
260 },
261 },
262 ],
263 },
264 ],
265 },
266};
267```
268
269### `sourceMap`
270
271Type:
272
273```ts
274type sourceMap = boolean;
275```
276
277Default: depends on the `compiler.devtool` value
278
279By default generation of source maps depends on the [`devtool`](https://webpack.js.org/configuration/devtool/) option. All values enable source map generation except `eval` and `false` value.
280
281**webpack.config.js**
282
283```js
284module.exports = {
285 module: {
286 rules: [
287 {
288 test: /\.less$/i,
289 use: [
290 "style-loader",
291 {
292 loader: "css-loader",
293 options: {
294 sourceMap: true,
295 },
296 },
297 {
298 loader: "less-loader",
299 options: {
300 sourceMap: true,
301 },
302 },
303 ],
304 },
305 ],
306 },
307};
308```
309
310### `webpackImporter`
311
312Type:
313
314```ts
315type webpackImporter = boolean;
316```
317
318Default: `true`
319
320Enables/Disables the default `webpack` importer.
321
322This can improve performance in some cases. Use it with caution because aliases and `@import` from [`node_modules`](https://webpack.js.org/configuration/resolve/#resolvemodules) will not work.
323
324**webpack.config.js**
325
326```js
327module.exports = {
328 module: {
329 rules: [
330 {
331 test: /\.less$/i,
332 use: [
333 "style-loader",
334 "css-loader",
335 {
336 loader: "less-loader",
337 options: {
338 webpackImporter: false,
339 },
340 },
341 ],
342 },
343 ],
344 },
345};
346```
347
348### `implementation`
349
350Type:
351
352```ts
353type implementation = object | string;
354```
355
356> less-loader compatible with Less 3 and 4 versions
357
358The special `implementation` option determines which implementation of Less to use. Overrides the locally installed `peerDependency` version of `less`.
359
360**This option is only really useful for downstream tooling authors to ease the Less 3-to-4 transition.**
361
362#### `object`
363
364**webpack.config.js**
365
366```js
367module.exports = {
368 module: {
369 rules: [
370 {
371 test: /\.less$/i,
372 use: [
373 "style-loader",
374 "css-loader",
375 {
376 loader: "less-loader",
377 options: {
378 implementation: require("less"),
379 },
380 },
381 ],
382 },
383 ],
384 },
385};
386```
387
388#### `string`
389
390**webpack.config.js**
391
392```js
393module.exports = {
394 module: {
395 rules: [
396 {
397 test: /\.less$/i,
398 use: [
399 "style-loader",
400 "css-loader",
401 {
402 loader: "less-loader",
403 options: {
404 implementation: require.resolve("less"),
405 },
406 },
407 ],
408 },
409 ],
410 },
411};
412```
413
414## Examples
415
416### Normal usage
417
418Chain the `less-loader` with the [`css-loader`](https://github.com/webpack-contrib/css-loader) and the [`style-loader`](https://github.com/webpack-contrib/style-loader) to immediately apply all styles to the DOM.
419
420**webpack.config.js**
421
422```js
423module.exports = {
424 module: {
425 rules: [
426 {
427 test: /\.less$/i,
428 use: [
429 {
430 loader: "style-loader", // creates style nodes from JS strings
431 },
432 {
433 loader: "css-loader", // translates CSS into CommonJS
434 },
435 {
436 loader: "less-loader", // compiles Less to CSS
437 },
438 ],
439 },
440 ],
441 },
442};
443```
444
445Unfortunately, Less doesn't map all options 1-by-1 to camelCase. When in doubt, [check their executable](https://github.com/less/less.js/blob/3.x/bin/lessc) and search for the dash-case option.
446
447### Source maps
448
449To enable sourcemaps for CSS, you'll need to pass the `sourceMap` property in the loader's options. If this is not passed, the loader will respect the setting for webpack source maps, set in `devtool`.
450
451**webpack.config.js**
452
453```js
454module.exports = {
455 devtool: "source-map", // any "source-map"-like devtool is possible
456 module: {
457 rules: [
458 {
459 test: /\.less$/i,
460 use: [
461 "style-loader",
462 {
463 loader: "css-loader",
464 options: {
465 sourceMap: true,
466 },
467 },
468 {
469 loader: "less-loader",
470 options: {
471 sourceMap: true,
472 },
473 },
474 ],
475 },
476 ],
477 },
478};
479```
480
481If you want to edit the original Less files inside Chrome, [there's a good blog post](https://medium.com/@toolmantim/getting-started-with-css-sourcemaps-and-in-browser-sass-editing-b4daab987fb0). The blog post is about Sass but it also works for Less.
482
483### In production
484
485Usually, it's recommended to extract the style sheets into a dedicated file in production using the [MiniCssExtractPlugin](https://github.com/webpack-contrib/mini-css-extract-plugin). This way your styles are not dependent on JavaScript.
486
487### Imports
488
489First we try to use built-in `less` resolve logic, then `webpack` resolve logic.
490
491#### Webpack Resolver
492
493`webpack` provides an [advanced mechanism to resolve files](https://webpack.js.org/configuration/resolve/).
494`less-loader` applies a Less plugin that passes all queries to the webpack resolver if `less` could not resolve `@import`.
495Thus you can import your Less modules from `node_modules`.
496
497```css
498@import "bootstrap/less/bootstrap";
499```
500
501Using `~` is deprecated and can be removed from your code (**we recommend it**), but we still support it for historical reasons.
502Why you can removed it? The loader will first try to resolve `@import` as relative, if it cannot be resolved, the loader will try to resolve `@import` inside [`node_modules`](https://webpack.js.org/configuration/resolve/#resolvemodules).
503
504Default resolver options can be modified by [`resolve.byDependency`](https://webpack.js.org/configuration/resolve/#resolvebydependency):
505
506**webpack.config.js**
507
508```js
509module.exports = {
510 devtool: "source-map", // any "source-map"-like devtool is possible
511 module: {
512 rules: [
513 {
514 test: /\.less$/i,
515 use: ["style-loader", "css-loader", "less-loader"],
516 },
517 ],
518 },
519 resolve: {
520 byDependency: {
521 // More options can be found here https://webpack.js.org/configuration/resolve/
522 less: {
523 mainFiles: ["custom"],
524 },
525 },
526 },
527};
528```
529
530#### Less Resolver
531
532If you specify the `paths` option, modules will be searched in the given `paths`. This is `less` default behavior. `paths` should be an array with absolute paths:
533
534**webpack.config.js**
535
536```js
537module.exports = {
538 module: {
539 rules: [
540 {
541 test: /\.less$/i,
542 use: [
543 {
544 loader: "style-loader",
545 },
546 {
547 loader: "css-loader",
548 },
549 {
550 loader: "less-loader",
551 options: {
552 lessOptions: {
553 paths: [path.resolve(__dirname, "node_modules")],
554 },
555 },
556 },
557 ],
558 },
559 ],
560 },
561};
562```
563
564### Plugins
565
566In order to use [plugins](http://lesscss.org/usage/#plugins), simply set the `plugins` option like this:
567
568**webpack.config.js**
569
570```js
571const CleanCSSPlugin = require('less-plugin-clean-css');
572
573module.exports = {
574 ...
575 {
576 loader: 'less-loader',
577 options: {
578 lessOptions: {
579 plugins: [
580 new CleanCSSPlugin({ advanced: true }),
581 ],
582 },
583 },
584 },
585 ...
586};
587```
588
589> **Note**
590>
591> Access to the [loader context](https://webpack.js.org/api/loaders/#the-loader-context) inside the custom plugin can be done using the `pluginManager.webpackLoaderContext` property.
592
593```js
594module.exports = {
595 install: function (less, pluginManager, functions) {
596 functions.add("pi", function () {
597 // Loader context is available in `pluginManager.webpackLoaderContext`
598
599 return Math.PI;
600 });
601 },
602};
603```
604
605### Extracting style sheets
606
607Bundling CSS with webpack has some nice advantages like referencing images and fonts with hashed urls or [hot module replacement](https://webpack.js.org/concepts/hot-module-replacement/) in development. In production, on the other hand, it's not a good idea to apply your style sheets depending on JS execution. Rendering may be delayed or even a [FOUC](https://en.wikipedia.org/wiki/Flash_of_unstyled_content) might be visible. Thus it's often still better to have them as separate files in your final production build.
608
609There are two possibilities to extract a style sheet from the bundle:
610
611- [`extract-loader`](https://github.com/peerigon/extract-loader) (simpler, but specialized on the css-loader's output)
612- [`MiniCssExtractPlugin`](https://github.com/webpack-contrib/mini-css-extract-plugin) (more complex, but works in all use-cases)
613
614### CSS modules gotcha
615
616There is a known problem with Less and [CSS modules](https://github.com/css-modules/css-modules) regarding relative file paths in `url(...)` statements. [See this issue for an explanation](https://github.com/webpack-contrib/less-loader/issues/109#issuecomment-253797335).
617
618## Contributing
619
620Please take a moment to read our contributing guidelines if you haven't yet done so.
621
622[CONTRIBUTING](./.github/CONTRIBUTING.md)
623
624## License
625
626[MIT](./LICENSE)
627
628[npm]: https://img.shields.io/npm/v/less-loader.svg
629[npm-url]: https://npmjs.com/package/less-loader
630[node]: https://img.shields.io/node/v/less-loader.svg
631[node-url]: https://nodejs.org
632[tests]: https://github.com/webpack-contrib/less-loader/workflows/less-loader/badge.svg
633[tests-url]: https://github.com/webpack-contrib/less-loader/actions
634[cover]: https://codecov.io/gh/webpack-contrib/less-loader/branch/master/graph/badge.svg
635[cover-url]: https://codecov.io/gh/webpack-contrib/less-loader
636[discussion]: https://img.shields.io/github/discussions/webpack/webpack
637[discussion-url]: https://github.com/webpack/webpack/discussions
638[size]: https://packagephobia.now.sh/badge?p=less-loader
639[size-url]: https://packagephobia.now.sh/result?p=less-loader