To transpile .scss
(or .sass
) in Node you have the choice between sass
and node-sass
. sass
is a JavaScript compilation of Dart Sass which is supposedly "the primary implementation of Sass" which is a pretty powerful statement. node-sass
on the other hand is a wrapper on LibSass
which is written in C++. Let's break it down a little bit more.
Speed
node-sass
is faster. About 7 times faster. I took all the SCSS files behind the current MDN Web Docs which is fairly large. Transformed into CSS it becomes a ~180KB blob of CSS (92KB when optimized with csso
).
Here's my ugly benchmark test which I run about 10 times like this:
node-sass took 101ms result 180kb 92kb node-sass took 99ms result 180kb 92kb node-sass took 99ms result 180kb 92kb node-sass took 100ms result 180kb 92kb node-sass took 100ms result 180kb 92kb node-sass took 103ms result 180kb 92kb node-sass took 102ms result 180kb 92kb node-sass took 113ms result 180kb 92kb node-sass took 100ms result 180kb 92kb node-sass took 101ms result 180kb 92kb
And here's the same thing for sass
:
sass took 751ms result 173kb 92kb sass took 728ms result 173kb 92kb sass took 728ms result 173kb 92kb sass took 798ms result 173kb 92kb sass took 854ms result 173kb 92kb sass took 726ms result 173kb 92kb sass took 727ms result 173kb 92kb sass took 782ms result 173kb 92kb sass took 834ms result 173kb 92kb
In another example, I ran sass
and node-sass
on ./node_modules/bootstrap/scss/bootstrap.scss
(version 5.0.0-alpha1) and the results are after 5 runs:
node-sass took 269ms result 176kb 139kb node-sass took 260ms result 176kb 139kb node-sass took 288ms result 176kb 139kb node-sass took 261ms result 176kb 139kb node-sass took 260ms result 176kb 139kb
versus
sass took 1423ms result 176kb 139kb sass took 1350ms result 176kb 139kb sass took 1338ms result 176kb 139kb sass took 1368ms result 176kb 139kb sass took 1467ms result 176kb 139kb
Output
The unminified CSS difference primarily in the indentation. But you minify both outputs and the pretty print them (with prettier
) you get the following difference:
▶ diff /tmp/sass.min.css.pretty /tmp/node-sass.min.css.pretty
152c152
< letter-spacing: -0.0027777778rem;
---
> letter-spacing: -0.00278rem;
231c231
< content: "▼︎";
---
> content: "\25BC\FE0E";
...snip...
2804c2812
< .external-icon:not([href^="https://mdn.mozillademos.org"]):not(.ignore-external) {
---
> .external-icon:not([href^='https://mdn.mozillademos.org']):not(.ignore-external) {
Basically, sass
will use produce things like letter-spacing: -0.0027777778rem;
and content: "▼︎";
. And node-sass
will produce letter-spacing: -0.00278rem;
and content: "\25BC\FE0E";
.
I also noticed some minor difference just in the order of some selectors but when I look more carefully, they're immaterial order differences meaning they're not cascading each other in any way.
Note! I don't know why the use of '
and "
is different or if it matters. I don't know know why prettier
(version 2.1.1) didn't pick one over the other consistently.
node_modules
Here's how I created two projects to compare
cd /tmp
mkdir just-sass && cd just-sass && yarn init -y && time yarn add sass && cd ..
mkdir just-node-sass && cd just-node-sass && yarn init -y && time yarn add node-sass && cd ..
Considering that sass
is just a JavaScript compilation of a Dart program, all you get is basically a 3.6MB node_modules/sass/sass.dart.js
file.
The /tmp/just-sass/node_modules
directory is only 113 files and folders weighing a total of 4.1MB.
Whereas /tmp/just-node-sass/node_modules
directory is 3,658 files and folders weighing a total of 15.2MB.
I don't know about you but I'm very skeptical that node-gyp
ever works. Who even has Python 2.7 installed anymore? Being able to avoid node-gyp
seems like a win for sass
.
Conclusion
The speed difference may or may not matter. If you're only doing it once, who cares about a couple of hundred milliseconds. But if you're forced to have to wait 1.4 seconds on every Ctrl-S when Webpack or whatever tooling you have starts up sass
it might become very painful.
I don't know much about the sass-loader
Webpack plugin but it apparently works with either but they do recommend sass
in their documentation. And it's the default implementation too.
It's definitely a feather in sass
's hat that Dart Sass is the "primary implementation" of Sass. That just has a nice feelin in sass
's favor.
Bonus
NPMCompare has a nice comparison of them as projects but you have to study each row of numbers because it's rarely as simple as more (or less) number is better. For example, the number of open issues isn't a measure of bugs.
The new module system launched in October 2019 supposedly only comes to Dart Sass which means sass
is definitely going to get it first. If that stuff matters to you. For example, true
, the Sass unit-testing tool, now requires Dart Sass and drops support for node-sass
.
Comments
I've wasted so many hours trying to build node-sass with node-gyp. I simply cannot get it to work. I would choose anything else at this point even if it's a 100 times slower. Yes you have to wait 2 seconds more every time but you don't waste entire days trying to solve a problem.
I had problem installing node-sass as well couple weeks ago. It was really frustrating so eventually give up and move to sass. But today I started a new project and just for fun I tried installing and it worked. Most likely they had some problem before, or I don't know. So I would like to let you know, I had similar problem,but now it looks like working fine again.
This is broken: https://npmcompare.com/compare/node-sass,sass
Use https://npm-compare.com/node-sass,sass instead.