You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

345 lines
12 KiB

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var os = _interopRequireWildcard(require("os"));
var _sourceMap = require("source-map");
var _schemaUtils = require("schema-utils");
var _serializeJavascript = _interopRequireDefault(require("serialize-javascript"));
var _pLimit = _interopRequireDefault(require("p-limit"));
var _jestWorker = require("jest-worker");
var _utils = require("./utils");
var schema = _interopRequireWildcard(require("./options.json"));
var _minify = require("./minify");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const warningRegex = /\s.+:+([0-9]+):+([0-9]+)/;
class CssMinimizerPlugin {
constructor(options = {}) {
(0, _schemaUtils.validate)(schema, options, {
name: 'Css Minimizer Plugin',
baseDataPath: 'options'
});
const {
minify = _utils.cssnanoMinify,
minimizerOptions,
test = /\.css(\?.*)?$/i,
warningsFilter = () => true,
parallel = true,
include,
exclude
} = options;
this.options = {
test,
warningsFilter,
parallel,
include,
exclude,
minify,
minimizerOptions
};
}
static isSourceMap(input) {
// All required options for `new SourceMapConsumer(...options)`
// https://github.com/mozilla/source-map#new-sourcemapconsumerrawsourcemap
return Boolean(input && input.version && input.sources && Array.isArray(input.sources) && typeof input.mappings === 'string');
}
static buildError(error, name, requestShortener, sourceMap) {
let builtError;
if (error.line) {
const original = sourceMap && sourceMap.originalPositionFor({
line: error.line,
column: error.column
});
if (original && original.source && requestShortener) {
builtError = new Error(`${name} from Css Minimizer Webpack Plugin\n${error.message} [${requestShortener.shorten(original.source)}:${original.line},${original.column}][${name}:${error.line},${error.column}]${error.stack ? `\n${error.stack.split('\n').slice(1).join('\n')}` : ''}`);
builtError.file = name;
return builtError;
}
builtError = new Error(`${name} from Css Minimizer \n${error.message} [${name}:${error.line},${error.column}]${error.stack ? `\n${error.stack.split('\n').slice(1).join('\n')}` : ''}`);
builtError.file = name;
return builtError;
}
if (error.stack) {
builtError = new Error(`${name} from Css Minimizer\n${error.stack}`);
builtError.file = name;
return builtError;
}
builtError = new Error(`${name} from Css Minimizer\n${error.message}`);
builtError.file = name;
return builtError;
}
static buildWarning(warning, file, sourceMap, requestShortener, warningsFilter) {
let warningMessage = warning;
let locationMessage = '';
let source;
if (sourceMap) {
const match = warningRegex.exec(warning);
if (match) {
const line = +match[1];
const column = +match[2];
const original = sourceMap.originalPositionFor({
line,
column
});
if (original && original.source && original.source !== file && requestShortener) {
({
source
} = original);
warningMessage = `${warningMessage.replace(warningRegex, '')}`;
locationMessage = `${requestShortener.shorten(original.source)}:${original.line}:${original.column}`;
}
}
}
if (warningsFilter && !warningsFilter(warning, file, source)) {
return null;
}
return `Css Minimizer Plugin: ${warningMessage} ${locationMessage}`;
}
static getAvailableNumberOfCores(parallel) {
// In some cases cpus() returns undefined
// https://github.com/nodejs/node/issues/19022
const cpus = os.cpus() || {
length: 1
};
return parallel === true ? cpus.length - 1 : Math.min(Number(parallel) || 0, cpus.length - 1);
}
async optimize(compiler, compilation, assets, optimizeOptions) {
const cache = compilation.getCache('CssMinimizerWebpackPlugin');
let numberOfAssetsForMinify = 0;
const assetsForMinify = await Promise.all(Object.keys(typeof assets === 'undefined' ? compilation.assets : assets).filter(name => {
const {
info
} = compilation.getAsset(name);
if ( // Skip double minimize assets from child compilation
info.minimized) {
return false;
}
if (!compiler.webpack.ModuleFilenameHelpers.matchObject.bind( // eslint-disable-next-line no-undefined
undefined, this.options)(name)) {
return false;
}
return true;
}).map(async name => {
const {
info,
source
} = compilation.getAsset(name);
const eTag = cache.getLazyHashedEtag(source);
const cacheItem = cache.getItemCache(name, eTag);
const output = await cacheItem.getPromise();
if (!output) {
numberOfAssetsForMinify += 1;
}
return {
name,
info,
inputSource: source,
output,
cacheItem
};
}));
let getWorker;
let initializedWorker;
let numberOfWorkers;
if (optimizeOptions.availableNumberOfCores > 0) {
// Do not create unnecessary workers when the number of files is less than the available cores, it saves memory
numberOfWorkers = Math.min(numberOfAssetsForMinify, optimizeOptions.availableNumberOfCores);
getWorker = () => {
if (initializedWorker) {
return initializedWorker;
}
initializedWorker = new _jestWorker.Worker(require.resolve('./minify'), {
numWorkers: numberOfWorkers,
enableWorkerThreads: true
}); // https://github.com/facebook/jest/issues/8872#issuecomment-524822081
const workerStdout = initializedWorker.getStdout();
if (workerStdout) {
workerStdout.on('data', chunk => process.stdout.write(chunk));
}
const workerStderr = initializedWorker.getStderr();
if (workerStderr) {
workerStderr.on('data', chunk => process.stderr.write(chunk));
}
return initializedWorker;
};
}
const limit = (0, _pLimit.default)(getWorker && numberOfAssetsForMinify > 0 ? numberOfWorkers : Infinity);
const {
SourceMapSource,
RawSource
} = compiler.webpack.sources;
const scheduledTasks = [];
for (const asset of assetsForMinify) {
scheduledTasks.push(limit(async () => {
const {
name,
inputSource,
cacheItem
} = asset;
let {
output
} = asset;
if (!output) {
let input;
let inputSourceMap;
const {
source: sourceFromInputSource,
map
} = inputSource.sourceAndMap();
input = sourceFromInputSource;
if (map) {
if (CssMinimizerPlugin.isSourceMap(map)) {
inputSourceMap = map;
} else {
inputSourceMap = map;
compilation.warnings.push(new Error(`${name} contains invalid source map`));
}
}
if (Buffer.isBuffer(input)) {
input = input.toString();
}
const options = {
name,
input,
inputSourceMap,
minify: this.options.minify,
minifyOptions: this.options.minimizerOptions
};
try {
output = await (getWorker ? getWorker().transform((0, _serializeJavascript.default)(options)) : (0, _minify.minify)(options));
} catch (error) {
compilation.errors.push(CssMinimizerPlugin.buildError(error, name, compilation.requestShortener, inputSourceMap && CssMinimizerPlugin.isSourceMap(inputSourceMap) ? new _sourceMap.SourceMapConsumer(inputSourceMap) : null));
return;
}
if (output.map) {
output.source = new SourceMapSource(output.code, name, output.map, input, inputSourceMap, true);
} else {
output.source = new RawSource(output.code);
}
if (output.warnings && output.warnings.length > 0) {
output.warnings = output.warnings.map(warning => CssMinimizerPlugin.buildWarning(warning, name, inputSourceMap && CssMinimizerPlugin.isSourceMap(inputSourceMap) ? new _sourceMap.SourceMapConsumer(inputSourceMap) : null, compilation.requestShortener, this.options.warningsFilter)).filter(Boolean);
}
await cacheItem.storePromise({
source: output.source,
warnings: output.warnings
});
}
if (output.warnings && output.warnings.length > 0) {
output.warnings.forEach(warning => {
const Warning = class Warning extends Error {
constructor(message) {
super(message);
this.name = 'Warning';
this.hideStack = true;
this.file = name;
}
};
compilation.warnings.push(new Warning(warning));
});
}
const newInfo = {
minimized: true
};
const {
source
} = output;
compilation.updateAsset(name, source, newInfo);
}));
}
const result = await Promise.all(scheduledTasks);
if (initializedWorker) {
await initializedWorker.end();
}
return result;
}
apply(compiler) {
const pluginName = this.constructor.name;
const availableNumberOfCores = CssMinimizerPlugin.getAvailableNumberOfCores(this.options.parallel);
compiler.hooks.compilation.tap(pluginName, compilation => {
compilation.hooks.processAssets.tapPromise({
name: pluginName,
stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE,
additionalAssets: true
}, assets => this.optimize(compiler, compilation, assets, {
availableNumberOfCores
}));
compilation.hooks.statsPrinter.tap(pluginName, stats => {
stats.hooks.print.for('asset.info.minimized').tap('css-minimizer-webpack-plugin', (minimized, {
green,
formatFlag
}) => // eslint-disable-next-line no-undefined
minimized ? green(formatFlag('minimized')) : '');
});
});
}
}
CssMinimizerPlugin.cssnanoMinify = _utils.cssnanoMinify;
CssMinimizerPlugin.cssoMinify = _utils.cssoMinify;
CssMinimizerPlugin.cleanCssMinify = _utils.cleanCssMinify;
var _default = CssMinimizerPlugin;
exports.default = _default;