Spaces:
Sleeping
Sleeping
| const cssnano = require('cssnano'); | |
| const postcss = require('postcss'); | |
| /** | |
| * Optimize cssnano plugin | |
| * | |
| * @param {Object} options | |
| */ | |
| function OptimizeCssnanoPlugin(options) { | |
| this.options = Object.assign({ | |
| sourceMap: false, | |
| cssnanoOptions: { | |
| preset: 'default', | |
| }, | |
| }, options); | |
| if (this.options.sourceMap) { | |
| this.options.sourceMap = Object.assign( | |
| {inline: false}, | |
| this.options.sourceMap || {}); | |
| } | |
| } | |
| OptimizeCssnanoPlugin.prototype.apply = function(compiler) { | |
| const self = this; | |
| compiler.hooks.emit.tapAsync('OptimizeCssnanoPlugin', | |
| function(compilation, callback) { | |
| // Search for CSS assets | |
| const assetsNames = Object.keys(compilation.assets) | |
| .filter((assetName) => { | |
| return /\.css$/i.test(assetName); | |
| }); | |
| let hasErrors = false; | |
| const promises = []; | |
| // Generate promises for each minification | |
| assetsNames.forEach((assetName) => { | |
| // Original CSS | |
| const asset = compilation.assets[assetName]; | |
| const originalCss = asset.source(); | |
| // Options for particalar cssnano call | |
| const postCssOptions = { | |
| from: assetName, | |
| to: assetName, | |
| map: false, | |
| }; | |
| const cssnanoOptions = self.options.cssnanoOptions; | |
| // Extract or remove previous map | |
| const mapName = assetName + '.map'; | |
| if (self.options.sourceMap) { | |
| // Use previous map if exist... | |
| if (compilation.assets[mapName]) { | |
| const mapObject = JSON.parse(compilation.assets[mapName].source()); | |
| // ... and not empty | |
| if (mapObject.sources.length > 0 || mapObject.mappings.length > 0) { | |
| postCssOptions.map = Object.assign({ | |
| prev: compilation.assets[mapName].source(), | |
| }, self.options.sourceMap); | |
| } else { | |
| postCssOptions.map = Object.assign({}, self.options.sourceMap); | |
| } | |
| } | |
| } else { | |
| delete compilation.assets[mapName]; | |
| } | |
| // Run minification | |
| const promise = postcss([cssnano(cssnanoOptions)]) | |
| .process(originalCss, postCssOptions) | |
| .then((result) => { | |
| if (hasErrors) { | |
| return; | |
| } | |
| // Extract CSS back to assets | |
| const processedCss = result.css; | |
| compilation.assets[assetName] = { | |
| source: function() { | |
| return processedCss; | |
| }, | |
| size: function() { | |
| return processedCss.length; | |
| }, | |
| }; | |
| // Extract map back to assets | |
| if (result.map) { | |
| const processedMap = result.map.toString(); | |
| compilation.assets[mapName] = { | |
| source: function() { | |
| return processedMap; | |
| }, | |
| size: function() { | |
| return processedMap.length; | |
| }, | |
| }; | |
| } | |
| } | |
| ).catch(function(err) { | |
| hasErrors = true; | |
| throw new Error('CSS minification error: ' + err.message + | |
| '. File: ' + assetName); | |
| } | |
| ); | |
| promises.push(promise); | |
| }); | |
| Promise.all(promises) | |
| .then(function() { | |
| callback(); | |
| }) | |
| .catch(callback); | |
| }); | |
| }; | |
| module.exports = OptimizeCssnanoPlugin; | |