So we just pushed a fix, sorry about that! Here's a breakdown of what went wrong...
We upgraded our local version of lesscss from 1.7 to 2.2. Everything worked just fine. This just uses the in-browser version of LESS.
Next up we updated the version in our build process. We use a custom nodejs build tool called capn-crunch that compiles and minifies our LESS and JS using a heavily parallelised engine. We use lesscss to compile LESS followed by clean-css to minify the result.
It seemed to work just fine - the build tool executed successfully with no errors. We checked out the development environment and it looked all good. Then we pushed to production. Oh noes! Everything is broken! Why is it OK on dev?
Turns out an old friend Monsieur Le Cache bit us; dev was not in a good way either.
So what was the problem?
Between 1.7 and 2.2 there was a minor breaking change in the lesscss API:
From this:
less.render(fileData, options, function (e, css) {
if (e) {
throw e;
}
file.data = new Buffer(css);
next(null, file);
});
To this:
less.render(fileData, options, function (e, output) {
if (e) {
throw e;
}
file.data = new Buffer(output.css);
next(null, file);
});
Note the change to the second argument in the event handler. When we instantiated the Buffer
to pass the result to the next item in the pipeline it passed in an object. Turns out Buffer
doesn't throw in this case and even then we wouldn't have handled the error correctly.
To fix this issue we've taken a two-pronged approach.
Firstly, improve the error handling in the LESS handler:
var error = null;
less.render(fileData, options, function (e, output) {
if (e) {
error = e;
return;
}
try {
file.data = new Buffer(output.css);
}
catch (e) {
error = e;
return;
}
if (error != null) {
throw error;
}
next(null, file);
});
if (error != null) {
throw error;
}
This ensures errors bubble out of the pipeline correctly.
Secondly, add an integration test that verifies whether some common CSS and JS has been generated correctly (in this case checking for a zero-length file). This will prevent breaking changes like this making it out to production.