123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668 |
- <div align="center">
- <img height="100"
- src="https://worldvectorlogo.com/logos/sass-1.svg">
- <a href="https://github.com/webpack/webpack">
- <img width="200" height="200"
- src="https://webpack.js.org/assets/icon-square-big.svg">
- </a>
- </div>
- [![npm][npm]][npm-url]
- [![node][node]][node-url]
- [![deps][deps]][deps-url]
- [![tests][tests]][tests-url]
- [![coverage][cover]][cover-url]
- [![chat][chat]][chat-url]
- [![size][size]][size-url]
- # sass-loader
- Loads a Sass/SCSS file and compiles it to CSS.
- ## Getting Started
- To begin, you'll need to install `sass-loader`:
- ```console
- npm install sass-loader sass webpack --save-dev
- ```
- `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).
- This allows you to control the versions of all your dependencies, and to choose which Sass implementation to use.
- > ℹ️ We recommend using [Dart Sass](https://github.com/sass/dart-sass).
- > ⚠ [Node Sass](https://github.com/sass/node-sass) does not work with [Yarn PnP](https://classic.yarnpkg.com/en/docs/pnp/) feature.
- 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.
- Then add the loader to your Webpack configuration. For example:
- **app.js**
- ```js
- import "./style.scss";
- ```
- **style.scss**
- ```scss
- $body-color: red;
- body {
- color: $body-color;
- }
- ```
- **webpack.config.js**
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- // Creates `style` nodes from JS strings
- "style-loader",
- // Translates CSS into CommonJS
- "css-loader",
- // Compiles Sass to CSS
- "sass-loader",
- ],
- },
- ],
- },
- };
- ```
- Finally run `webpack` via your preferred method.
- ### Resolving `import` at-rules
- Webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/concepts/module-resolution/).
- 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:
- ```scss
- @import "~bootstrap";
- ```
- It's important to only prepend it with `~`, because `~/` resolves to the home directory.
- Webpack needs to distinguish between `bootstrap` and `~bootstrap` because CSS and Sass files have no special syntax for importing relative files.
- Writing `@import "style.scss"` is the same as `@import "./style.scss";`
- ### Problems with `url(...)`
- Since Sass implementations don't provide [url rewriting](https://github.com/sass/libsass/issues/532), all linked assets must be relative to the output.
- - If you pass the generated CSS on to the `css-loader`, all urls must be relative to the entry-file (e.g. `main.scss`).
- - If you're just generating CSS without passing it to the `css-loader`, it must be relative to your web root.
- 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).
- Thankfully there are a two solutions to this problem:
- - 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.
- - 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`.
- ## Options
- | Name | Type | Default | Description |
- | :---------------------------------------: | :------------------: | :-------------------------------------: | :---------------------------------------------------------------- |
- | **[`implementation`](#implementation)** | `{Object}` | `sass` | Setup Sass implementation to use. |
- | **[`sassOptions`](#sassoptions)** | `{Object\|Function}` | defaults values for Sass implementation | Options for Sass. |
- | **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps. |
- | **[`additionalData`](#additionaldata)** | `{String\|Function}` | `undefined` | Prepends/Appends `Sass`/`SCSS` code before the actual entry file. |
- | **[`webpackImporter`](#webpackimporter)** | `{Boolean}` | `true` | Enables/Disables the default Webpack importer. |
- ### `implementation`
- Type: `Object`
- Default: `sass`
- The special `implementation` option determines which implementation of Sass to use.
- By default the loader resolve the implementation based on your dependencies.
- Just add required implementation to `package.json` (`sass` or `node-sass` package) and install dependencies.
- Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementation:
- **package.json**
- ```json
- {
- "devDependencies": {
- "sass-loader": "^7.2.0",
- "sass": "^1.22.10"
- }
- }
- ```
- Example where the `sass-loader` loader uses the `node-sass` implementation:
- **package.json**
- ```json
- {
- "devDependencies": {
- "sass-loader": "^7.2.0",
- "node-sass": "^5.0.0"
- }
- }
- ```
- Beware the situation when `node-sass` and `sass` were installed! By default the `sass-loader` prefers `sass`.
- In order to avoid this situation you can use the `implementation` option.
- The `implementation` options either accepts `sass` (`Dart Sass`) or `node-sass` as a module.
- For example, to use Dart Sass, you'd pass:
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- // Prefer `dart-sass`
- implementation: require("sass"),
- },
- },
- ],
- },
- ],
- },
- };
- ```
- 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.
- 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.
- 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).
- **package.json**
- ```json
- {
- "devDependencies": {
- "sass-loader": "^7.2.0",
- "sass": "^1.22.10",
- "fibers": "^4.0.1"
- }
- }
- ```
- You can disable automatically injecting the [`fibers`](https://github.com/laverdet/node-fibers) package by passing a `false` value for the `sassOptions.fiber` option.
- **webpack.config.js**
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- implementation: require("sass"),
- sassOptions: {
- fiber: false,
- },
- },
- },
- ],
- },
- ],
- },
- };
- ```
- You can also pass the `fiber` value using this code:
- **webpack.config.js**
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- implementation: require("sass"),
- sassOptions: {
- fiber: require("fibers"),
- },
- },
- },
- ],
- },
- ],
- },
- };
- ```
- ### `sassOptions`
- Type: `Object|Function`
- Default: defaults values for Sass implementation
- Options for [Dart Sass](http://sass-lang.com/dart-sass) or [Node Sass](https://github.com/sass/node-sass) implementation.
- > ℹ️ The `indentedSyntax` option has `true` value for the `sass` extension.
- > ℹ️ Options such as `data` and `file` are unavailable and will be ignored.
- > ℹ We recommend not to set the `outFile`, `sourceMapContents`, `sourceMapEmbed`, `sourceMapRoot` options because `sass-loader` automatically sets these options when the `sourceMap` option is `true`.
- > ℹ️ 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.
- There is a slight difference between the `sass` (`dart-sass`) and `node-sass` options.
- Please consult documentation before using them:
- - [Dart Sass documentation](https://github.com/sass/dart-sass#javascript-api) for all available `sass` options.
- - [Node Sass documentation](https://github.com/sass/node-sass/#options) for all available `node-sass` options.
- #### `Object`
- Use and object for the Sass implementation setup.
- **webpack.config.js**
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- sassOptions: {
- indentWidth: 4,
- includePaths: ["absolute/path/a", "absolute/path/b"],
- },
- },
- },
- ],
- },
- ],
- },
- };
- ```
- #### `Function`
- Allows to setup the Sass implementation by setting different options based on the loader context.
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- sassOptions: (loaderContext) => {
- // More information about available properties https://webpack.js.org/api/loaders/
- const { resourcePath, rootContext } = loaderContext;
- const relativePath = path.relative(rootContext, resourcePath);
- if (relativePath === "styles/foo.scss") {
- return {
- includePaths: ["absolute/path/c", "absolute/path/d"],
- };
- }
- return {
- includePaths: ["absolute/path/a", "absolute/path/b"],
- };
- },
- },
- },
- ],
- },
- ],
- },
- };
- ```
- ### `sourceMap`
- Type: `Boolean`
- Default: depends on the `compiler.devtool` value
- Enables/Disables generation of source maps.
- By 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.
- > ℹ If a `true` the `sourceMap`, `sourceMapRoot`, `sourceMapEmbed`, `sourceMapContents` and `omitSourceMapUrl` from `sassOptions` will be ignored.
- **webpack.config.js**
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- {
- loader: "css-loader",
- options: {
- sourceMap: true,
- },
- },
- {
- loader: "sass-loader",
- options: {
- sourceMap: true,
- },
- },
- ],
- },
- ],
- },
- };
- ```
- > ℹ In some rare cases `node-sass` can output invalid source maps (it is a `node-sass` bug).
- > > 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`.
- **webpack.config.js**
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- sourceMap: true,
- sassOptions: {
- outputStyle: "compressed",
- },
- },
- },
- ],
- },
- ],
- },
- };
- ```
- ### `additionalData`
- Type: `String|Function`
- Default: `undefined`
- Prepends `Sass`/`SCSS` code before the actual entry file.
- In this case, the `sass-loader` will not override the `data` option but just **prepend** the entry's content.
- This is especially useful when some of your Sass variables depend on the environment:
- #### `String`
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- additionalData: "$env: " + process.env.NODE_ENV + ";",
- },
- },
- ],
- },
- ],
- },
- };
- ```
- #### `Function`
- ##### Sync
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- additionalData: (content, loaderContext) => {
- // More information about available properties https://webpack.js.org/api/loaders/
- const { resourcePath, rootContext } = loaderContext;
- const relativePath = path.relative(rootContext, resourcePath);
- if (relativePath === "styles/foo.scss") {
- return "$value: 100px;" + content;
- }
- return "$value: 200px;" + content;
- },
- },
- },
- ],
- },
- ],
- },
- };
- ```
- ##### Async
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- additionalData: async (content, loaderContext) => {
- // More information about available properties https://webpack.js.org/api/loaders/
- const { resourcePath, rootContext } = loaderContext;
- const relativePath = path.relative(rootContext, resourcePath);
- if (relativePath === "styles/foo.scss") {
- return "$value: 100px;" + content;
- }
- return "$value: 200px;" + content;
- },
- },
- },
- ],
- },
- ],
- },
- };
- ```
- ### `webpackImporter`
- Type: `Boolean`
- Default: `true`
- Enables/Disables the default Webpack importer.
- This can improve performance in some cases. Use it with caution because aliases and `@import` at-rules starting with `~` will not work.
- You can pass own `importer` to solve this (see [`importer docs`](https://github.com/sass/node-sass#importer--v200---experimental)).
- **webpack.config.js**
- ```js
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- "css-loader",
- {
- loader: "sass-loader",
- options: {
- webpackImporter: false,
- },
- },
- ],
- },
- ],
- },
- };
- ```
- ## Examples
- ### Extracts CSS into separate files
- 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.
- There are two possibilities to extract a style sheet from the bundle:
- - [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)
- - [extract-loader](https://github.com/peerigon/extract-loader) (simpler, but specialized on the css-loader's output)
- **webpack.config.js**
- ```js
- const MiniCssExtractPlugin = require("mini-css-extract-plugin");
- module.exports = {
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- // fallback to style-loader in development
- process.env.NODE_ENV !== "production"
- ? "style-loader"
- : MiniCssExtractPlugin.loader,
- "css-loader",
- "sass-loader",
- ],
- },
- ],
- },
- plugins: [
- new MiniCssExtractPlugin({
- // Options similar to the same options in webpackOptions.output
- // both options are optional
- filename: "[name].css",
- chunkFilename: "[id].css",
- }),
- ],
- };
- ```
- ### Source maps
- Enables/Disables generation of source maps.
- To enable CSS source maps, you'll need to pass the `sourceMap` option to the `sass-loader` _and_ the css-loader.
- **webpack.config.js**
- ```javascript
- module.exports = {
- devtool: "source-map", // any "source-map"-like devtool is possible
- module: {
- rules: [
- {
- test: /\.s[ac]ss$/i,
- use: [
- "style-loader",
- {
- loader: "css-loader",
- options: {
- sourceMap: true,
- },
- },
- {
- loader: "sass-loader",
- options: {
- sourceMap: true,
- },
- },
- ],
- },
- ],
- },
- };
- ```
- 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.
- ## Contributing
- Please take a moment to read our contributing guidelines if you haven't yet done so.
- [CONTRIBUTING](./.github/CONTRIBUTING.md)
- ## License
- [MIT](./LICENSE)
- [npm]: https://img.shields.io/npm/v/sass-loader.svg
- [npm-url]: https://npmjs.com/package/sass-loader
- [node]: https://img.shields.io/node/v/sass-loader.svg
- [node-url]: https://nodejs.org
- [deps]: https://david-dm.org/webpack-contrib/sass-loader.svg
- [deps-url]: https://david-dm.org/webpack-contrib/sass-loader
- [tests]: https://github.com/webpack-contrib/sass-loader/workflows/sass-loader/badge.svg
- [tests-url]: https://github.com/webpack-contrib/sass-loader/actions
- [cover]: https://codecov.io/gh/webpack-contrib/sass-loader/branch/master/graph/badge.svg
- [cover-url]: https://codecov.io/gh/webpack-contrib/sass-loader
- [chat]: https://badges.gitter.im/webpack/webpack.svg
- [chat-url]: https://gitter.im/webpack/webpack
- [size]: https://packagephobia.now.sh/badge?p=sass-loader
- [size-url]: https://packagephobia.now.sh/result?p=sass-loader
|