UNPKG

21.6 kBMarkdownView Raw
1<div align="center">
2 <img height="170"
3 src="https://worldvectorlogo.com/logos/sass-1.svg">
4 <a href="https://github.com/webpack/webpack">
5 <img width="200" height="200"
6 src="https://webpack.js.org/assets/icon-square-big.svg">
7 </a>
8</div>
9
10[![npm][npm]][npm-url]
11[![node][node]][node-url]
12[![deps][deps]][deps-url]
13[![tests][tests]][tests-url]
14[![coverage][cover]][cover-url]
15[![chat][chat]][chat-url]
16[![size][size]][size-url]
17
18# sass-loader
19
20Loads a Sass/SCSS file and compiles it to CSS.
21
22## Getting Started
23
24To begin, you'll need to install `sass-loader`:
25
26```console
27npm install sass-loader sass webpack --save-dev
28```
29
30`sass-loader` requires you to install either [Dart Sass](https://github.com/sass/dart-sass) or [Node Sass](https://github.com/sass/node-sass) on your own (more documentation can be found below).
31
32This allows you to control the versions of all your dependencies, and to choose which Sass implementation to use.
33
34> ℹ️ We highly recommend using [Dart Sass](https://github.com/sass/dart-sass).
35
36> ⚠ [Node Sass](https://github.com/sass/node-sass) does not work with [Yarn PnP](https://classic.yarnpkg.com/en/docs/pnp/) feature and doesn't support [@use rule](https://sass-lang.com/documentation/at-rules/use).
37
38Chain the `sass-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 or the [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) to extract it into a separate file.
39
40Then add the loader to your Webpack configuration. For example:
41
42**app.js**
43
44```js
45import "./style.scss";
46```
47
48**style.scss**
49
50```scss
51$body-color: red;
52
53body {
54 color: $body-color;
55}
56```
57
58**webpack.config.js**
59
60```js
61module.exports = {
62 module: {
63 rules: [
64 {
65 test: /\.s[ac]ss$/i,
66 use: [
67 // Creates `style` nodes from JS strings
68 "style-loader",
69 // Translates CSS into CommonJS
70 "css-loader",
71 // Compiles Sass to CSS
72 "sass-loader",
73 ],
74 },
75 ],
76 },
77};
78```
79
80Finally run `webpack` via your preferred method.
81
82### Resolving `import` at-rules
83
84Webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/concepts/module-resolution/).
85
86The `sass-loader` uses Sass's custom importer feature to pass all queries to the Webpack resolving engine.
87Thus you can import your Sass modules from `node_modules`.
88
89```scss
90@import "bootstrap";
91```
92
93Using `~` is deprecated and can be removed from your code (**we recommend it**), but we still support it for historical reasons.
94Why can you remove it? The loader will first try to resolve `@import` as a relative path. If it cannot be resolved, then the loader will try to resolve `@import` inside [`node_modules`](https://webpack.js.org/configuration/resolve/#resolvemodules).
95
96Prepending module paths with a `~` tells webpack to search through [`node_modules`](https://webpack.js.org/configuration/resolve/#resolvemodules).
97
98```scss
99@import "~bootstrap";
100```
101
102It's important to prepend it with only `~`, because `~/` resolves to the home directory.
103Webpack needs to distinguish between `bootstrap` and `~bootstrap` because CSS and Sass files have no special syntax for importing relative files.
104Writing `@import "style.scss"` is the same as `@import "./style.scss";`
105
106### Problems with `url(...)`
107
108Since Sass implementations don't provide [url rewriting](https://github.com/sass/libsass/issues/532), all linked assets must be relative to the output.
109
110- If you pass the generated CSS on to the `css-loader`, all urls must be relative to the entry-file (e.g. `main.scss`).
111- If you're just generating CSS without passing it to the `css-loader`, it must be relative to your web root.
112
113You will be disrupted by this first issue. It is natural to expect relative references to be resolved against the `.sass`/`.scss` file in which they are specified (like in regular `.css` files).
114
115Thankfully there are a two solutions to this problem:
116
117- Add the missing url rewriting using the [resolve-url-loader](https://github.com/bholloway/resolve-url-loader). Place it before `sass-loader` in the loader chain.
118- Library authors usually provide a variable to modify the asset path. [bootstrap-sass](https://github.com/twbs/bootstrap-sass) for example has an `$icon-font-path`.
119
120## Options
121
122| Name | Type | Default | Description |
123| :-------------------------------------------: | :------------------: | :-------------------------------------: | :---------------------------------------------------------------- |
124| **[`implementation`](#implementation)** | `{Object\|String}` | `sass` | Setup Sass implementation to use. |
125| **[`sassOptions`](#sassoptions)** | `{Object\|Function}` | defaults values for Sass implementation | Options for Sass. |
126| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps. |
127| **[`additionalData`](#additionaldata)** | `{String\|Function}` | `undefined` | Prepends/Appends `Sass`/`SCSS` code before the actual entry file. |
128| **[`webpackImporter`](#webpackimporter)** | `{Boolean}` | `true` | Enables/Disables the default Webpack importer. |
129| **[`warnRuleAsWarning`](#warnruleaswarning)** | `{Boolean}` | `false` | Treats the `@warn` rule as a webpack warning. |
130
131### `implementation`
132
133Type: `Object | String`
134Default: `sass`
135
136The special `implementation` option determines which implementation of Sass to use.
137
138By default the loader resolve the implementation based on your dependencies.
139Just add required implementation to `package.json` (`sass` or `node-sass` package) and install dependencies.
140
141Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementation:
142
143**package.json**
144
145```json
146{
147 "devDependencies": {
148 "sass-loader": "^7.2.0",
149 "sass": "^1.22.10"
150 }
151}
152```
153
154Example where the `sass-loader` loader uses the `node-sass` implementation:
155
156**package.json**
157
158```json
159{
160 "devDependencies": {
161 "sass-loader": "^7.2.0",
162 "node-sass": "^5.0.0"
163 }
164}
165```
166
167Beware the situation when `node-sass` and `sass` were installed! By default the `sass-loader` prefers `sass`.
168In order to avoid this situation you can use the `implementation` option.
169
170The `implementation` options either accepts `sass` (`Dart Sass`) or `node-sass` as a module.
171
172#### Object
173
174For example, to use Dart Sass, you'd pass:
175
176```js
177module.exports = {
178 module: {
179 rules: [
180 {
181 test: /\.s[ac]ss$/i,
182 use: [
183 "style-loader",
184 "css-loader",
185 {
186 loader: "sass-loader",
187 options: {
188 // Prefer `dart-sass`
189 implementation: require("sass"),
190 },
191 },
192 ],
193 },
194 ],
195 },
196};
197```
198
199#### String
200
201For example, to use Dart Sass, you'd pass:
202
203```js
204module.exports = {
205 module: {
206 rules: [
207 {
208 test: /\.s[ac]ss$/i,
209 use: [
210 "style-loader",
211 "css-loader",
212 {
213 loader: "sass-loader",
214 options: {
215 // Prefer `dart-sass`
216 implementation: require.resolve("sass"),
217 },
218 },
219 ],
220 },
221 ],
222 },
223};
224```
225
226Note that when using `sass` (`Dart Sass`), **synchronous compilation is twice as fast as asynchronous compilation** by default, due to the overhead of asynchronous callbacks.
227To avoid this overhead, you can use the [fibers](https://www.npmjs.com/package/fibers) package to call asynchronous importers from the synchronous code path.
228
229We automatically inject the [`fibers`](https://github.com/laverdet/node-fibers) package (setup `sassOptions.fiber`) for `Node.js` less v16.0.0 if is possible (i.e. you need install the [`fibers`](https://github.com/laverdet/node-fibers) package).
230
231> Fibers is not compatible with `Node.js` v16.0.0 or later ([see introduction to readme](https://github.com/laverdet/node-fibers)).
232
233**package.json**
234
235```json
236{
237 "devDependencies": {
238 "sass-loader": "^7.2.0",
239 "sass": "^1.22.10",
240 "fibers": "^4.0.1"
241 }
242}
243```
244
245You can disable automatically injecting the [`fibers`](https://github.com/laverdet/node-fibers) package by passing a `false` value for the `sassOptions.fiber` option.
246
247**webpack.config.js**
248
249```js
250module.exports = {
251 module: {
252 rules: [
253 {
254 test: /\.s[ac]ss$/i,
255 use: [
256 "style-loader",
257 "css-loader",
258 {
259 loader: "sass-loader",
260 options: {
261 implementation: require("sass"),
262 sassOptions: {
263 fiber: false,
264 },
265 },
266 },
267 ],
268 },
269 ],
270 },
271};
272```
273
274You can also pass the `fiber` value using this code:
275
276**webpack.config.js**
277
278```js
279module.exports = {
280 module: {
281 rules: [
282 {
283 test: /\.s[ac]ss$/i,
284 use: [
285 "style-loader",
286 "css-loader",
287 {
288 loader: "sass-loader",
289 options: {
290 implementation: require("sass"),
291 sassOptions: {
292 fiber: require("fibers"),
293 },
294 },
295 },
296 ],
297 },
298 ],
299 },
300};
301```
302
303### `sassOptions`
304
305Type: `Object|Function`
306Default: defaults values for Sass implementation
307
308Options for [Dart Sass](http://sass-lang.com/dart-sass) or [Node Sass](https://github.com/sass/node-sass) implementation.
309
310> ℹ️ The `charset` option has `true` value by default for `dart-sass`, we strongly discourage change value to `false`, because webpack doesn't support files other than `utf-8`.
311
312> ℹ️ The `indentedSyntax` option has `true` value for the `sass` extension.
313
314> ℹ️ Options such as `data` and `file` are unavailable and will be ignored.
315
316> ℹ We strongly discourage change `outFile`, `sourceMapContents`, `sourceMapEmbed`, `sourceMapRoot` options because `sass-loader` automatically sets these options when the `sourceMap` option is `true`.
317
318> ℹ️ Access to the [loader context](https://webpack.js.org/api/loaders/#the-loader-context) inside the custom importer can be done using the `this.webpackLoaderContext` property.
319
320There is a slight difference between the `sass` (`dart-sass`) and `node-sass` options.
321
322Please consult documentation before using them:
323
324- [Dart Sass documentation](https://github.com/sass/dart-sass#javascript-api) for all available `sass` options.
325- [Node Sass documentation](https://github.com/sass/node-sass/#options) for all available `node-sass` options.
326
327#### `Object`
328
329Use and object for the Sass implementation setup.
330
331**webpack.config.js**
332
333```js
334module.exports = {
335 module: {
336 rules: [
337 {
338 test: /\.s[ac]ss$/i,
339 use: [
340 "style-loader",
341 "css-loader",
342 {
343 loader: "sass-loader",
344 options: {
345 sassOptions: {
346 indentWidth: 4,
347 includePaths: ["absolute/path/a", "absolute/path/b"],
348 },
349 },
350 },
351 ],
352 },
353 ],
354 },
355};
356```
357
358#### `Function`
359
360Allows to setup the Sass implementation by setting different options based on the loader context.
361
362```js
363module.exports = {
364 module: {
365 rules: [
366 {
367 test: /\.s[ac]ss$/i,
368 use: [
369 "style-loader",
370 "css-loader",
371 {
372 loader: "sass-loader",
373 options: {
374 sassOptions: (loaderContext) => {
375 // More information about available properties https://webpack.js.org/api/loaders/
376 const { resourcePath, rootContext } = loaderContext;
377 const relativePath = path.relative(rootContext, resourcePath);
378
379 if (relativePath === "styles/foo.scss") {
380 return {
381 includePaths: ["absolute/path/c", "absolute/path/d"],
382 };
383 }
384
385 return {
386 includePaths: ["absolute/path/a", "absolute/path/b"],
387 };
388 },
389 },
390 },
391 ],
392 },
393 ],
394 },
395};
396```
397
398### `sourceMap`
399
400Type: `Boolean`
401Default: depends on the `compiler.devtool` value
402
403Enables/Disables generation of source maps.
404
405By default generation of source maps depends on the [`devtool`](https://webpack.js.org/configuration/devtool/) option.
406All values enable source map generation except `eval` and `false` value.
407
408> ℹ If a `true` the `sourceMap`, `sourceMapRoot`, `sourceMapEmbed`, `sourceMapContents` and `omitSourceMapUrl` from `sassOptions` will be ignored.
409
410**webpack.config.js**
411
412```js
413module.exports = {
414 module: {
415 rules: [
416 {
417 test: /\.s[ac]ss$/i,
418 use: [
419 "style-loader",
420 {
421 loader: "css-loader",
422 options: {
423 sourceMap: true,
424 },
425 },
426 {
427 loader: "sass-loader",
428 options: {
429 sourceMap: true,
430 },
431 },
432 ],
433 },
434 ],
435 },
436};
437```
438
439> ℹ In some rare cases `node-sass` can output invalid source maps (it is a `node-sass` bug).
440
441> > In order to avoid this, you can try to update `node-sass` to latest version or you can try to set within `sassOptions` the `outputStyle` option to `compressed`.
442
443**webpack.config.js**
444
445```js
446module.exports = {
447 module: {
448 rules: [
449 {
450 test: /\.s[ac]ss$/i,
451 use: [
452 "style-loader",
453 "css-loader",
454 {
455 loader: "sass-loader",
456 options: {
457 sourceMap: true,
458 sassOptions: {
459 outputStyle: "compressed",
460 },
461 },
462 },
463 ],
464 },
465 ],
466 },
467};
468```
469
470### `additionalData`
471
472Type: `String|Function`
473Default: `undefined`
474
475Prepends `Sass`/`SCSS` code before the actual entry file.
476In this case, the `sass-loader` will not override the `data` option but just **prepend** the entry's content.
477
478This is especially useful when some of your Sass variables depend on the environment:
479
480#### `String`
481
482```js
483module.exports = {
484 module: {
485 rules: [
486 {
487 test: /\.s[ac]ss$/i,
488 use: [
489 "style-loader",
490 "css-loader",
491 {
492 loader: "sass-loader",
493 options: {
494 additionalData: "$env: " + process.env.NODE_ENV + ";",
495 },
496 },
497 ],
498 },
499 ],
500 },
501};
502```
503
504#### `Function`
505
506##### Sync
507
508```js
509module.exports = {
510 module: {
511 rules: [
512 {
513 test: /\.s[ac]ss$/i,
514 use: [
515 "style-loader",
516 "css-loader",
517 {
518 loader: "sass-loader",
519 options: {
520 additionalData: (content, loaderContext) => {
521 // More information about available properties https://webpack.js.org/api/loaders/
522 const { resourcePath, rootContext } = loaderContext;
523 const relativePath = path.relative(rootContext, resourcePath);
524
525 if (relativePath === "styles/foo.scss") {
526 return "$value: 100px;" + content;
527 }
528
529 return "$value: 200px;" + content;
530 },
531 },
532 },
533 ],
534 },
535 ],
536 },
537};
538```
539
540##### Async
541
542```js
543module.exports = {
544 module: {
545 rules: [
546 {
547 test: /\.s[ac]ss$/i,
548 use: [
549 "style-loader",
550 "css-loader",
551 {
552 loader: "sass-loader",
553 options: {
554 additionalData: async (content, loaderContext) => {
555 // More information about available properties https://webpack.js.org/api/loaders/
556 const { resourcePath, rootContext } = loaderContext;
557 const relativePath = path.relative(rootContext, resourcePath);
558
559 if (relativePath === "styles/foo.scss") {
560 return "$value: 100px;" + content;
561 }
562
563 return "$value: 200px;" + content;
564 },
565 },
566 },
567 ],
568 },
569 ],
570 },
571};
572```
573
574### `webpackImporter`
575
576Type: `Boolean`
577Default: `true`
578
579Enables/Disables the default Webpack importer.
580
581This can improve performance in some cases. Use it with caution because aliases and `@import` at-rules starting with `~` will not work.
582You can pass own `importer` to solve this (see [`importer docs`](https://github.com/sass/node-sass#importer--v200---experimental)).
583
584**webpack.config.js**
585
586```js
587module.exports = {
588 module: {
589 rules: [
590 {
591 test: /\.s[ac]ss$/i,
592 use: [
593 "style-loader",
594 "css-loader",
595 {
596 loader: "sass-loader",
597 options: {
598 webpackImporter: false,
599 },
600 },
601 ],
602 },
603 ],
604 },
605};
606```
607
608### `warnRuleAsWarning`
609
610Type: `Boolean`
611Default: `false`
612
613Treats the `@warn` rule as a webpack warning.
614
615> ℹ️ It will be `true` by default in the next major release.
616
617**style.scss**
618
619```scss
620$known-prefixes: webkit, moz, ms, o;
621
622@mixin prefix($property, $value, $prefixes) {
623 @each $prefix in $prefixes {
624 @if not index($known-prefixes, $prefix) {
625 @warn "Unknown prefix #{$prefix}.";
626 }
627
628 -#{$prefix}-#{$property}: $value;
629 }
630 #{$property}: $value;
631}
632
633.tilt {
634 // Oops, we typo'd "webkit" as "wekbit"!
635 @include prefix(transform, rotate(15deg), wekbit ms);
636}
637```
638
639The presented code will throw webpack warning instead logging.
640
641To ignore unnecessary warnings you can use the [ignoreWarnings](https://webpack.js.org/configuration/other-options/#ignorewarnings) option.
642
643**webpack.config.js**
644
645```js
646module.exports = {
647 module: {
648 rules: [
649 {
650 test: /\.s[ac]ss$/i,
651 use: [
652 "style-loader",
653 "css-loader",
654 {
655 loader: "sass-loader",
656 options: {
657 warnRuleAsWarning: true,
658 },
659 },
660 ],
661 },
662 ],
663 },
664};
665```
666
667## Examples
668
669### Extracts CSS into separate files
670
671For production builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on.
672
673There are two possibilities to extract a style sheet from the bundle:
674
675- [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin)
676- [extract-loader](https://github.com/peerigon/extract-loader) (simpler, but specialized on the css-loader's output)
677
678**webpack.config.js**
679
680```js
681const MiniCssExtractPlugin = require("mini-css-extract-plugin");
682
683module.exports = {
684 module: {
685 rules: [
686 {
687 test: /\.s[ac]ss$/i,
688 use: [
689 // fallback to style-loader in development
690 process.env.NODE_ENV !== "production"
691 ? "style-loader"
692 : MiniCssExtractPlugin.loader,
693 "css-loader",
694 "sass-loader",
695 ],
696 },
697 ],
698 },
699 plugins: [
700 new MiniCssExtractPlugin({
701 // Options similar to the same options in webpackOptions.output
702 // both options are optional
703 filename: "[name].css",
704 chunkFilename: "[id].css",
705 }),
706 ],
707};
708```
709
710### Source maps
711
712Enables/Disables generation of source maps.
713
714To enable CSS source maps, you'll need to pass the `sourceMap` option to the `sass-loader` _and_ the css-loader.
715
716**webpack.config.js**
717
718```javascript
719module.exports = {
720 devtool: "source-map", // any "source-map"-like devtool is possible
721 module: {
722 rules: [
723 {
724 test: /\.s[ac]ss$/i,
725 use: [
726 "style-loader",
727 {
728 loader: "css-loader",
729 options: {
730 sourceMap: true,
731 },
732 },
733 {
734 loader: "sass-loader",
735 options: {
736 sourceMap: true,
737 },
738 },
739 ],
740 },
741 ],
742 },
743};
744```
745
746If you want to edit the original Sass files inside Chrome, [there's a good blog post](https://medium.com/@toolmantim/getting-started-with-css-sourcemaps-and-in-browser-sass-editing-b4daab987fb0). Checkout [test/sourceMap](https://github.com/webpack-contrib/sass-loader/tree/master/test) for a running example.
747
748## Contributing
749
750Please take a moment to read our contributing guidelines if you haven't yet done so.
751
752[CONTRIBUTING](./.github/CONTRIBUTING.md)
753
754## License
755
756[MIT](./LICENSE)
757
758[npm]: https://img.shields.io/npm/v/sass-loader.svg
759[npm-url]: https://npmjs.com/package/sass-loader
760[node]: https://img.shields.io/node/v/sass-loader.svg
761[node-url]: https://nodejs.org
762[deps]: https://david-dm.org/webpack-contrib/sass-loader.svg
763[deps-url]: https://david-dm.org/webpack-contrib/sass-loader
764[tests]: https://github.com/webpack-contrib/sass-loader/workflows/sass-loader/badge.svg
765[tests-url]: https://github.com/webpack-contrib/sass-loader/actions
766[cover]: https://codecov.io/gh/webpack-contrib/sass-loader/branch/master/graph/badge.svg
767[cover-url]: https://codecov.io/gh/webpack-contrib/sass-loader
768[chat]: https://badges.gitter.im/webpack/webpack.svg
769[chat-url]: https://gitter.im/webpack/webpack
770[size]: https://packagephobia.now.sh/badge?p=sass-loader
771[size-url]: https://packagephobia.now.sh/result?p=sass-loader