You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

484 lines
13 KiB

4 years ago
  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. [![npm][npm]][npm-url]
  10. [![node][node]][node-url]
  11. [![deps][deps]][deps-url]
  12. [![tests][tests]][tests-url]
  13. [![coverage][cover]][cover-url]
  14. [![chat][chat]][chat-url]
  15. [![size][size]][size-url]
  16. # sass-loader
  17. Loads a Sass/SCSS file and compiles it to CSS.
  18. ## Getting Started
  19. To begin, you'll need to install `sass-loader`:
  20. ```console
  21. npm install sass-loader node-sass webpack --save-dev
  22. ```
  23. The sass-loader requires you to install either [Node Sass](https://github.com/sass/node-sass) or [Dart Sass](https://github.com/sass/dart-sass) on your own (more documentation you can find below).
  24. This allows you to control the versions of all your dependencies, and to choose which Sass implementation to use.
  25. - [node sass](https://github.com/sass/node-sass)
  26. - [dart sass](http://sass-lang.com/dart-sass)
  27. 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.
  28. Then add the loader to your `webpack` config. For example:
  29. **file.js**
  30. ```js
  31. import style from './style.scss';
  32. ```
  33. **file.scss**
  34. ```scss
  35. $body-color: red;
  36. body {
  37. color: $body-color;
  38. }
  39. ```
  40. **webpack.config.js**
  41. ```js
  42. module.exports = {
  43. module: {
  44. rules: [
  45. {
  46. test: /\.s[ac]ss$/i,
  47. use: [
  48. // Creates `style` nodes from JS strings
  49. 'style-loader',
  50. // Translates CSS into CommonJS
  51. 'css-loader',
  52. // Compiles Sass to CSS
  53. 'sass-loader',
  54. ],
  55. },
  56. ],
  57. },
  58. };
  59. ```
  60. And run `webpack` via your preferred method.
  61. ### Resolving `import` at-rules
  62. The webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/concepts/module-resolution/).
  63. 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:
  64. ```css
  65. @import '~bootstrap';
  66. ```
  67. It's important to only prepend it with `~`, because `~/` resolves to the home directory.
  68. The webpack needs to distinguish between `bootstrap` and `~bootstrap` because CSS and Sass files have no special syntax for importing relative files.
  69. Writing `@import "file"` is the same as `@import "./file";`
  70. ### Problems with `url(...)`
  71. Since sass implementations don't provide [url rewriting](https://github.com/sass/libsass/issues/532), all linked assets must be relative to the output.
  72. - If you pass the generated CSS on to the css-loader, all urls must be relative to the entry-file (e.g. `main.scss`).
  73. - If you're just generating CSS without passing it to the css-loader, it must be relative to your web root.
  74. 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).
  75. Thankfully there are a two solutions to this problem:
  76. - Add the missing url rewriting using the [resolve-url-loader](https://github.com/bholloway/resolve-url-loader). Place it before the sass-loader in the loader chain.
  77. - 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`.
  78. ## Options
  79. By default all options passed to loader also passed to to [Node Sass](https://github.com/sass/node-sass) or [Dart Sass](http://sass-lang.com/dart-sass)
  80. > ℹ️ The `indentedSyntax` option has `true` value for the `sass` extension.
  81. > ℹ️ Options such as `file` and `outFile` are unavailable.
  82. > ℹ️ Only the "expanded" and "compressed" values of outputStyle are supported for `dart-sass`.
  83. > ℹ We recommend don't use `sourceMapContents`, `sourceMapEmbed`, `sourceMapRoot` options because loader automatically setup this options.
  84. There is a slight difference between the `node-sass` and `sass` options. We recommend look documentation before used them:
  85. - [the Node Sass documentation](https://github.com/sass/node-sass/#options) for all available `node-sass` options.
  86. - [the Dart Sass documentation](https://github.com/sass/dart-sass#javascript-api) for all available `sass` options.
  87. **webpack.config.js**
  88. ```js
  89. module.exports = {
  90. module: {
  91. rules: [
  92. {
  93. test: /\.s[ac]ss$/i,
  94. use: [
  95. 'style-loader',
  96. 'css-loader',
  97. {
  98. loader: 'sass-loader',
  99. options: {
  100. indentWidth: 4,
  101. includePaths: ['absolute/path/a', 'absolute/path/b'],
  102. },
  103. },
  104. ],
  105. },
  106. ],
  107. },
  108. };
  109. ```
  110. ### `implementation`
  111. The special `implementation` option determines which implementation of Sass to use.
  112. By default the loader resolve the implementation based on your dependencies.
  113. Just add required implementation to `package.json` (`node-sass` or `sass` package) and install dependencies.
  114. Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementation:
  115. **package.json**
  116. ```json
  117. {
  118. "devDependencies": {
  119. "sass-loader": "^7.2.0",
  120. "sass": "^1.22.10"
  121. }
  122. }
  123. ```
  124. Example where the `sass-loader` loader uses the `node-sass` implementation:
  125. **package.json**
  126. ```json
  127. {
  128. "devDependencies": {
  129. "sass-loader": "^7.2.0",
  130. "node-sass": "^4.0.0"
  131. }
  132. }
  133. ```
  134. Beware the situation when `node-sass` and `sass` was installed, by default the `sass-loader` prefers `node-sass`, to avoid this situation use the `implementation` option.
  135. It takes either `node-sass` or `sass` (`Dart Sass`) module.
  136. For example, to use Dart Sass, you'd pass:
  137. ```js
  138. module.exports = {
  139. module: {
  140. rules: [
  141. {
  142. test: /\.s[ac]ss$/i,
  143. use: [
  144. 'style-loader',
  145. 'css-loader',
  146. {
  147. loader: 'sass-loader',
  148. options: {
  149. // Prefer `dart-sass`
  150. implementation: require('sass'),
  151. },
  152. },
  153. ],
  154. },
  155. ],
  156. },
  157. };
  158. ```
  159. 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.
  160. 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.
  161. To enable this, pass the `Fiber` class to the `fiber` option:
  162. **webpack.config.js**
  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. implementation: require('sass'),
  176. fiber: require('fibers'),
  177. },
  178. },
  179. ],
  180. },
  181. ],
  182. },
  183. };
  184. ```
  185. ### `data`
  186. Type: `String|Function`
  187. Default: `undefined`
  188. Prepends `Sass`/`SCSS` code before the actual entry file.
  189. In this case, the `sass-loader` will not override the `data` option but just append the entry's content.
  190. This is especially useful when some of your Sass variables depend on the environment:
  191. > ℹ 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 Sass entry files.
  192. #### `String`
  193. ```js
  194. module.exports = {
  195. module: {
  196. rules: [
  197. {
  198. test: /\.s[ac]ss$/i,
  199. use: [
  200. 'style-loader',
  201. 'css-loader',
  202. {
  203. loader: 'sass-loader',
  204. options: {
  205. data: '$env: ' + process.env.NODE_ENV + ';',
  206. },
  207. },
  208. ],
  209. },
  210. ],
  211. },
  212. };
  213. ```
  214. #### `Function`
  215. ```js
  216. module.exports = {
  217. module: {
  218. rules: [
  219. {
  220. test: /\.s[ac]ss$/i,
  221. use: [
  222. 'style-loader',
  223. 'css-loader',
  224. {
  225. loader: 'sass-loader',
  226. options: {
  227. data: (loaderContext) => {
  228. // More information about avalaible options https://webpack.js.org/api/loaders/
  229. const { resourcePath, rootContext } = loaderContext;
  230. const relativePath = path.relative(rootContext, resourcePath);
  231. if (relativePath === 'styles/foo.scss') {
  232. return '$value: 100px;';
  233. }
  234. return '$value: 200px;';
  235. },
  236. },
  237. },
  238. ],
  239. },
  240. ],
  241. },
  242. };
  243. ```
  244. ### `sourceMap`
  245. Type: `Boolean`
  246. Default: `false`
  247. Enables/Disables generation of source maps.
  248. They are not enabled by default because they expose a runtime overhead and increase in bundle size (JS source maps do not).
  249. **webpack.config.js**
  250. ```js
  251. module.exports = {
  252. module: {
  253. rules: [
  254. {
  255. test: /\.s[ac]ss$/i,
  256. use: [
  257. 'style-loader',
  258. {
  259. loader: 'css-loader',
  260. options: {
  261. sourceMap: true,
  262. },
  263. },
  264. {
  265. loader: 'sass-loader',
  266. options: {
  267. sourceMap: true,
  268. },
  269. },
  270. ],
  271. },
  272. ],
  273. },
  274. };
  275. ```
  276. > ℹ In some rare case `node-sass` can output invalid source maps (it is `node-sass` bug), to avoid try to update node-sass to latest version or you can try to set the `outputStyle` option to `compressed` value.
  277. ### `webpackImporter`
  278. Type: `Boolean`
  279. Default: `true`
  280. Allows to disable default `webpack` importer.
  281. This can improve performance in some cases. Use it with caution because aliases and `@import` at-rules starts with `~` will not work, but you can pass own `importer` to solve this (see [`importer docs`](https://github.com/sass/node-sass#importer--v200---experimental)).
  282. **webpack.config.js**
  283. ```js
  284. module.exports = {
  285. module: {
  286. rules: [
  287. {
  288. test: /\.s[ac]ss$/i,
  289. use: [
  290. 'style-loader',
  291. 'css-loader',
  292. {
  293. loader: 'sass-loader',
  294. options: {
  295. webpackImporter: false,
  296. },
  297. },
  298. ],
  299. },
  300. ],
  301. },
  302. };
  303. ```
  304. ## Examples
  305. ### Extracts CSS into separate files
  306. 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.
  307. There are two possibilities to extract a style sheet from the bundle:
  308. - [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)
  309. - [extract-loader](https://github.com/peerigon/extract-loader) (simpler, but specialized on the css-loader's output)
  310. **webpack.config.js**
  311. ```js
  312. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  313. module.exports = {
  314. module: {
  315. rules: [
  316. {
  317. test: /\.s[ac]ss$/i,
  318. use: [
  319. // fallback to style-loader in development
  320. process.env.NODE_ENV !== 'production'
  321. ? 'style-loader'
  322. : MiniCssExtractPlugin.loader,
  323. 'css-loader',
  324. 'sass-loader',
  325. ],
  326. },
  327. ],
  328. },
  329. plugins: [
  330. new MiniCssExtractPlugin({
  331. // Options similar to the same options in webpackOptions.output
  332. // both options are optional
  333. filename: '[name].css',
  334. chunkFilename: '[id].css',
  335. }),
  336. ],
  337. };
  338. ```
  339. ### Source maps
  340. To enable CSS source maps, you'll need to pass the `sourceMap` option to the sass-loader _and_ the css-loader.
  341. **webpack.config.js**
  342. ```javascript
  343. module.exports = {
  344. devtool: 'source-map', // any "source-map"-like devtool is possible
  345. module: {
  346. rules: [
  347. {
  348. test: /\.scss$/,
  349. use: [
  350. 'style-loader',
  351. {
  352. loader: 'css-loader',
  353. options: {
  354. sourceMap: true,
  355. },
  356. },
  357. {
  358. loader: 'sass-loader',
  359. options: {
  360. sourceMap: true,
  361. },
  362. },
  363. ],
  364. },
  365. ],
  366. },
  367. };
  368. ```
  369. 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.
  370. ## Contributing
  371. Please take a moment to read our contributing guidelines if you haven't yet done so.
  372. [CONTRIBUTING](./.github/CONTRIBUTING.md)
  373. ## License
  374. [MIT](./LICENSE)
  375. [npm]: https://img.shields.io/npm/v/sass-loader.svg
  376. [npm-url]: https://npmjs.com/package/sass-loader
  377. [node]: https://img.shields.io/node/v/sass-loader.svg
  378. [node-url]: https://nodejs.org
  379. [deps]: https://david-dm.org/webpack-contrib/sass-loader.svg
  380. [deps-url]: https://david-dm.org/webpack-contrib/sass-loader
  381. [tests]: https://dev.azure.com/webpack-contrib/sass-loader/_apis/build/status/webpack-contrib.sass-loader?branchName=master
  382. [tests-url]: https://dev.azure.com/webpack-contrib/sass-loader/_build/latest?definitionId=21&branchName=master
  383. [cover]: https://codecov.io/gh/webpack-contrib/sass-loader/branch/master/graph/badge.svg
  384. [cover-url]: https://codecov.io/gh/webpack-contrib/sass-loader
  385. [chat]: https://badges.gitter.im/webpack/webpack.svg
  386. [chat-url]: https://gitter.im/webpack/webpack
  387. [size]: https://packagephobia.now.sh/badge?p=css-loader
  388. [size-url]: https://packagephobia.now.sh/result?p=css-loader