Description
Bug report
When css-minimizer-webpack-plugin is used, source map content from previous step is ignore and completely replaced and not merge with the one that came from minification.
Actual Behavior
In debug mode, you can inspect the DOM elements in the browsers devtool and see the original source of applied rulesets.
In release mode, due css-minimizer-webpack-plugin apply minification, you only see the source before minification, not the original one.
Expected Behavior
When you inspect DOM elements in the browsers devtool you can see the original source of applied rulesets in any mode (release, debug, etc.)
How Do We Reproduce?
Compile styles with a preprocessor (sass, less, stylus, etc.) with sourcemap without css-minimizer-webpack-plugin (or disabled with debug mode), inspect the extracted source map with devtool or source-map-visualization.
Do it again but with css-minimizer-webpack-plugin, then it inspect again.
Reproducible test: webpack-source-map-merge-test
Please paste the results of npx webpack-cli info
here, and mention other relevant information
System:
OS: Windows 8.1 6.3.9600
CPU: (4) x64 Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
Memory: 6.94 GB / 31.88 GB
Binaries:
Node: 14.17.4 - C:\Program Files\nodejs\node.EXE
npm: 6.14.14 - C:\Program Files\nodejs\npm.CMD
Browsers:
Chrome: 95.0.4638.69
Internet Explorer: 11.0.9600.19036
Packages:
webpack: ^5.61.0 => 5.62.2
webpack-cli: ^4.9.1 => 4.9.1
Possible solutions
Each minimizer has it's own option/solution:
- postcss+cssnano:
postcssOptions.map.prev = inputSourceMap
- csso:
output.map.applySourceMap(await new SourceMapConsumer(inputSourceMap), filename)
- clean-css:
new CleanCSS({sourceMap: Boolean(inputSourceMap), ...minimizerOptions}).minify({[name]: {styles: code}}, inputSourceMap)
- esbuild:
code = `${code}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${btoa(inputSourceMap)}`
It's also possible to not provide previous source map to the minimizer but instead manually merge source maps:
const { SourceMapGenerator } = require('source-map/lib/source-map-generator.js');
const { SourceMapConsumer } = require('source-map/lib/source-map-consumer.js');
const mergedSourceMap = await SourceMapConsumer.with(resultSourceMap, null, async (resultConsumer) =>
SourceMapConsumer.with(inputSourceMap, null, inputConsumer => {
const generator = SourceMapGenerator.fromSourceMap(resultConsumer);
generator.applySourceMap(inputConsumer, filename);
return generator.toJSON();
}));
Example of implementation with cssnano:
diff --git a/src/utils.jst b/src/utils.js
index 08829e0..19b90f3 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -116,7 +116,10 @@ async function cssnanoMinify(
}
if (inputSourceMap) {
- postcssOptions.map = { annotation: false };
+ postcssOptions.map = {
+ annotation: false,
+ prev: inputSourceMap,
+ };
}
// eslint-disable-next-line global-require