sass-loader 7.0.3 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ <a name="7.1.0"></a>
6
+ # [7.1.0](https://github.com/webpack-contrib/sass-loader/compare/v7.0.3...v7.1.0) (2018-08-01)
7
+
8
+
9
+ ### Features
10
+
11
+ * Make this package implementation-agnostic (#573) ([bed9fb5](https://github.com/webpack-contrib/sass-loader/commit/bed9fb5)), closes [#435](https://github.com/webpack-contrib/sass-loader/issues/435)
12
+
13
+
14
+
5
15
  <a name="7.0.3"></a>
6
16
  ## [7.0.3](https://github.com/webpack-contrib/sass-loader/compare/v7.0.2...v7.0.3) (2018-06-05)
7
17
 
package/README.md CHANGED
@@ -27,8 +27,14 @@ Looking for the webpack 1 loader? Check out the [archive/webpack-1 branch](https
27
27
  npm install sass-loader node-sass webpack --save-dev
28
28
  ```
29
29
 
30
- The sass-loader requires [node-sass](https://github.com/sass/node-sass) and [webpack](https://github.com/webpack)
31
- as [`peerDependency`](https://docs.npmjs.com/files/package.json#peerdependencies). Thus you are able to control the versions accurately.
30
+ The sass-loader requires [webpack](https://github.com/webpack) as a
31
+ [`peerDependency`](https://docs.npmjs.com/files/package.json#peerdependencies)
32
+ and it requires you to install either [Node Sass][] or [Dart Sass][] on your
33
+ own. This allows you to control the versions of all your dependencies, and to
34
+ choose which Sass implementation to use.
35
+
36
+ [Node Sass]: https://github.com/sass/node-sass
37
+ [Dart Sass]: http://sass-lang.com/dart-sass
32
38
 
33
39
  <h2 align="center">Examples</h2>
34
40
 
@@ -48,14 +54,14 @@ module.exports = {
48
54
  use: [
49
55
  "style-loader", // creates style nodes from JS strings
50
56
  "css-loader", // translates CSS into CommonJS
51
- "sass-loader" // compiles Sass to CSS
57
+ "sass-loader" // compiles Sass to CSS, using Node Sass by default
52
58
  ]
53
59
  }]
54
60
  }
55
61
  };
56
62
  ```
57
63
 
58
- You can also pass options directly to [node-sass](https://github.com/andrew/node-sass) by specifying an `options` property like this:
64
+ You can also pass options directly to [Node Sass][] or [Dart Sass][]:
59
65
 
60
66
  ```js
61
67
  // webpack.config.js
@@ -79,7 +85,54 @@ module.exports = {
79
85
  };
80
86
  ```
81
87
 
82
- See [node-sass](https://github.com/andrew/node-sass) for all available Sass options.
88
+ See [the Node Sass documentation](https://github.com/sass/node-sass/blob/master/README.md#options) for all available Sass options.
89
+
90
+ The special `implementation` option determines which implementation of Sass to
91
+ use. It takes either a [Node Sass][] or a [Dart Sass][] module. For example, to
92
+ use Dart Sass, you'd pass:
93
+
94
+ ```js
95
+ // ...
96
+ {
97
+ loader: "sass-loader",
98
+ options: {
99
+ implementation: require("sass")
100
+ }
101
+ }
102
+ // ...
103
+ ```
104
+
105
+ Note that when using Dart Sass, **synchronous compilation is twice as fast as
106
+ asynchronous compilation** by default, due to the overhead of asynchronous
107
+ callbacks. To avoid this overhead, you can use the
108
+ [`fibers`](https://www.npmjs.com/package/fibers) package to call asynchronous
109
+ importers from the synchronous code path. To enable this, pass the `Fiber` class
110
+ to the `fiber` option:
111
+
112
+ ```js
113
+ // webpack.config.js
114
+ const Fiber = require('fibers');
115
+
116
+ module.exports = {
117
+ ...
118
+ module: {
119
+ rules: [{
120
+ test: /\.scss$/,
121
+ use: [{
122
+ loader: "style-loader"
123
+ }, {
124
+ loader: "css-loader"
125
+ }, {
126
+ loader: "sass-loader",
127
+ options: {
128
+ implementation: require("sass"),
129
+ fiber: Fiber
130
+ }
131
+ }]
132
+ }]
133
+ }
134
+ };
135
+ ```
83
136
 
84
137
  ### In production
85
138
 
@@ -116,7 +169,7 @@ module.exports = {
116
169
 
117
170
  ### Imports
118
171
 
119
- webpack provides an [advanced mechanism to resolve files](https://webpack.js.org/concepts/module-resolution/). The sass-loader uses node-sass' 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:
172
+ 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:
120
173
 
121
174
  ```css
122
175
  @import "~bootstrap/dist/css/bootstrap";
package/lib/loader.js CHANGED
@@ -6,12 +6,9 @@ const formatSassError = require("./formatSassError");
6
6
  const webpackImporter = require("./webpackImporter");
7
7
  const normalizeOptions = require("./normalizeOptions");
8
8
  const pify = require("pify");
9
+ const semver = require("semver");
9
10
 
10
- // This queue makes sure node-sass leaves one thread available for executing
11
- // fs tasks when running the custom importer code.
12
- // This can be removed as soon as node-sass implements a fix for this.
13
- const threadPoolSize = process.env.UV_THREADPOOL_SIZE || 4;
14
- let asyncSassJobQueue = null;
11
+ let nodeSassJobQueue = null;
15
12
 
16
13
  /**
17
14
  * The sass-loader makes node-sass available to webpack modules.
@@ -20,19 +17,6 @@ let asyncSassJobQueue = null;
20
17
  * @param {string} content
21
18
  */
22
19
  function sassLoader(content) {
23
- if (asyncSassJobQueue === null) {
24
- const sass = require("node-sass");
25
- const sassVersion = /^(\d+)/.exec(require("node-sass/package.json").version).pop();
26
-
27
- if (Number(sassVersion) < 4) {
28
- throw new Error(
29
- "The installed version of `node-sass` is not compatible (expected: >= 4, actual: " + sassVersion + ")."
30
- );
31
- }
32
-
33
- asyncSassJobQueue = async.queue(sass.render, threadPoolSize - 1);
34
- }
35
-
36
20
  const callback = this.async();
37
21
  const isSync = typeof callback !== "function";
38
22
  const self = this;
@@ -59,8 +43,9 @@ function sassLoader(content) {
59
43
  return;
60
44
  }
61
45
 
62
- // start the actual rendering
63
- asyncSassJobQueue.push(options, (err, result) => {
46
+ const render = getRenderFuncFromSassImpl(options.implementation || require("node-sass"));
47
+
48
+ render(options, (err, result) => {
64
49
  if (err) {
65
50
  formatSassError(err, this.resourcePath);
66
51
  err.file && this.dependency(err.file);
@@ -92,4 +77,48 @@ function sassLoader(content) {
92
77
  });
93
78
  }
94
79
 
80
+ /**
81
+ * Verifies that the implementation and version of Sass is supported by this loader.
82
+ *
83
+ * @param {Object} module
84
+ * @returns {Function}
85
+ */
86
+ function getRenderFuncFromSassImpl(module) {
87
+ const info = module.info;
88
+ const components = info.split("\t");
89
+
90
+ if (components.length < 2) {
91
+ throw new Error("Unknown Sass implementation \"" + info + "\".");
92
+ }
93
+
94
+ const implementation = components[0];
95
+ const version = components[1];
96
+
97
+ if (!semver.valid(version)) {
98
+ throw new Error("Invalid Sass version \"" + version + "\".");
99
+ }
100
+
101
+ if (implementation === "dart-sass") {
102
+ if (!semver.satisfies(version, "^1.3.0")) {
103
+ throw new Error("Dart Sass version " + version + " is incompatible with ^1.3.0.");
104
+ }
105
+ return module.render.bind(module);
106
+ } else if (implementation === "node-sass") {
107
+ if (!semver.satisfies(version, "^4.0.0")) {
108
+ throw new Error("Node Sass version " + version + " is incompatible with ^4.0.0.");
109
+ }
110
+ // There is an issue with node-sass when async custom importers are used
111
+ // See https://github.com/sass/node-sass/issues/857#issuecomment-93594360
112
+ // We need to use a job queue to make sure that one thread is always available to the UV lib
113
+ if (nodeSassJobQueue === null) {
114
+ const threadPoolSize = Number(process.env.UV_THREADPOOL_SIZE || 4);
115
+
116
+ nodeSassJobQueue = async.queue(module.render.bind(module), threadPoolSize - 1);
117
+ }
118
+
119
+ return nodeSassJobQueue.push.bind(nodeSassJobQueue);
120
+ }
121
+ throw new Error("Unknown Sass implementation \"" + implementation + "\".");
122
+ }
123
+
95
124
  module.exports = sassLoader;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sass-loader",
3
- "version": "7.0.3",
3
+ "version": "7.1.0",
4
4
  "description": "Sass loader for webpack",
5
5
  "author": "J. Tangelder",
6
6
  "license": "MIT",
@@ -30,7 +30,8 @@
30
30
  "loader-utils": "^1.0.1",
31
31
  "lodash.tail": "^4.1.1",
32
32
  "neo-async": "^2.5.0",
33
- "pify": "^3.0.0"
33
+ "pify": "^3.0.0",
34
+ "semver": "^5.5.0"
34
35
  },
35
36
  "devDependencies": {
36
37
  "bootstrap-sass": "^3.3.5",
@@ -44,6 +45,7 @@
44
45
  "node-sass": "^4.5.0",
45
46
  "nyc": "^11.0.2",
46
47
  "raw-loader": "^0.5.1",
48
+ "sass": "^1.3.0",
47
49
  "should": "^11.2.0",
48
50
  "standard-version": "^4.2.0",
49
51
  "style-loader": "^0.18.2",