css-loader: "RangeError: Maximum call stack size exceeded" when compiling a file with many requires
Created based on comment https://github.com/webpack-contrib/css-loader/issues/689#issuecomment-422039086
Do you want to request a feature or report a bug? Bug
What is the current behavior? Given CSS file with 10000 or more classes with URLs, in our case generated from sprites.
...
.classN { ... background-image: url(./path/to/sprite.png); ... }
...
The css-loader creates such a JS file, which on compile throws RangeError: Maximum call stack size exceeded.
...
exports.push([
module.id,
".class0 { background-image: url(" +
escape(require("./path/to/sprite.png")) +
"); }.class1 { background-image: url(" +
escape(require("./path/to/sprite.png")) +
...
])
What is the expected behavior? The expected behaviour is to generate a JS file, which can be compiled and executed.
Please mention other relevant information such as your webpack version, Node.js version and Operating System. Reproducible on 1.0.0, Node 6.11.3 & Node 8.9.4.
Technical details
The issue is that URLs are replaced by requires and cssAsString in loader.js is built by string concatenation "..." + "..." + ... + "..." which has upper limit in each version of v8, given by it’s default stack size.
Experimentally measured:
- node 6.11.3 has ~6250 strings,
- node 8.9.4 has ~3285 strings.
The fix is straightforward, group the string concatenations by fixed amount so it can be compiled using default stack size. ("..." + ... + "...") + ("..." + ... + "...")
Smallest possible test-case for css-loader
/*globals describe */
var helpers = require("./helpers");
var test = helpers.test;
describe("string concat", function() {
this.timeout(20000);
var actualCSS, expectedCSS, i;
actualCSS = '';
expectedCSS = '';
for (i = 0; i < 10000; i++) {
actualCSS += ".class" + i + " { background-image: url(./path/to/file.png); }";
expectedCSS += ".class" + i + " { background-image: url({./path/to/file.png}); }";
}
test("should handle concat of 20001 strings", actualCSS, [[1, expectedCSS, ""]]);
});
Repo with reproducible test-case https://github.com/Gobie/css-loader/tree/issue-771
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 18 (12 by maintainers)
@sgarfinkel Okay, let’ use this https://github.com/webpack-contrib/css-loader/pull/1525, shorty:
templateLiteral, i.e.output. environment,templateLiteral: truewe will use it (if you have modern browsers it will be true for you), otherwise you can set it totruefor dev enviroment, because in productionmini-css-extract-pluginwill extract it to file and you will not have the such problem( "string" + "string" ) + ( "string" + "string" )doesn’t work, because acorn fails in other places (tokenizer), but I still think what acorn should use another approach to solve itLet me try to create a minimal reproduction for you. It looks like the one in the original ticket is gone.