sass-loader 7.0.0 → 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,47 @@
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
+
15
+ <a name="7.0.3"></a>
16
+ ## [7.0.3](https://github.com/webpack-contrib/sass-loader/compare/v7.0.2...v7.0.3) (2018-06-05)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * Bare imports not working sometimes (#579) ([c348281](https://github.com/webpack-contrib/sass-loader/commit/c348281)), closes [#566](https://github.com/webpack-contrib/sass-loader/issues/566)
22
+
23
+
24
+
25
+ <a name="7.0.2"></a>
26
+ ## [7.0.2](https://github.com/webpack-contrib/sass-loader/compare/v7.0.1...v7.0.2) (2018-06-02)
27
+
28
+
29
+ ### Bug Fixes
30
+
31
+ * Errors being swallowed when trying to load node-sass (#576) ([6dfb274](https://github.com/webpack-contrib/sass-loader/commit/6dfb274)), closes [#563](https://github.com/webpack-contrib/sass-loader/issues/563)
32
+ * Report error to user for problems loading node-sass (#562) ([2529c07](https://github.com/webpack-contrib/sass-loader/commit/2529c07))
33
+
34
+
35
+
36
+ <a name="7.0.1"></a>
37
+ ## [7.0.1](https://github.com/webpack-contrib/sass-loader/compare/v7.0.0...v7.0.1) (2018-04-13)
38
+
39
+
40
+ ### Bug Fixes
41
+
42
+ * Wrong import precedence (#557) ([f4eeff1](https://github.com/webpack-contrib/sass-loader/commit/f4eeff1))
43
+
44
+
45
+
5
46
  <a name="7.0.0"></a>
6
47
  # [7.0.0](https://github.com/webpack-contrib/sass-loader/compare/v6.0.7...v7.0.0) (2018-04-13)
7
48
 
@@ -14,6 +55,7 @@ All notable changes to this project will be documented in this file. See [standa
14
55
 
15
56
  ### BREAKING CHANGES
16
57
 
58
+ * Drop official node 4 support
17
59
  * This slightly changes the resolving algorithm. Should not break in normal usage, but might break in complex configurations.
18
60
  * The sass-loader throws an error at runtime now and refuses to compile if the peer dependency is wrong. This could break applications where npm's peer dependency warning was just ignored.
19
61
 
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
  <p>Loads a Sass/SCSS file and compiles it to CSS.</p>
19
19
  </div>
20
20
 
21
- Use the [css-loader](https://github.com/webpack-contrib/css-loader) or the [raw-loader](https://github.com/webpack-contrib/raw-loader) to turn it into a JS module and the [ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) to extract it into a separate file.
21
+ Use the [css-loader](https://github.com/webpack-contrib/css-loader) or the [raw-loader](https://github.com/webpack-contrib/raw-loader) to turn it into a JS module and the [MiniCssExtractPlugin](https://github.com/webpack-contrib/mini-css-extract-plugin) to extract it into a separate file.
22
22
  Looking for the webpack 1 loader? Check out the [archive/webpack-1 branch](https://github.com/webpack-contrib/sass-loader/tree/archive/webpack-1).
23
23
 
24
24
  <h2 align="center">Install</h2>
@@ -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
 
@@ -38,6 +44,25 @@ Chain the sass-loader with the [css-loader](https://github.com/webpack-contrib/c
38
44
  npm install style-loader css-loader --save-dev
39
45
  ```
40
46
 
47
+ ```js
48
+ // webpack.config.js
49
+ module.exports = {
50
+ ...
51
+ module: {
52
+ rules: [{
53
+ test: /\.scss$/,
54
+ use: [
55
+ "style-loader", // creates style nodes from JS strings
56
+ "css-loader", // translates CSS into CommonJS
57
+ "sass-loader" // compiles Sass to CSS, using Node Sass by default
58
+ ]
59
+ }]
60
+ }
61
+ };
62
+ ```
63
+
64
+ You can also pass options directly to [Node Sass][] or [Dart Sass][]:
65
+
41
66
  ```js
42
67
  // webpack.config.js
43
68
  module.exports = {
@@ -46,21 +71,48 @@ module.exports = {
46
71
  rules: [{
47
72
  test: /\.scss$/,
48
73
  use: [{
49
- loader: "style-loader" // creates style nodes from JS strings
74
+ loader: "style-loader"
50
75
  }, {
51
- loader: "css-loader" // translates CSS into CommonJS
76
+ loader: "css-loader"
52
77
  }, {
53
- loader: "sass-loader" // compiles Sass to CSS
78
+ loader: "sass-loader",
79
+ options: {
80
+ includePaths: ["absolute/path/a", "absolute/path/b"]
81
+ }
54
82
  }]
55
83
  }]
56
84
  }
57
85
  };
58
86
  ```
59
87
 
60
- You can also pass options directly to [node-sass](https://github.com/andrew/node-sass) by specifying an `options` property like this:
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:
61
111
 
62
112
  ```js
63
113
  // webpack.config.js
114
+ const Fiber = require('fibers');
115
+
64
116
  module.exports = {
65
117
  ...
66
118
  module: {
@@ -73,7 +125,8 @@ module.exports = {
73
125
  }, {
74
126
  loader: "sass-loader",
75
127
  options: {
76
- includePaths: ["absolute/path/a", "absolute/path/b"]
128
+ implementation: require("sass"),
129
+ fiber: Fiber
77
130
  }
78
131
  }]
79
132
  }]
@@ -81,38 +134,33 @@ module.exports = {
81
134
  };
82
135
  ```
83
136
 
84
- See [node-sass](https://github.com/andrew/node-sass) for all available Sass options.
85
-
86
137
  ### In production
87
138
 
88
- Usually, it's recommended to extract the style sheets into a dedicated file in production using the [ExtractTextPlugin](https://github.com/webpack-contrib/extract-text-webpack-plugin). This way your styles are not dependent on JavaScript:
139
+ Usually, it's recommended to extract the style sheets into a dedicated file in production using the [MiniCssExtractPlugin](https://github.com/webpack-contrib/mini-css-extract-plugin). This way your styles are not dependent on JavaScript:
89
140
 
90
141
  ```js
91
- const ExtractTextPlugin = require("extract-text-webpack-plugin");
92
-
93
- const extractSass = new ExtractTextPlugin({
94
- filename: "[name].[contenthash].css",
95
- disable: process.env.NODE_ENV === "development"
96
- });
142
+ const MiniCssExtractPlugin = require("mini-css-extract-plugin");
97
143
 
98
144
  module.exports = {
99
145
  ...
100
146
  module: {
101
147
  rules: [{
102
148
  test: /\.scss$/,
103
- use: extractSass.extract({
104
- use: [{
105
- loader: "css-loader"
106
- }, {
107
- loader: "sass-loader"
108
- }],
109
- // use style-loader in development
110
- fallback: "style-loader"
111
- })
149
+ use: [
150
+ // fallback to style-loader in development
151
+ process.env.NODE_ENV !== 'production' ? 'style-loader' : MiniCssExtractPlugin.loader,
152
+ "css-loader",
153
+ "sass-loader"
154
+ ]
112
155
  }]
113
156
  },
114
157
  plugins: [
115
- extractSass
158
+ new MiniCssExtractPlugin({
159
+ // Options similar to the same options in webpackOptions.output
160
+ // both options are optional
161
+ filename: "[name].css",
162
+ chunkFilename: "[id].css"
163
+ })
116
164
  ]
117
165
  };
118
166
  ```
@@ -121,7 +169,7 @@ module.exports = {
121
169
 
122
170
  ### Imports
123
171
 
124
- 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:
125
173
 
126
174
  ```css
127
175
  @import "~bootstrap/dist/css/bootstrap";
@@ -3,12 +3,12 @@
3
3
  const path = require("path");
4
4
  const utils = require("loader-utils");
5
5
 
6
- const matchModuleImport = /^~([^\/]+|@[^\/]+[\/][^\/]+)$/g;
6
+ const matchModuleImport = /^~([^\/]+|@[^\/]+[\/][^\/]+)$/;
7
7
 
8
8
  /**
9
9
  * When libsass tries to resolve an import, it uses a special algorithm.
10
10
  * Since the sass-loader uses webpack to resolve the modules, we need to simulate that algorithm. This function
11
- * returns an array of import paths to try. The first entry in the array is always the original url
11
+ * returns an array of import paths to try. The last entry in the array is always the original url
12
12
  * to enable straight-forward webpack.config aliases.
13
13
  *
14
14
  * @param {string} url
@@ -21,7 +21,7 @@ function importsToResolve(url) {
21
21
  const ext = path.extname(request);
22
22
 
23
23
  if (matchModuleImport.test(url)) {
24
- return [url, request];
24
+ return [request, url];
25
25
  }
26
26
 
27
27
  // libsass' import algorithm works like this:
@@ -33,7 +33,7 @@ function importsToResolve(url) {
33
33
  return [];
34
34
  }
35
35
  if (ext === ".scss" || ext === ".sass") {
36
- return [url, request];
36
+ return [request, url];
37
37
  }
38
38
 
39
39
  // In case there is no file extension...
@@ -43,17 +43,17 @@ function importsToResolve(url) {
43
43
 
44
44
  if (basename.charAt(0) === "_") {
45
45
  return [
46
- url,
47
- `${ request }.scss`, `${ request }.sass`, `${ request }.css`
46
+ `${ request }.scss`, `${ request }.sass`, `${ request }.css`,
47
+ url
48
48
  ];
49
49
  }
50
50
 
51
51
  const dirname = path.dirname(request);
52
52
 
53
53
  return [
54
- url,
55
54
  `${ dirname }/_${ basename }.scss`, `${ dirname }/_${ basename }.sass`, `${ dirname }/_${ basename }.css`,
56
- `${ request }.scss`, `${ request }.sass`, `${ request }.css`
55
+ `${ request }.scss`, `${ request }.sass`, `${ request }.css`,
56
+ url
57
57
  ];
58
58
  }
59
59
 
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,28 +17,6 @@ let asyncSassJobQueue = null;
20
17
  * @param {string} content
21
18
  */
22
19
  function sassLoader(content) {
23
- if (asyncSassJobQueue === null) {
24
- let sass;
25
- let sassVersion;
26
-
27
- try {
28
- sass = require("node-sass");
29
- sassVersion = /^(\d+)/.exec(require("node-sass/package.json").version).pop();
30
- } catch (e) {
31
- throw new Error(
32
- "`sass-loader` requires `node-sass` >=4. Please install a compatible version."
33
- );
34
- }
35
-
36
- if (Number(sassVersion) < 4) {
37
- throw new Error(
38
- "The installed version of `node-sass` is not compatible (expected: >= 4, actual: " + sassVersion + ")."
39
- );
40
- }
41
-
42
- asyncSassJobQueue = async.queue(sass.render, threadPoolSize - 1);
43
- }
44
-
45
20
  const callback = this.async();
46
21
  const isSync = typeof callback !== "function";
47
22
  const self = this;
@@ -68,8 +43,9 @@ function sassLoader(content) {
68
43
  return;
69
44
  }
70
45
 
71
- // start the actual rendering
72
- asyncSassJobQueue.push(options, (err, result) => {
46
+ const render = getRenderFuncFromSassImpl(options.implementation || require("node-sass"));
47
+
48
+ render(options, (err, result) => {
73
49
  if (err) {
74
50
  formatSassError(err, this.resourcePath);
75
51
  err.file && this.dependency(err.file);
@@ -101,4 +77,48 @@ function sassLoader(content) {
101
77
  });
102
78
  }
103
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
+
104
124
  module.exports = sassLoader;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sass-loader",
3
- "version": "7.0.0",
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",