When attempting to compile any more than 9 less files (via mix.less), the number of resulting .css files are always one short.
I ran the following tests:
I replicated my problem in a fresh Laravel install which is available here:
https://github.com/susanBuck/foobar.
webpack.mix.js is as follows:
let mix = require('laravel-mix');
mix.less('resources/less/a.less', 'css/')
.less('resources/less/b.less', 'css/')
.less('resources/less/c.less', 'css/')
.less('resources/less/d.less', 'css/')
.less('resources/less/e.less', 'css/')
.less('resources/less/f.less', 'css/')
.less('resources/less/g.less', 'css/')
.less('resources/less/h.less', 'css/')
.less('resources/less/i.less', 'css/')
.less('resources/less/j.less', 'css/')
.less('resources/less/k.less', 'css/')
.less('resources/less/l.less', 'css/');
And below are the details of 5 different tests that vary the amount of mix.less calls by commenting them out.
Between each test, I run this command...
```bash
rm -rf ./public/css; npm run dev; find ./public/css -type f -and -not -name ".DS_STORE" | wc -l
````
...in order to:
public/css (destination folder) clean for a blank slatenpm run dev to invoke Mixpublic/cssTest 1:
Leave all 12 .less statements as is.
Invoke above-mentioned command.
.css file count:
Test 2
Comment any ONE of the .less statements so only 11 are run.
Invoke above-mentioned command.
.css file count:
Test 3
Comment any TWO of the .less statements so only 10 are run.
Invoke above-mentioned command.
.css file count:
Test 4
Comment out any THREE of the .less statements so only 9 are run.
Invoke above-mentioned command.
.css file count:
Test 5
Comment out any FOUR of the .less statements so only 8 are run.
Invoke above-mentioned command.
Here's the console output when attempting to compile 12 less files (as demonstrated in Test 1). It mirrors my file count from the test (11... one short).

Additional note: I've just noticed that when I compile <= 9 .less files (i.e. passing cases), mix.js is not included in the output of compiled Assets.
Digging into the source, I learned that the mix.js file is a temporary file created when no js compilation is requested.
From laravel-mix/src/plugins/MockEntryPlugin.js:
class MockEntryPlugin {
/**
* Handle the deletion of the temporary mix.js
* output file that was generated by webpack.
*
* This file is created when the user hasn't
* requested any JavaScript compilation, but
* webpack still requires an entry.
*
* @param {Object} compiler
*/
Knowing this, as an experiment I added a single mix.js() invocation in my webpack.mix.js file and __it resolves the problem__.
let mix = require('laravel-mix');
mix.less('resources/less/a.less', 'css/')
.less('resources/less/b.less', 'css/')
.less('resources/less/c.less', 'css/')
.less('resources/less/d.less', 'css/')
.less('resources/less/e.less', 'css/')
.less('resources/less/f.less', 'css/')
.less('resources/less/g.less', 'css/')
.less('resources/less/h.less', 'css/')
.less('resources/less/i.less', 'css/')
.less('resources/less/j.less', 'css/')
.less('resources/less/k.less', 'css/')
.less('resources/less/l.less', 'css/');
// As long as there's just one mix.js call, all 12 .less files are compiled
mix.js('resources/assets/js/bootstrap.js', 'js/');
So, I've got a work-around for my app, but seems like there's still some underlying problem.
Found the source of the problem in laravel-mix/src/plugins/MockEntryPlugin.js:
class MockEntryPlugin {
/**
* Handle the deletion of the temporary mix.js
* output file that was generated by webpack.
*
* This file is created when the user hasn't
* requested any JavaScript compilation, but
* webpack still requires an entry.
*
* @param {Object} compiler
*/
apply(compiler) {
compiler.plugin('done', stats => {
let temporaryOutputFile = stats.toJson()
.assets
.find(asset => asset.chunkNames.includes('mix'));
if (temporaryOutputFile) {
delete stats.compilation.assets[temporaryOutputFile.name];
File.find(
path.resolve(Config.publicPath, temporaryOutputFile.name)
).delete();
}
});
}
}
It locates the temporary mix file with this line:
let temporaryOutputFile = stats.toJson()
.assets
.find(asset => asset.chunkNames.includes('mix'));
When I console.log stats.toJson().assets I see the following output. Notice that the very first item css/f.css has a chunkName of mix (they all do, actually). Thus, the above line targets this as the temporary mix.js file and deletes it. But it's not the temporary mix.js file, it's my app's CSS file!
[ { name: 'css/f.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'mix.js',
size: 4051,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/b.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/c.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/d.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/e.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/a.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/g.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/h.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/i.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/j.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/k.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined },
{ name: 'css/l.css',
size: 13,
chunks: [ 0 ],
chunkNames: [ 'mix' ],
emitted: true,
isOverSizeLimit: undefined } ]
If I amend the definition of temporaryOutputFile to search on name instead of chunkNames the problem is solved. Also amended it to more specifically look for mix.js instead of mix.
Before:
let temporaryOutputFile = stats.toJson()
.assets
.find(asset => asset.chunkNames.includes('mix'));
After:
let temporaryOutputFile = stats.toJson()
.assets
.find(asset => asset.chunk.includes('mix.js'));
Thanks! That's fixed now, and will be part of the next release.
Most helpful comment
Thanks! That's fixed now, and will be part of the next release.