web 3d图形渲染器
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.

668 lines
18 KiB

  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 sass webpack --save-dev
  22. ```
  23. `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).
  24. This allows you to control the versions of all your dependencies, and to choose which Sass implementation to use.
  25. > ℹ️ We recommend using [Dart Sass](https://github.com/sass/dart-sass).
  26. > ⚠ [Node Sass](https://github.com/sass/node-sass) does not work with [Yarn PnP](https://classic.yarnpkg.com/en/docs/pnp/) feature.
  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 configuration. For example:
  29. **app.js**
  30. ```js
  31. import "./style.scss";
  32. ```
  33. **style.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. Finally run `webpack` via your preferred method.
  61. ### Resolving `import` at-rules
  62. 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. ```scss
  65. @import "~bootstrap";
  66. ```
  67. It's important to only prepend it with `~`, because `~/` resolves to the home directory.
  68. Webpack needs to distinguish between `bootstrap` and `~bootstrap` because CSS and Sass files have no special syntax for importing relative files.
  69. Writing `@import "style.scss"` is the same as `@import "./style.scss";`
  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 `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. | Name | Type | Default | Description |
  80. | :---------------------------------------: | :------------------: | :-------------------------------------: | :---------------------------------------------------------------- |
  81. | **[`implementation`](#implementation)** | `{Object}` | `sass` | Setup Sass implementation to use. |
  82. | **[`sassOptions`](#sassoptions)** | `{Object\|Function}` | defaults values for Sass implementation | Options for Sass. |
  83. | **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps. |
  84. | **[`additionalData`](#additionaldata)** | `{String\|Function}` | `undefined` | Prepends/Appends `Sass`/`SCSS` code before the actual entry file. |
  85. | **[`webpackImporter`](#webpackimporter)** | `{Boolean}` | `true` | Enables/Disables the default Webpack importer. |
  86. ### `implementation`
  87. Type: `Object`
  88. Default: `sass`
  89. The special `implementation` option determines which implementation of Sass to use.
  90. By default the loader resolve the implementation based on your dependencies.
  91. Just add required implementation to `package.json` (`sass` or `node-sass` package) and install dependencies.
  92. Example where the `sass-loader` loader uses the `sass` (`dart-sass`) implementation:
  93. **package.json**
  94. ```json
  95. {
  96. "devDependencies": {
  97. "sass-loader": "^7.2.0",
  98. "sass": "^1.22.10"
  99. }
  100. }
  101. ```
  102. Example where the `sass-loader` loader uses the `node-sass` implementation:
  103. **package.json**
  104. ```json
  105. {
  106. "devDependencies": {
  107. "sass-loader": "^7.2.0",
  108. "node-sass": "^5.0.0"
  109. }
  110. }
  111. ```
  112. Beware the situation when `node-sass` and `sass` were installed! By default the `sass-loader` prefers `sass`.
  113. In order to avoid this situation you can use the `implementation` option.
  114. The `implementation` options either accepts `sass` (`Dart Sass`) or `node-sass` as a module.
  115. For example, to use Dart Sass, you'd pass:
  116. ```js
  117. module.exports = {
  118. module: {
  119. rules: [
  120. {
  121. test: /\.s[ac]ss$/i,
  122. use: [
  123. "style-loader",
  124. "css-loader",
  125. {
  126. loader: "sass-loader",
  127. options: {
  128. // Prefer `dart-sass`
  129. implementation: require("sass"),
  130. },
  131. },
  132. ],
  133. },
  134. ],
  135. },
  136. };
  137. ```
  138. 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.
  139. 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.
  140. 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).
  141. **package.json**
  142. ```json
  143. {
  144. "devDependencies": {
  145. "sass-loader": "^7.2.0",
  146. "sass": "^1.22.10",
  147. "fibers": "^4.0.1"
  148. }
  149. }
  150. ```
  151. You can disable automatically injecting the [`fibers`](https://github.com/laverdet/node-fibers) package by passing a `false` value for the `sassOptions.fiber` option.
  152. **webpack.config.js**
  153. ```js
  154. module.exports = {
  155. module: {
  156. rules: [
  157. {
  158. test: /\.s[ac]ss$/i,
  159. use: [
  160. "style-loader",
  161. "css-loader",
  162. {
  163. loader: "sass-loader",
  164. options: {
  165. implementation: require("sass"),
  166. sassOptions: {
  167. fiber: false,
  168. },
  169. },
  170. },
  171. ],
  172. },
  173. ],
  174. },
  175. };
  176. ```
  177. You can also pass the `fiber` value using this code:
  178. **webpack.config.js**
  179. ```js
  180. module.exports = {
  181. module: {
  182. rules: [
  183. {
  184. test: /\.s[ac]ss$/i,
  185. use: [
  186. "style-loader",
  187. "css-loader",
  188. {
  189. loader: "sass-loader",
  190. options: {
  191. implementation: require("sass"),
  192. sassOptions: {
  193. fiber: require("fibers"),
  194. },
  195. },
  196. },
  197. ],
  198. },
  199. ],
  200. },
  201. };
  202. ```
  203. ### `sassOptions`
  204. Type: `Object|Function`
  205. Default: defaults values for Sass implementation
  206. Options for [Dart Sass](http://sass-lang.com/dart-sass) or [Node Sass](https://github.com/sass/node-sass) implementation.
  207. > ℹ️ The `indentedSyntax` option has `true` value for the `sass` extension.
  208. > ℹ️ Options such as `data` and `file` are unavailable and will be ignored.
  209. > ℹ We recommend not to set the `outFile`, `sourceMapContents`, `sourceMapEmbed`, `sourceMapRoot` options because `sass-loader` automatically sets these options when the `sourceMap` option is `true`.
  210. > ℹ️ 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.
  211. There is a slight difference between the `sass` (`dart-sass`) and `node-sass` options.
  212. Please consult documentation before using them:
  213. - [Dart Sass documentation](https://github.com/sass/dart-sass#javascript-api) for all available `sass` options.
  214. - [Node Sass documentation](https://github.com/sass/node-sass/#options) for all available `node-sass` options.
  215. #### `Object`
  216. Use and object for the Sass implementation setup.
  217. **webpack.config.js**
  218. ```js
  219. module.exports = {
  220. module: {
  221. rules: [
  222. {
  223. test: /\.s[ac]ss$/i,
  224. use: [
  225. "style-loader",
  226. "css-loader",
  227. {
  228. loader: "sass-loader",
  229. options: {
  230. sassOptions: {
  231. indentWidth: 4,
  232. includePaths: ["absolute/path/a", "absolute/path/b"],
  233. },
  234. },
  235. },
  236. ],
  237. },
  238. ],
  239. },
  240. };
  241. ```
  242. #### `Function`
  243. Allows to setup the Sass implementation by setting different options based on the loader context.
  244. ```js
  245. module.exports = {
  246. module: {
  247. rules: [
  248. {
  249. test: /\.s[ac]ss$/i,
  250. use: [
  251. "style-loader",
  252. "css-loader",
  253. {
  254. loader: "sass-loader",
  255. options: {
  256. sassOptions: (loaderContext) => {
  257. // More information about available properties https://webpack.js.org/api/loaders/
  258. const { resourcePath, rootContext } = loaderContext;
  259. const relativePath = path.relative(rootContext, resourcePath);
  260. if (relativePath === "styles/foo.scss") {
  261. return {
  262. includePaths: ["absolute/path/c", "absolute/path/d"],
  263. };
  264. }
  265. return {
  266. includePaths: ["absolute/path/a", "absolute/path/b"],
  267. };
  268. },
  269. },
  270. },
  271. ],
  272. },
  273. ],
  274. },
  275. };
  276. ```
  277. ### `sourceMap`
  278. Type: `Boolean`
  279. Default: depends on the `compiler.devtool` value
  280. Enables/Disables generation of source maps.
  281. By default generation of source maps depends on the [`devtool`](https://webpack.js.org/configuration/devtool/) option.
  282. All values enable source map generation except `eval` and `false` value.
  283. > ℹ If a `true` the `sourceMap`, `sourceMapRoot`, `sourceMapEmbed`, `sourceMapContents` and `omitSourceMapUrl` from `sassOptions` will be ignored.
  284. **webpack.config.js**
  285. ```js
  286. module.exports = {
  287. module: {
  288. rules: [
  289. {
  290. test: /\.s[ac]ss$/i,
  291. use: [
  292. "style-loader",
  293. {
  294. loader: "css-loader",
  295. options: {
  296. sourceMap: true,
  297. },
  298. },
  299. {
  300. loader: "sass-loader",
  301. options: {
  302. sourceMap: true,
  303. },
  304. },
  305. ],
  306. },
  307. ],
  308. },
  309. };
  310. ```
  311. > ℹ In some rare cases `node-sass` can output invalid source maps (it is a `node-sass` bug).
  312. > > 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`.
  313. **webpack.config.js**
  314. ```js
  315. module.exports = {
  316. module: {
  317. rules: [
  318. {
  319. test: /\.s[ac]ss$/i,
  320. use: [
  321. "style-loader",
  322. "css-loader",
  323. {
  324. loader: "sass-loader",
  325. options: {
  326. sourceMap: true,
  327. sassOptions: {
  328. outputStyle: "compressed",
  329. },
  330. },
  331. },
  332. ],
  333. },
  334. ],
  335. },
  336. };
  337. ```
  338. ### `additionalData`
  339. Type: `String|Function`
  340. Default: `undefined`
  341. Prepends `Sass`/`SCSS` code before the actual entry file.
  342. In this case, the `sass-loader` will not override the `data` option but just **prepend** the entry's content.
  343. This is especially useful when some of your Sass variables depend on the environment:
  344. #### `String`
  345. ```js
  346. module.exports = {
  347. module: {
  348. rules: [
  349. {
  350. test: /\.s[ac]ss$/i,
  351. use: [
  352. "style-loader",
  353. "css-loader",
  354. {
  355. loader: "sass-loader",
  356. options: {
  357. additionalData: "$env: " + process.env.NODE_ENV + ";",
  358. },
  359. },
  360. ],
  361. },
  362. ],
  363. },
  364. };
  365. ```
  366. #### `Function`
  367. ##### Sync
  368. ```js
  369. module.exports = {
  370. module: {
  371. rules: [
  372. {
  373. test: /\.s[ac]ss$/i,
  374. use: [
  375. "style-loader",
  376. "css-loader",
  377. {
  378. loader: "sass-loader",
  379. options: {
  380. additionalData: (content, loaderContext) => {
  381. // More information about available properties https://webpack.js.org/api/loaders/
  382. const { resourcePath, rootContext } = loaderContext;
  383. const relativePath = path.relative(rootContext, resourcePath);
  384. if (relativePath === "styles/foo.scss") {
  385. return "$value: 100px;" + content;
  386. }
  387. return "$value: 200px;" + content;
  388. },
  389. },
  390. },
  391. ],
  392. },
  393. ],
  394. },
  395. };
  396. ```
  397. ##### Async
  398. ```js
  399. module.exports = {
  400. module: {
  401. rules: [
  402. {
  403. test: /\.s[ac]ss$/i,
  404. use: [
  405. "style-loader",
  406. "css-loader",
  407. {
  408. loader: "sass-loader",
  409. options: {
  410. additionalData: async (content, loaderContext) => {
  411. // More information about available properties https://webpack.js.org/api/loaders/
  412. const { resourcePath, rootContext } = loaderContext;
  413. const relativePath = path.relative(rootContext, resourcePath);
  414. if (relativePath === "styles/foo.scss") {
  415. return "$value: 100px;" + content;
  416. }
  417. return "$value: 200px;" + content;
  418. },
  419. },
  420. },
  421. ],
  422. },
  423. ],
  424. },
  425. };
  426. ```
  427. ### `webpackImporter`
  428. Type: `Boolean`
  429. Default: `true`
  430. Enables/Disables the default Webpack importer.
  431. This can improve performance in some cases. Use it with caution because aliases and `@import` at-rules starting with `~` will not work.
  432. You can pass own `importer` to solve this (see [`importer docs`](https://github.com/sass/node-sass#importer--v200---experimental)).
  433. **webpack.config.js**
  434. ```js
  435. module.exports = {
  436. module: {
  437. rules: [
  438. {
  439. test: /\.s[ac]ss$/i,
  440. use: [
  441. "style-loader",
  442. "css-loader",
  443. {
  444. loader: "sass-loader",
  445. options: {
  446. webpackImporter: false,
  447. },
  448. },
  449. ],
  450. },
  451. ],
  452. },
  453. };
  454. ```
  455. ## Examples
  456. ### Extracts CSS into separate files
  457. 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.
  458. There are two possibilities to extract a style sheet from the bundle:
  459. - [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)
  460. - [extract-loader](https://github.com/peerigon/extract-loader) (simpler, but specialized on the css-loader's output)
  461. **webpack.config.js**
  462. ```js
  463. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  464. module.exports = {
  465. module: {
  466. rules: [
  467. {
  468. test: /\.s[ac]ss$/i,
  469. use: [
  470. // fallback to style-loader in development
  471. process.env.NODE_ENV !== "production"
  472. ? "style-loader"
  473. : MiniCssExtractPlugin.loader,
  474. "css-loader",
  475. "sass-loader",
  476. ],
  477. },
  478. ],
  479. },
  480. plugins: [
  481. new MiniCssExtractPlugin({
  482. // Options similar to the same options in webpackOptions.output
  483. // both options are optional
  484. filename: "[name].css",
  485. chunkFilename: "[id].css",
  486. }),
  487. ],
  488. };
  489. ```
  490. ### Source maps
  491. Enables/Disables generation of source maps.
  492. To enable CSS source maps, you'll need to pass the `sourceMap` option to the `sass-loader` _and_ the css-loader.
  493. **webpack.config.js**
  494. ```javascript
  495. module.exports = {
  496. devtool: "source-map", // any "source-map"-like devtool is possible
  497. module: {
  498. rules: [
  499. {
  500. test: /\.s[ac]ss$/i,
  501. use: [
  502. "style-loader",
  503. {
  504. loader: "css-loader",
  505. options: {
  506. sourceMap: true,
  507. },
  508. },
  509. {
  510. loader: "sass-loader",
  511. options: {
  512. sourceMap: true,
  513. },
  514. },
  515. ],
  516. },
  517. ],
  518. },
  519. };
  520. ```
  521. 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.
  522. ## Contributing
  523. Please take a moment to read our contributing guidelines if you haven't yet done so.
  524. [CONTRIBUTING](./.github/CONTRIBUTING.md)
  525. ## License
  526. [MIT](./LICENSE)
  527. [npm]: https://img.shields.io/npm/v/sass-loader.svg
  528. [npm-url]: https://npmjs.com/package/sass-loader
  529. [node]: https://img.shields.io/node/v/sass-loader.svg
  530. [node-url]: https://nodejs.org
  531. [deps]: https://david-dm.org/webpack-contrib/sass-loader.svg
  532. [deps-url]: https://david-dm.org/webpack-contrib/sass-loader
  533. [tests]: https://github.com/webpack-contrib/sass-loader/workflows/sass-loader/badge.svg
  534. [tests-url]: https://github.com/webpack-contrib/sass-loader/actions
  535. [cover]: https://codecov.io/gh/webpack-contrib/sass-loader/branch/master/graph/badge.svg
  536. [cover-url]: https://codecov.io/gh/webpack-contrib/sass-loader
  537. [chat]: https://badges.gitter.im/webpack/webpack.svg
  538. [chat-url]: https://gitter.im/webpack/webpack
  539. [size]: https://packagephobia.now.sh/badge?p=sass-loader
  540. [size-url]: https://packagephobia.now.sh/result?p=sass-loader