-
-
Notifications
You must be signed in to change notification settings - Fork 430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor(package): remove node-sass
(peerDependencies
)
#533
Conversation
Codecov Report
@@ Coverage Diff @@
## master #533 +/- ##
==========================================
+ Coverage 97.43% 97.58% +0.14%
==========================================
Files 6 6
Lines 117 124 +7
==========================================
+ Hits 114 121 +7
Misses 3 3
Continue to review full report at Codecov.
|
lib/loader.js
Outdated
const sass = require("node-sass"); | ||
const sassVersion = require("node-sass/package.json").version; | ||
|
||
if (/^4[.]/.test(sassVersion)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think better to check >= 4
, maybe in future we can have 5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, please check for greater than
if (Number(sassVersion[0]) >= 4) {}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we're not compatible with the node-sass
v5 API?
lib/loader.js
Outdated
const sass = require("node-sass"); | ||
const sassVersion = require("node-sass/package.json").version; | ||
|
||
if (/^4[.]/.test(sassVersion)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, please check for greater than
if (Number(sassVersion[0]) >= 4) {}
lib/loader.js
Outdated
if (/^4[.]/.test(sassVersion)) { | ||
asyncSassJobQueue = async.queue(sass.render, threadPoolSize - 1); | ||
} else { | ||
loadingError = new Error("The installed version of \`node-sass\` is not compatible (expected: 4.x, actual: " + sassVersion + ")."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw
here and catch the {Error}
in (L27+) instead of an assignment please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. This will work better when we add support for things other than node-sass
or something else bombs out.
node-sass
peerdepnode-sass
(peerDependencies
)
Updated with concerns. |
@@ -12,7 +11,21 @@ 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let move this variables before asyncSassJobQueue = async.queue(sass.render, threadPoolSize - 1);
, it don't have sense in top of file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. I should've thought of this. 😝
lib/loader.js
Outdated
@@ -35,6 +49,15 @@ function sassLoader(content) { | |||
throw new Error("Synchronous compilation is not supported anymore. See https://github.com/webpack-contrib/sass-loader/issues/333"); | |||
} | |||
|
|||
if (asyncSassJobQueue == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last note 😄 Seems we can avoid this block, just throw error in catch
instead loadingError = e;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it safe to throw an error at require-time? I figured you'd want them surfaced as webpack compiler errors -- I'm not sure how this works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Timer Yep, it is not compilation error. It does not make sense because all attempts to compile sass/scss
return error in callback. I think better throw error as fast as possible. @michael-ciniawsky what do you think about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't webpack's bail
option cause it to stop on the first? I'm no expert here, just asking questions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think this block is redundant with the try/catch
(L13+) and version check, but not 💯 😛
- let loadingError = null;
try {
const sass = require("node-sass");
const sassVersion = require("node-sass/package.json").version;
if (Number(sassVersion[0]) >= 4) {
// This queue makes sure node-sass leaves one thread available for executing
// 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;
asyncSassJobQueue = async.queue(sass.render, threadPoolSize - 1);
+ // Maybe not needed (see comment)
+ if (asyncSassJobQueue === null) {
+ throw new Error("Please install `node-sass >= 4.x` to use `sass-loader`.")
+ }
} else {
throw new Error("The installed version of \`node-sass\` is not compatible (expected: >=4.x, actual: " + sassVersion + ").");
}
} catch (err) {
+ // Catches 'both' (first thrown) {Error} thrown in the try block
+ callback(err);
+ return;
}
...
- if (asyncSassJobQueue == null) {
- if (loadingError) {
- callback(loadingError);
- return;
- }
- callback(new Error("Please install `node-sass >=4.x` to use `sass-loader`."));
- return;
- }
But what's the exact reason for asyncQueue === null
, in case node-sass < 4
? And isn't this basically a redundant (the same check) as if (Number(sassVersion[0]) >= 4)
again ? Please elaborate what could possibly fail when queueing sass.render
for thread pooling, since I'm not that familiar with node-sass
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Callback isn't available where you've added it, that's where the package itself is being evaluated.
AFAIK, it's generally poor practice to make a require throw an exception, but this might be normal practice in the webpack world.
The loadingError
is to store the error until the plugin is used at compile time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooops... 😛you're right. What alternatives do we have to make this less confusing and more compact ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll come up with something.
@michael-ciniawsky I went ahead and moved the loading of a compiler into its own file and created placeholder logic for expanding beyond one compiler. This keeps the main Let me know what you think! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add tests?
Sure! I just want to make sure the code is accepted and no functionality majorly changes before I write the test cases. 😄 |
@michael-ciniawsky friendly ping |
@michael-ciniawsky could you please see if you agree with the changes? 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Timer Thanks for your contribution. I'm willing to merge this since it seems like this could improve the overall flexibility and developer experience. It also helps the maintainers of create-react-app to support Sass out of the box (#532) @gaearon.
This is going into the right direction, but I'm not sure how big the change should be. Currently, this is built with the flexibility in mind to support multiple compilers. However, this is only going to work if all these node packages provide roughly the same API/behavior as node-sass. Could you name some node packages for example so that I can get a better understanding of that requirement?
If a sass compiler/node package exposes a completely different API, it probably makes more sense to have a dedicated loader for it.
So, if there are no other packages that provide the same API, we should probably make the change smaller and just check specifically for node-sass.
Besides, we also have to keep in mind that the current sass-loader implementation applies some fixes that expect a specific node-sass behavior.
What do you think?
.nycrc
Outdated
@@ -6,9 +6,9 @@ | |||
"include": [ | |||
"lib/**/*.js" | |||
], | |||
"lines": 97, | |||
"lines": 92, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should just decrease the coverage limit here 😁
The new code should have tests :). Maybe we should add each supported compiler as dev dependency. Then requiring it in a test should be no problem.
lib/compilers/index.js
Outdated
try { | ||
const value = compiler.getCompilerQueue(); | ||
|
||
if (value == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of these == null
checks (the V8 for instance has a hard time optimizing these since document.all == null
evaluates to true
😁). Why not check on === null
instead? We know that the compiler queue should return null
, so let's enforce a strict API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough.
lib/compilers/index.js
Outdated
} | ||
// Return the error encountered while loading a compiler, otherwise say | ||
// there was no compiler found. | ||
return { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just return the queue here or throw
or log the error if none was available?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK throwing on require
is being a bad neighbor, so we store the error until the loader is invoked (this function is called synchronously on package evaluation).
lib/compilers/libsass.js
Outdated
@@ -0,0 +1,27 @@ | |||
"use strict"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you rename that file to node-sass
. The sass-loader doesn't really know about libsass
lib/loader.js
Outdated
@@ -35,6 +30,13 @@ function sassLoader(content) { | |||
throw new Error("Synchronous compilation is not supported anymore. See https://github.com/webpack-contrib/sass-loader/issues/333"); | |||
} | |||
|
|||
const compilerError = asyncJobQueue.error; | |||
|
|||
if (compilerError) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to do that check. If the error was just thrown, webpack would report the loader error accordingly.
/cc @Timer let's finish this PR and implement |
I believe Let's keep this PR focused to removing the peer dep. |
@jhnns I've greatly simplified this PR and added tests; can I ask for another review? |
Remaining tests should pass after #514 is merged. |
Hi! Anything we can do to help this along? We'd really like to add Sass support in Create React App, but we need this released first. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only one note 👍
"functions": 100, | ||
"branches": 89, | ||
"branches": 91, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we return old values and add more tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/cc @Timer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify, you want me to reduce target test coverage and add then add more tests?
I increased the values here, I did not decrease them -- the tests I added provided more coverage than previously available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Timer oh sorry, all looks good 👍
LGTM 👍 thank you 👏 Travis is failing right now since it's trying to run webpack@4 with node 4 which doesn't work... I'll try to get #514 merged so that our CI is working again. |
- Add mock-require
this is a massive PR, lots of people will be happy :) |
Shipped with sass-loader |
@@ -54,7 +55,6 @@ | |||
"node": ">= 6.9.0 || >= 8.9.0" | |||
}, | |||
"peerDependencies": { | |||
"node-sass": "^4.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you remove node-sass
as a peerDependency when sass-loader
explicitly requires a version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sass-loader
requires either node-sass
or sass
. There's no way to express that as a peer dependency without having npm complain about one or the other missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! Thank you. Didn't know you could use either.
Fixes #532
Let me know what more is required. Doc changes, fixing coverage, etc.