210 lines
6.6 KiB
JavaScript
210 lines
6.6 KiB
JavaScript
var assign = require('lodash/assign');
|
|
var each = require('lodash/each');
|
|
var find = require('lodash/find');
|
|
var isArray = require('lodash/isArray');
|
|
var isFunction = require('lodash/isFunction');
|
|
var isRegExp = require('lodash/isRegExp');
|
|
var keys = require('lodash/keys');
|
|
var values = require('lodash/values');
|
|
var webpackSources = require('webpack-sources');
|
|
|
|
function EMPTY_FUNC() {};
|
|
|
|
var PHASE = {
|
|
OPTIMIZE_CHUNK_ASSETS: 'compilation.optimize-chunk-assets',
|
|
OPTIMIZE_ASSETS: 'compilation.optimize-assets',
|
|
EMIT: 'emit'
|
|
};
|
|
var PHASES = values(PHASE);
|
|
|
|
function AssetsManipulation(lastCallWebpackPlugin, compilation) {
|
|
this.lastCallWebpackPlugin = lastCallWebpackPlugin;
|
|
this.compilation = compilation;
|
|
}
|
|
|
|
AssetsManipulation.prototype.setAsset = function(assetName, assetValue, immediate) {
|
|
this.lastCallWebpackPlugin.setAsset(assetName, assetValue, immediate, this.compilation);
|
|
};
|
|
|
|
AssetsManipulation.prototype.getAsset = function(assetName) {
|
|
var asset = assetName && this.compilation.assets[assetName] && this.compilation.assets[assetName].source();
|
|
return asset || undefined;
|
|
};
|
|
|
|
function LastCallWebpackPlugin(options) {
|
|
this.options = assign(
|
|
{
|
|
assetProcessors: [],
|
|
onStart: EMPTY_FUNC,
|
|
onEnd: EMPTY_FUNC,
|
|
canPrint: true
|
|
},
|
|
options || {}
|
|
);
|
|
|
|
if (!isArray(this.options.assetProcessors)) {
|
|
throw new Error('LastCallWebpackPlugin Error: invalid options.assetProcessors (must be an Array).');
|
|
}
|
|
|
|
each(this.options.assetProcessors, function (processor, index) {
|
|
if (!processor) {
|
|
throw new Error('LastCallWebpackPlugin Error: invalid options.assetProcessors[' + String(index) + '] (must be an object).');
|
|
}
|
|
if (!isRegExp(processor.regExp)) {
|
|
throw new Error('LastCallWebpackPlugin Error: invalid options.assetProcessors[' + String(index) + '].regExp (must be an regular expression).');
|
|
}
|
|
if (!isFunction(processor.processor)) {
|
|
throw new Error('LastCallWebpackPlugin Error: invalid options.assetProcessors[' + String(index) + '].processor (must be a function).');
|
|
}
|
|
if (processor.phase === undefined) {
|
|
processor.phase = PHASE.OPTIMIZE_ASSETS;
|
|
}
|
|
if (!find(PHASES, function(p) { return p === processor.phase; })) {
|
|
throw new Error('LastCallWebpackPlugin Error: invalid options.assetProcessors[' + String(index) + '].phase (must be on of: ' + PHASES.join(', ') + ').');
|
|
}
|
|
});
|
|
|
|
if (!isFunction(this.options.onStart)) {
|
|
throw new Error('LastCallWebpackPlugin Error: invalid options.onStart (must be a function).');
|
|
}
|
|
if (!isFunction(this.options.onEnd)) {
|
|
throw new Error('LastCallWebpackPlugin Error: invalid options.onEnd (must be a function).');
|
|
}
|
|
|
|
this.initCompile();
|
|
};
|
|
|
|
LastCallWebpackPlugin.prototype.initCompile = function() {
|
|
this.deleteAssetsMap = {};
|
|
}
|
|
|
|
LastCallWebpackPlugin.prototype.print = function() {
|
|
if (this.options.canPrint) {
|
|
console.log.apply(console, arguments);
|
|
}
|
|
};
|
|
|
|
LastCallWebpackPlugin.prototype.onAssetError = function(assetName, asset, err) {
|
|
this.print('Error processing file: ' + assetName);
|
|
};
|
|
|
|
LastCallWebpackPlugin.prototype.getAssetsAndProcessors = function(assets, phase) {
|
|
var assetProcessors = this.options.assetProcessors;
|
|
var assetNames = keys(assets);
|
|
var assetsAndProcessors = [];
|
|
|
|
each(assetNames, function (assetName) {
|
|
each(assetProcessors, function(assetProcessor) {
|
|
if (assetProcessor.phase === phase) {
|
|
var regExpResult = assetProcessor.regExp.exec(assetName);
|
|
assetProcessor.regExp.lastIndex = 0;
|
|
if (regExpResult) {
|
|
var assetAndProcessor = {
|
|
assetName: assetName,
|
|
regExp: assetProcessor.regExp,
|
|
processor: assetProcessor.processor,
|
|
regExpResult: regExpResult,
|
|
};
|
|
assetsAndProcessors.push(assetAndProcessor);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
return assetsAndProcessors;
|
|
};
|
|
|
|
LastCallWebpackPlugin.prototype.createAsset = function(content, originalAsset) {
|
|
return new webpackSources.RawSource(content);
|
|
};
|
|
|
|
LastCallWebpackPlugin.prototype.process = function(compilation, phase, callback) {
|
|
var self = this;
|
|
|
|
var assetsAndProcessors = this.getAssetsAndProcessors(compilation.assets, phase);
|
|
if (assetsAndProcessors.length <= 0) {
|
|
return callback();
|
|
}
|
|
|
|
this.options.onStart(assetsAndProcessors, compilation, phase);
|
|
|
|
var hasErrors = false;
|
|
var promises = [];
|
|
|
|
var assetsManipulationObject = new AssetsManipulation(self, compilation);
|
|
|
|
each(assetsAndProcessors, function(assetAndProcessor) {
|
|
var asset = compilation.assets[assetAndProcessor.assetName];
|
|
var promise = assetAndProcessor
|
|
.processor(assetAndProcessor.assetName, asset, assetsManipulationObject)
|
|
.then(function (result) {
|
|
if (result !== undefined) {
|
|
self.setAsset(assetAndProcessor.assetName, result, false, compilation);
|
|
}
|
|
})
|
|
.catch(function(err) {
|
|
hasErrors = true;
|
|
self.onAssetError(assetAndProcessor.assetName, asset, err);
|
|
throw err;
|
|
});
|
|
promises.push(promise);
|
|
});
|
|
|
|
return Promise.all(promises)
|
|
.then(function () {
|
|
self.options.onEnd(assetsAndProcessors, compilation, phase);
|
|
callback();
|
|
})
|
|
.catch(function (err) {
|
|
self.options.onEnd(assetsAndProcessors, compilation, phase, err);
|
|
callback(err);
|
|
});
|
|
};
|
|
|
|
LastCallWebpackPlugin.prototype.setAsset = function(assetName, assetValue, immediate, compilation) {
|
|
if (assetName) {
|
|
if (assetValue === null) {
|
|
this.deleteAssetsMap[assetName] = true;
|
|
if (immediate) {
|
|
delete compilation.assets[assetName];
|
|
}
|
|
} else {
|
|
if (assetValue !== undefined) {
|
|
compilation.assets[assetName] = this.createAsset(assetValue, compilation.assets[assetName]);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
LastCallWebpackPlugin.prototype.deleteAssets = function(compilation) {
|
|
if (this.deleteAssetsMap && compilation) {
|
|
each(keys(this.deleteAssetsMap), function(key) {
|
|
delete compilation.assets[key];
|
|
});
|
|
}
|
|
};
|
|
|
|
LastCallWebpackPlugin.prototype.apply = function(compiler) {
|
|
var self = this;
|
|
|
|
compiler.plugin('compilation', function(compilation, params) {
|
|
self.initCompile();
|
|
|
|
compilation.plugin("optimize-chunk-assets", function(chunks, callback) {
|
|
self.process(compilation, PHASE.OPTIMIZE_CHUNK_ASSETS, callback);
|
|
});
|
|
compilation.plugin("optimize-assets", function(chunks, callback) {
|
|
self.process(compilation, PHASE.OPTIMIZE_ASSETS, callback);
|
|
});
|
|
});
|
|
compiler.plugin('emit', function(compilation, callback) {
|
|
self.process(compilation, PHASE.EMIT, callback);
|
|
self.deleteAssets(compilation);
|
|
});
|
|
};
|
|
|
|
LastCallWebpackPlugin.prototype.PHASE = PHASE;
|
|
LastCallWebpackPlugin.PHASE = PHASE;
|
|
|
|
module.exports = LastCallWebpackPlugin;
|