Skip to content

Commit

Permalink
feat: Remove node-sass from peerDependencies (#533)
Browse files Browse the repository at this point in the history
- Only require("node-sass") on runtime when loader has been called
- Based on feedback from #533 and facebook/create-react-app#4195

BREAKING CHANGE: 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.
  • Loading branch information
Timer authored and jhnns committed Apr 12, 2018
1 parent eb5a555 commit 6439cef
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 5 deletions.
4 changes: 2 additions & 2 deletions .nycrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"lib/**/*.js"
],
"lines": 97,
"statements": 91,
"statements": 97,
"functions": 100,
"branches": 89,
"branches": 91,
"check-coverage": true
}
25 changes: 23 additions & 2 deletions lib/loader.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use strict";

const sass = require("node-sass");
const path = require("path");
const async = require("neo-async");
const formatSassError = require("./formatSassError");
Expand All @@ -12,7 +11,7 @@ const pify = require("pify");
// fs tasks when running the custom importer code.
// This can be removed as soon as node-sass implements a fix for this.
const threadPoolSize = process.env.UV_THREADPOOL_SIZE || 4;
const asyncSassJobQueue = async.queue(sass.render, threadPoolSize - 1);
let asyncSassJobQueue = null;

/**
* The sass-loader makes node-sass available to webpack modules.
Expand All @@ -21,6 +20,28 @@ const asyncSassJobQueue = async.queue(sass.render, threadPoolSize - 1);
* @param {string} content
*/
function sassLoader(content) {
if (asyncSassJobQueue === null) {
let sass;
let sassVersion;

try {
sass = require("node-sass");
sassVersion = /^(\d+)/.exec(require("node-sass/package.json").version).pop();
} catch (e) {
throw new Error(
"`sass-loader` requires `node-sass` >=4. Please install a compatible version."
);
}

if (Number(sassVersion) < 4) {
throw new Error(
"The installed version of `node-sass` is not compatible (expected: >= 4, actual: " + sassVersion + ")."
);
}

asyncSassJobQueue = async.queue(sass.render, threadPoolSize - 1);
}

const callback = this.async();
const isSync = typeof callback !== "function";
const self = this;
Expand Down
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"eslint-plugin-jsdoc": "^2.4.0",
"file-loader": "^0.11.2",
"mocha": "^3.0.2",
"mock-require": "^3.0.1",
"node-sass": "^4.5.0",
"nyc": "^11.0.2",
"raw-loader": "^0.5.1",
Expand All @@ -54,7 +55,6 @@
"node": ">= 6.9.0 || >= 8.9.0"
},
"peerDependencies": {
"node-sass": "^4.0.0",
"webpack": "^3.0.0 || ^4.0.0"
},
"keywords": [
Expand Down
35 changes: 35 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const customFunctions = require("./tools/customFunctions.js");
const pathToSassLoader = require.resolve("../lib/loader.js");
const testLoader = require("./tools/testLoader");
const sassLoader = require(pathToSassLoader);
const mockRequire = require("mock-require");

const CR = /\r/g;
const syntaxStyles = ["scss", "sass"];
Expand Down Expand Up @@ -256,6 +257,40 @@ describe("sass-loader", () => {
done();
});
});
it("should output a message when `node-sass` is missing", (done) => {
mockRequire.reRequire(pathToSassLoader);
const module = require("module");
const originalResolve = module._resolveFilename;

module._resolveFilename = function (filename) {
if (!filename.match(/node-sass/)) {
return originalResolve.apply(this, arguments);
}
const err = new Error();

err.code = "MODULE_NOT_FOUND";
throw err;
};
runWebpack({
entry: pathToSassLoader + "!" + pathToErrorFile
}, (err) => {
module._resolveFilename = originalResolve;
mockRequire.reRequire("node-sass");
err.message.should.match(/Please install a compatible version/);
done();
});
});
it("should output a message when `node-sass` is an incompatible version", (done) => {
mockRequire.reRequire(pathToSassLoader);
mockRequire("node-sass/package.json", { version: "3.0.0" });
runWebpack({
entry: pathToSassLoader + "!" + pathToErrorFile
}, (err) => {
mockRequire.stop("node-sass");
err.message.should.match(/The installed version of `node-sass` is not compatible/);
done();
});
});
});
});

Expand Down

0 comments on commit 6439cef

Please sign in to comment.