Skip to content

Commit ffc71c2

Browse files
fix: skip double compression for child compilation (#18)
1 parent 69c144c commit ffc71c2

File tree

8 files changed

+144
-20
lines changed

8 files changed

+144
-20
lines changed

src/Webpack5Cache.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default class Cache {
1414
async get(task) {
1515
// eslint-disable-next-line no-param-reassign
1616
task.cacheIdent =
17-
task.cacheIdent || `${task.file}|${serialize(task.cacheKeys)}`;
17+
task.cacheIdent || `${task.name}|${serialize(task.cacheKeys)}`;
1818
// eslint-disable-next-line no-param-reassign
1919
task.cacheETag =
2020
task.cacheETag || this.cache.getLazyHashedEtag(task.assetSource);

src/index.js

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,38 @@ class CssMinimizerPlugin {
171171
: Math.min(Number(parallel) || 0, cpus.length - 1);
172172
}
173173

174-
*taskGenerator(compiler, compilation, file) {
175-
const assetSource = compilation.assets[file];
174+
// eslint-disable-next-line consistent-return
175+
static getAsset(compilation, name) {
176+
// New API
177+
if (compilation.getAsset) {
178+
return compilation.getAsset(name);
179+
}
180+
181+
if (compilation.assets[name]) {
182+
return { name, source: compilation.assets[name], info: {} };
183+
}
184+
}
185+
186+
static updateAsset(compilation, name, newSource, assetInfo) {
187+
// New API
188+
if (compilation.updateAsset) {
189+
compilation.updateAsset(name, newSource, assetInfo);
190+
}
191+
192+
// eslint-disable-next-line no-param-reassign
193+
compilation.assets[name] = newSource;
194+
}
195+
196+
*taskGenerator(compiler, compilation, name) {
197+
const { info, source: assetSource } = CssMinimizerPlugin.getAsset(
198+
compilation,
199+
name
200+
);
201+
202+
// Skip double minimize assets from child compilation
203+
if (info.minimized) {
204+
yield false;
205+
}
176206

177207
let input;
178208
let inputSourceMap;
@@ -190,7 +220,7 @@ class CssMinimizerPlugin {
190220
inputSourceMap = map;
191221

192222
compilation.warnings.push(
193-
new Error(`${file} contains invalid source map`)
223+
new Error(`${name} contains invalid source map`)
194224
);
195225
}
196226
}
@@ -222,7 +252,7 @@ class CssMinimizerPlugin {
222252
compilation.errors.push(
223253
CssMinimizerPlugin.buildError(
224254
error,
225-
file,
255+
name,
226256
sourceMap,
227257
new RequestShortener(compiler.context)
228258
)
@@ -236,7 +266,7 @@ class CssMinimizerPlugin {
236266
if (map) {
237267
outputSource = new SourceMapSource(
238268
code,
239-
file,
269+
name,
240270
map,
241271
input,
242272
inputSourceMap,
@@ -246,16 +276,17 @@ class CssMinimizerPlugin {
246276
outputSource = new RawSource(code);
247277
}
248278

249-
// Updating assets
250-
// eslint-disable-next-line no-param-reassign
251-
compilation.assets[file] = outputSource;
279+
CssMinimizerPlugin.updateAsset(compilation, name, outputSource, {
280+
...info,
281+
minimized: true,
282+
});
252283

253284
// Handling warnings
254285
if (warnings && warnings.length > 0) {
255286
warnings.forEach((warning) => {
256287
const builtWarning = CssMinimizerPlugin.buildWarning(
257288
warning,
258-
file,
289+
name,
259290
sourceMap,
260291
new RequestShortener(compiler.context),
261292
this.options.warningsFilter
@@ -269,7 +300,7 @@ class CssMinimizerPlugin {
269300
};
270301

271302
const task = {
272-
file,
303+
name,
273304
input,
274305
inputSourceMap,
275306
map: this.options.sourceMap,
@@ -299,11 +330,11 @@ class CssMinimizerPlugin {
299330
'css-minimizer-webpack-plugin': require('../package.json').version,
300331
'css-minimizer-webpack-plugin-options': this.options,
301332
nodeVersion: process.version,
302-
filename: file,
333+
filename: name,
303334
contentHash: digest.substr(0, hashDigestLength),
304335
};
305336

306-
task.cacheKeys = this.options.cacheKeys(defaultCacheKeys, file);
337+
task.cacheKeys = this.options.cacheKeys(defaultCacheKeys, name);
307338
}
308339
} else {
309340
// For webpack@5 cache

src/minify.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ function warningsToString(warnings) {
1010

1111
const minify = async (options) => {
1212
const {
13-
file,
13+
name,
1414
input,
1515
minimizerOptions,
1616
map,
1717
inputSourceMap,
1818
minify: minifyFn,
1919
} = options;
2020

21-
const postcssOptions = { to: file, from: file };
21+
const postcssOptions = { to: name, from: name };
2222

2323
if (minifyFn) {
2424
const result = await minifyFn(

test/CssMinimizerPlugin.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,4 +340,35 @@ describe('CssMinimizerPlugin', () => {
340340
}
341341
});
342342
});
343+
344+
it('should work with child compilation', async () => {
345+
const compiler = getCompiler({
346+
entry: {
347+
entry: `${__dirname}/fixtures/entry.js`,
348+
},
349+
module: {
350+
rules: [
351+
{
352+
test: /entry.js$/i,
353+
use: [
354+
{
355+
loader: path.resolve(__dirname, './helpers/preLoader'),
356+
},
357+
],
358+
},
359+
{
360+
test: /.s?css$/i,
361+
use: [MiniCssExtractPlugin.loader, 'css-loader'],
362+
},
363+
],
364+
},
365+
});
366+
new CssMinimizerPlugin().apply(compiler);
367+
368+
const stats = await compile(compiler);
369+
370+
expect(readAssets(compiler, stats, '.css')).toMatchSnapshot('assets');
371+
expect(getErrors(stats)).toMatchSnapshot('errors');
372+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
373+
});
343374
});

test/__snapshots__/CssMinimizerPlugin.test.js.snap.webpack4

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ exports[`CssMinimizerPlugin should work with assets using querystring: entry.css
6666
/*# sourceMappingURL=entry.css.map?v=test*/"
6767
`;
6868

69+
exports[`CssMinimizerPlugin should work with child compilation: assets 1`] = `
70+
Object {
71+
"entry.css": ".entry{text-align:center}",
72+
}
73+
`;
74+
75+
exports[`CssMinimizerPlugin should work with child compilation: errors 1`] = `Array []`;
76+
77+
exports[`CssMinimizerPlugin should work with child compilation: warnings 1`] = `Array []`;
78+
6979
exports[`CssMinimizerPlugin should write stdout and stderr of workers to stdout and stderr of main process in parallel mode: assets 1`] = `
7080
Object {
7181
"one.css": ".minify {};",

test/__snapshots__/CssMinimizerPlugin.test.js.snap.webpack5

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ exports[`CssMinimizerPlugin should work with assets using querystring: entry.css
6666
/*# sourceMappingURL=entry.css.map?v=test*/"
6767
`;
6868

69+
exports[`CssMinimizerPlugin should work with child compilation: assets 1`] = `
70+
Object {
71+
"entry.css": ".entry{text-align:center}",
72+
}
73+
`;
74+
75+
exports[`CssMinimizerPlugin should work with child compilation: errors 1`] = `Array []`;
76+
77+
exports[`CssMinimizerPlugin should work with child compilation: warnings 1`] = `Array []`;
78+
6979
exports[`CssMinimizerPlugin should write stdout and stderr of workers to stdout and stderr of main process in parallel mode: assets 1`] = `
7080
Object {
7181
"one.css": ".minify {};",

test/helpers/preLoader.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { RawSource } from 'webpack-sources';
2+
3+
class PreCopyPlugin {
4+
constructor(options = {}) {
5+
this.options = options.options || {};
6+
}
7+
8+
// eslint-disable-next-line class-methods-use-this
9+
apply(compiler) {
10+
const plugin = { name: 'PreCopyPlugin' };
11+
12+
compiler.hooks.compilation.tap(plugin, (compilation) => {
13+
compilation.hooks.additionalAssets.tapAsync(plugin, (callback) => {
14+
compilation.emitAsset(
15+
'entry.css',
16+
new RawSource('.entry {\n text-align: center;\n}\n\n')
17+
);
18+
19+
callback();
20+
});
21+
});
22+
}
23+
}
24+
25+
export default function loader() {
26+
const callback = this.async();
27+
28+
const childCompiler = this._compilation.createChildCompiler(
29+
`preloader`,
30+
this.options
31+
);
32+
33+
new PreCopyPlugin().apply(childCompiler);
34+
35+
childCompiler.runAsChild((error) => {
36+
if (error) {
37+
return callback(error);
38+
}
39+
40+
return callback(null, 'export default 1');
41+
});
42+
}

test/worker.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { normalizeErrors } from './helpers';
77
describe('worker', () => {
88
it('should minify css', async () => {
99
const options = {
10-
file: 'entry.css',
10+
name: 'entry.css',
1111
input: '.foo{color:red;}\n.bar{color:coral;}',
1212
inputSourceMap: {
1313
version: 3,
@@ -27,7 +27,7 @@ describe('worker', () => {
2727

2828
it('should work inputSourceMap as prev', async () => {
2929
const options = {
30-
file: 'entry.css',
30+
name: 'entry.css',
3131
input: '.foo{color:red;}\n.bar{color:coral;}',
3232
minimizerOptions: { discardComments: false },
3333
inputSourceMap: {
@@ -47,7 +47,7 @@ describe('worker', () => {
4747

4848
it('should work options.minify function', async () => {
4949
const options = {
50-
file: 'entry.css',
50+
name: 'entry.css',
5151
input: '.foo{color:red;}\n.bar{color:coral;}',
5252
minimizerOptions: { discardComments: false },
5353
minify: () => {
@@ -62,7 +62,7 @@ describe('worker', () => {
6262

6363
it('should emit error', async () => {
6464
const options = {
65-
file: 'entry.css',
65+
name: 'entry.css',
6666
input: false,
6767
};
6868

@@ -79,7 +79,7 @@ describe('worker', () => {
7979

8080
it('should emit minimizer error', async () => {
8181
const options = {
82-
file: 'entry.css',
82+
name: 'entry.css',
8383
input: false,
8484
minify: () => {
8585
return { error: new Error('css minimizer error') };

0 commit comments

Comments
 (0)