1 | <div align="center">
|
2 | <img height="100"
|
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 |
|
20 | Loads a Sass/SCSS file and compiles it to CSS.
|
21 |
|
22 | ## Getting Started
|
23 |
|
24 | To begin, you'll need to install `sass-loader`:
|
25 |
|
26 | ```console
|
27 | npm 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 |
|
32 | This allows you to control the versions of all your dependencies, and to choose which Sass implementation to use.
|
33 |
|
34 | > ℹ️ We 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.
|
37 |
|
38 | Chain 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 |
|
40 | Then add the loader to your Webpack configuration. For example:
|
41 |
|
42 | **app.js**
|
43 |
|
44 | ```js
|
45 | import './style.scss';
|
46 | ```
|
47 |
|
48 | **style.scss**
|
49 |
|
50 | ```scss
|
51 | $body-color: red;
|
52 |
|
53 | body {
|
54 | color: $body-color;
|
55 | }
|
56 | ```
|
57 |
|
58 | **webpack.config.js**
|
59 |
|
60 | ```js
|
61 | module.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 |
|
80 | Finally run `webpack` via your preferred method.
|
81 |
|
82 | ### Resolving `import` at-rules
|
83 |
|
84 | Webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/concepts/module-resolution/).
|
85 |
|
86 | The `sass-loader` uses Sass's custom importer feature to pass all queries to the Webpack resolving engine. Thus you can import your Sass modules from `node_modules`. Just prepend them with a `~` to tell Webpack that this is not a relative import:
|
87 |
|
88 | ```scss
|
89 | @import '~bootstrap';
|
90 | ```
|
91 |
|
92 | It's important to only prepend it with `~`, because `~/` resolves to the home directory.
|
93 | Webpack needs to distinguish between `bootstrap` and `~bootstrap` because CSS and Sass files have no special syntax for importing relative files.
|
94 | Writing `@import "style.scss"` is the same as `@import "./style.scss";`
|
95 |
|
96 | ### Problems with `url(...)`
|
97 |
|
98 | Since Sass implementations don't provide [url rewriting](https://github.com/sass/libsass/issues/532), all linked assets must be relative to the output.
|
99 |
|
100 | - If you pass the generated CSS on to the `css-loader`, all urls must be relative to the entry-file (e.g. `main.scss`).
|
101 | - If you're just generating CSS without passing it to the `css-loader`, it must be relative to your web root.
|
102 |
|
103 | You 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).
|
104 |
|
105 | Thankfully there are a two solutions to this problem:
|
106 |
|
107 | - 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.
|
108 | - 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`.
|
109 |
|
110 | ## Options
|
111 |
|
112 | | Name | Type | Default | Description |
|
113 | | :---------------------------------------: | :------------------: | :-------------------------------------: | :---------------------------------------------------------------- |
|
114 | | **[`implementation`](#implementation)** | `{Object}` | `sass` | Setup Sass implementation to use. |
|
115 | | **[`sassOptions`](#sassoptions)** | `{Object\|Function}` | defaults values for Sass implementation | Options for Sass. |
|
116 | | **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps. |
|
117 | | **[`additionalData`](#additionaldata)** | `{String\|Function}` | `undefined` | Prepends/Appends `Sass`/`SCSS` code before the actual entry file. |
|
118 | | **[`webpackImporter`](#webpackimporter)** | `{Boolean}` | `true` | Enables/Disables the default Webpack importer. |
|
119 |
|
120 | ### `implementation`
|
121 |
|
122 | Type: `Object`
|
123 | Default: `sass`
|
124 |
|
125 | The special `implementation` option determines which implementation of Sass to use.
|
126 |
|
127 | By default the loader resolve the implementation based on your dependencies.
|
128 | Just add required implementation to `package.json` (`sass` or `node-sass` package) and install dependencies.
|
129 |
|
130 | Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementation:
|
131 |
|
132 | **package.json**
|
133 |
|
134 | ```json
|
135 | {
|
136 | "devDependencies": {
|
137 | "sass-loader": "^7.2.0",
|
138 | "sass": "^1.22.10"
|
139 | }
|
140 | }
|
141 | ```
|
142 |
|
143 | Example where the `sass-loader` loader uses the `node-sass` implementation:
|
144 |
|
145 | **package.json**
|
146 |
|
147 | ```json
|
148 | {
|
149 | "devDependencies": {
|
150 | "sass-loader": "^7.2.0",
|
151 | "node-sass": "^4.0.0"
|
152 | }
|
153 | }
|
154 | ```
|
155 |
|
156 | Beware the situation when `node-sass` and `sass` were installed! By default the `sass-loader` prefers `sass`.
|
157 | In order to avoid this situation you can use the `implementation` option.
|
158 |
|
159 | The `implementation` options either accepts `sass` (`Dart Sass`) or `node-sass` as a module.
|
160 |
|
161 | For example, to use Dart Sass, you'd pass:
|
162 |
|
163 | ```js
|
164 | module.exports = {
|
165 | module: {
|
166 | rules: [
|
167 | {
|
168 | test: /\.s[ac]ss$/i,
|
169 | use: [
|
170 | 'style-loader',
|
171 | 'css-loader',
|
172 | {
|
173 | loader: 'sass-loader',
|
174 | options: {
|
175 | // Prefer `dart-sass`
|
176 | implementation: require('sass'),
|
177 | },
|
178 | },
|
179 | ],
|
180 | },
|
181 | ],
|
182 | },
|
183 | };
|
184 | ```
|
185 |
|
186 | Note that when using `sass` (`Dart Sass`), **synchronous compilation is twice as fast as asynchronous compilation** by default, due to the overhead of asynchronous callbacks.
|
187 | To avoid this overhead, you can use the [fibers](https://www.npmjs.com/package/fibers) package to call asynchronous importers from the synchronous code path.
|
188 |
|
189 | We automatically inject the [`fibers`](https://github.com/laverdet/node-fibers) package (setup `sassOptions.fiber`) if is possible (i.e. you need install the [`fibers`](https://github.com/laverdet/node-fibers) package).
|
190 |
|
191 | **package.json**
|
192 |
|
193 | ```json
|
194 | {
|
195 | "devDependencies": {
|
196 | "sass-loader": "^7.2.0",
|
197 | "sass": "^1.22.10",
|
198 | "fibers": "^4.0.1"
|
199 | }
|
200 | }
|
201 | ```
|
202 |
|
203 | You can disable automatically injecting the [`fibers`](https://github.com/laverdet/node-fibers) package by passing a `false` value for the `sassOptions.fiber` option.
|
204 |
|
205 | **webpack.config.js**
|
206 |
|
207 | ```js
|
208 | module.exports = {
|
209 | module: {
|
210 | rules: [
|
211 | {
|
212 | test: /\.s[ac]ss$/i,
|
213 | use: [
|
214 | 'style-loader',
|
215 | 'css-loader',
|
216 | {
|
217 | loader: 'sass-loader',
|
218 | options: {
|
219 | implementation: require('sass'),
|
220 | sassOptions: {
|
221 | fiber: false,
|
222 | },
|
223 | },
|
224 | },
|
225 | ],
|
226 | },
|
227 | ],
|
228 | },
|
229 | };
|
230 | ```
|
231 |
|
232 | You can also pass the `fiber` value using this code:
|
233 |
|
234 | **webpack.config.js**
|
235 |
|
236 | ```js
|
237 | module.exports = {
|
238 | module: {
|
239 | rules: [
|
240 | {
|
241 | test: /\.s[ac]ss$/i,
|
242 | use: [
|
243 | 'style-loader',
|
244 | 'css-loader',
|
245 | {
|
246 | loader: 'sass-loader',
|
247 | options: {
|
248 | implementation: require('sass'),
|
249 | sassOptions: {
|
250 | fiber: require('fibers'),
|
251 | },
|
252 | },
|
253 | },
|
254 | ],
|
255 | },
|
256 | ],
|
257 | },
|
258 | };
|
259 | ```
|
260 |
|
261 | ### `sassOptions`
|
262 |
|
263 | Type: `Object|Function`
|
264 | Default: defaults values for Sass implementation
|
265 |
|
266 | Options for [Dart Sass](http://sass-lang.com/dart-sass) or [Node Sass](https://github.com/sass/node-sass) implementation.
|
267 |
|
268 | > ℹ️ The `indentedSyntax` option has `true` value for the `sass` extension.
|
269 |
|
270 | > ℹ️ Options such as `data` and `file` are unavailable and will be ignored.
|
271 |
|
272 | > ℹ We recommend not to set the `outFile`, `sourceMapContents`, `sourceMapEmbed`, `sourceMapRoot` options because `sass-loader` automatically sets these options when the `sourceMap` option is `true`.
|
273 |
|
274 | > ℹ️ 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.
|
275 |
|
276 | There is a slight difference between the `sass` (`dart-sass`) and `node-sass` options.
|
277 |
|
278 | Please consult documentation before using them:
|
279 |
|
280 | - [Dart Sass documentation](https://github.com/sass/dart-sass#javascript-api) for all available `sass` options.
|
281 | - [Node Sass documentation](https://github.com/sass/node-sass/#options) for all available `node-sass` options.
|
282 |
|
283 | #### `Object`
|
284 |
|
285 | Use and object for the Sass implementation setup.
|
286 |
|
287 | **webpack.config.js**
|
288 |
|
289 | ```js
|
290 | module.exports = {
|
291 | module: {
|
292 | rules: [
|
293 | {
|
294 | test: /\.s[ac]ss$/i,
|
295 | use: [
|
296 | 'style-loader',
|
297 | 'css-loader',
|
298 | {
|
299 | loader: 'sass-loader',
|
300 | options: {
|
301 | sassOptions: {
|
302 | indentWidth: 4,
|
303 | includePaths: ['absolute/path/a', 'absolute/path/b'],
|
304 | },
|
305 | },
|
306 | },
|
307 | ],
|
308 | },
|
309 | ],
|
310 | },
|
311 | };
|
312 | ```
|
313 |
|
314 | #### `Function`
|
315 |
|
316 | Allows to setup the Sass implementation by setting different options based on the loader context.
|
317 |
|
318 | ```js
|
319 | module.exports = {
|
320 | module: {
|
321 | rules: [
|
322 | {
|
323 | test: /\.s[ac]ss$/i,
|
324 | use: [
|
325 | 'style-loader',
|
326 | 'css-loader',
|
327 | {
|
328 | loader: 'sass-loader',
|
329 | options: {
|
330 | sassOptions: (loaderContext) => {
|
331 | // More information about available properties https://webpack.js.org/api/loaders/
|
332 | const { resourcePath, rootContext } = loaderContext;
|
333 | const relativePath = path.relative(rootContext, resourcePath);
|
334 |
|
335 | if (relativePath === 'styles/foo.scss') {
|
336 | return {
|
337 | includePaths: ['absolute/path/c', 'absolute/path/d'],
|
338 | };
|
339 | }
|
340 |
|
341 | return {
|
342 | includePaths: ['absolute/path/a', 'absolute/path/b'],
|
343 | };
|
344 | },
|
345 | },
|
346 | },
|
347 | ],
|
348 | },
|
349 | ],
|
350 | },
|
351 | };
|
352 | ```
|
353 |
|
354 | ### `sourceMap`
|
355 |
|
356 | Type: `Boolean`
|
357 | Default: depends on the `compiler.devtool` value
|
358 |
|
359 | Enables/Disables generation of source maps.
|
360 |
|
361 | By default generation of source maps depends on the [`devtool`](https://webpack.js.org/configuration/devtool/) option.
|
362 | All values enable source map generation except `eval` and `false` value.
|
363 |
|
364 | > ℹ If a `true` the `sourceMap`, `sourceMapRoot`, `sourceMapEmbed`, `sourceMapContents` and `omitSourceMapUrl` from `sassOptions` will be ignored.
|
365 |
|
366 | **webpack.config.js**
|
367 |
|
368 | ```js
|
369 | module.exports = {
|
370 | module: {
|
371 | rules: [
|
372 | {
|
373 | test: /\.s[ac]ss$/i,
|
374 | use: [
|
375 | 'style-loader',
|
376 | {
|
377 | loader: 'css-loader',
|
378 | options: {
|
379 | sourceMap: true,
|
380 | },
|
381 | },
|
382 | {
|
383 | loader: 'sass-loader',
|
384 | options: {
|
385 | sourceMap: true,
|
386 | },
|
387 | },
|
388 | ],
|
389 | },
|
390 | ],
|
391 | },
|
392 | };
|
393 | ```
|
394 |
|
395 | > ℹ In some rare cases `node-sass` can output invalid source maps (it is a `node-sass` bug).
|
396 |
|
397 | > > 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`.
|
398 |
|
399 | **webpack.config.js**
|
400 |
|
401 | ```js
|
402 | module.exports = {
|
403 | module: {
|
404 | rules: [
|
405 | {
|
406 | test: /\.s[ac]ss$/i,
|
407 | use: [
|
408 | 'style-loader',
|
409 | 'css-loader',
|
410 | {
|
411 | loader: 'sass-loader',
|
412 | options: {
|
413 | sourceMap: true,
|
414 | sassOptions: {
|
415 | outputStyle: 'compressed',
|
416 | },
|
417 | },
|
418 | },
|
419 | ],
|
420 | },
|
421 | ],
|
422 | },
|
423 | };
|
424 | ```
|
425 |
|
426 | ### `additionalData`
|
427 |
|
428 | Type: `String|Function`
|
429 | Default: `undefined`
|
430 |
|
431 | Prepends `Sass`/`SCSS` code before the actual entry file.
|
432 | In this case, the `sass-loader` will not override the `data` option but just **prepend** the entry's content.
|
433 |
|
434 | This is especially useful when some of your Sass variables depend on the environment:
|
435 |
|
436 | #### `String`
|
437 |
|
438 | ```js
|
439 | module.exports = {
|
440 | module: {
|
441 | rules: [
|
442 | {
|
443 | test: /\.s[ac]ss$/i,
|
444 | use: [
|
445 | 'style-loader',
|
446 | 'css-loader',
|
447 | {
|
448 | loader: 'sass-loader',
|
449 | options: {
|
450 | additionalData: '$env: ' + process.env.NODE_ENV + ';',
|
451 | },
|
452 | },
|
453 | ],
|
454 | },
|
455 | ],
|
456 | },
|
457 | };
|
458 | ```
|
459 |
|
460 | #### `Function`
|
461 |
|
462 | ```js
|
463 | module.exports = {
|
464 | module: {
|
465 | rules: [
|
466 | {
|
467 | test: /\.s[ac]ss$/i,
|
468 | use: [
|
469 | 'style-loader',
|
470 | 'css-loader',
|
471 | {
|
472 | loader: 'sass-loader',
|
473 | options: {
|
474 | additionalData: (content, loaderContext) => {
|
475 | // More information about available properties https://webpack.js.org/api/loaders/
|
476 | const { resourcePath, rootContext } = loaderContext;
|
477 | const relativePath = path.relative(rootContext, resourcePath);
|
478 |
|
479 | if (relativePath === 'styles/foo.scss') {
|
480 | return '$value: 100px;' + content;
|
481 | }
|
482 |
|
483 | return '$value: 200px;' + content;
|
484 | },
|
485 | },
|
486 | },
|
487 | ],
|
488 | },
|
489 | ],
|
490 | },
|
491 | };
|
492 | ```
|
493 |
|
494 | ### `webpackImporter`
|
495 |
|
496 | Type: `Boolean`
|
497 | Default: `true`
|
498 |
|
499 | Enables/Disables the default Webpack importer.
|
500 |
|
501 | This can improve performance in some cases. Use it with caution because aliases and `@import` at-rules starting with `~` will not work.
|
502 | You can pass own `importer` to solve this (see [`importer docs`](https://github.com/sass/node-sass#importer--v200---experimental)).
|
503 |
|
504 | **webpack.config.js**
|
505 |
|
506 | ```js
|
507 | module.exports = {
|
508 | module: {
|
509 | rules: [
|
510 | {
|
511 | test: /\.s[ac]ss$/i,
|
512 | use: [
|
513 | 'style-loader',
|
514 | 'css-loader',
|
515 | {
|
516 | loader: 'sass-loader',
|
517 | options: {
|
518 | webpackImporter: false,
|
519 | },
|
520 | },
|
521 | ],
|
522 | },
|
523 | ],
|
524 | },
|
525 | };
|
526 | ```
|
527 |
|
528 | ## Examples
|
529 |
|
530 | ### Extracts CSS into separate files
|
531 |
|
532 | For production builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on.
|
533 |
|
534 | There are two possibilities to extract a style sheet from the bundle:
|
535 |
|
536 | - [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) (use this, when using webpack 4 configuration. Works in all use-cases)
|
537 | - [extract-loader](https://github.com/peerigon/extract-loader) (simpler, but specialized on the css-loader's output)
|
538 |
|
539 | **webpack.config.js**
|
540 |
|
541 | ```js
|
542 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
543 |
|
544 | module.exports = {
|
545 | module: {
|
546 | rules: [
|
547 | {
|
548 | test: /\.s[ac]ss$/i,
|
549 | use: [
|
550 | // fallback to style-loader in development
|
551 | process.env.NODE_ENV !== 'production'
|
552 | ? 'style-loader'
|
553 | : MiniCssExtractPlugin.loader,
|
554 | 'css-loader',
|
555 | 'sass-loader',
|
556 | ],
|
557 | },
|
558 | ],
|
559 | },
|
560 | plugins: [
|
561 | new MiniCssExtractPlugin({
|
562 | // Options similar to the same options in webpackOptions.output
|
563 | // both options are optional
|
564 | filename: '[name].css',
|
565 | chunkFilename: '[id].css',
|
566 | }),
|
567 | ],
|
568 | };
|
569 | ```
|
570 |
|
571 | ### Source maps
|
572 |
|
573 | Enables/Disables generation of source maps.
|
574 |
|
575 | To enable CSS source maps, you'll need to pass the `sourceMap` option to the `sass-loader` _and_ the css-loader.
|
576 |
|
577 | **webpack.config.js**
|
578 |
|
579 | ```javascript
|
580 | module.exports = {
|
581 | devtool: 'source-map', // any "source-map"-like devtool is possible
|
582 | module: {
|
583 | rules: [
|
584 | {
|
585 | test: /\.s[ac]ss$/i,
|
586 | use: [
|
587 | 'style-loader',
|
588 | {
|
589 | loader: 'css-loader',
|
590 | options: {
|
591 | sourceMap: true,
|
592 | },
|
593 | },
|
594 | {
|
595 | loader: 'sass-loader',
|
596 | options: {
|
597 | sourceMap: true,
|
598 | },
|
599 | },
|
600 | ],
|
601 | },
|
602 | ],
|
603 | },
|
604 | };
|
605 | ```
|
606 |
|
607 | If 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.
|
608 |
|
609 | ## Contributing
|
610 |
|
611 | Please take a moment to read our contributing guidelines if you haven't yet done so.
|
612 |
|
613 | [CONTRIBUTING](./.github/CONTRIBUTING.md)
|
614 |
|
615 | ## License
|
616 |
|
617 | [MIT](./LICENSE)
|
618 |
|
619 | [npm]: https://img.shields.io/npm/v/sass-loader.svg
|
620 | [npm-url]: https://npmjs.com/package/sass-loader
|
621 | [node]: https://img.shields.io/node/v/sass-loader.svg
|
622 | [node-url]: https://nodejs.org
|
623 | [deps]: https://david-dm.org/webpack-contrib/sass-loader.svg
|
624 | [deps-url]: https://david-dm.org/webpack-contrib/sass-loader
|
625 | [tests]: https://github.com/webpack-contrib/sass-loader/workflows/sass-loader/badge.svg
|
626 | [tests-url]: https://github.com/webpack-contrib/sass-loader/actions
|
627 | [cover]: https://codecov.io/gh/webpack-contrib/sass-loader/branch/master/graph/badge.svg
|
628 | [cover-url]: https://codecov.io/gh/webpack-contrib/sass-loader
|
629 | [chat]: https://badges.gitter.im/webpack/webpack.svg
|
630 | [chat-url]: https://gitter.im/webpack/webpack
|
631 | [size]: https://packagephobia.now.sh/badge?p=sass-loader
|
632 | [size-url]: https://packagephobia.now.sh/result?p=sass-loader
|