hard-source-webpack-plugin
Version:
Hard cache the source of modules in webpack.
226 lines (211 loc) • 6.22 kB
JavaScript
const relateContext = require('./util/relate-context');
const pluginCompat = require('./util/plugin-compat');
const SourceSchemas3 = [
['CachedSource', 'source'],
['ConcatSource'],
['LineToLineMappedSource', 'value', 'name', 'originalSource'],
['OriginalSource', 'value', 'name'],
['RawSource', 'value'],
['ReplaceSource', 'source', 'name'],
[
'SourceMapSource',
'value',
'name',
'sourceMap',
'originalSource',
'innerSourceMap',
],
];
try {
SourceSchemas3[0].Source = require('webpack-sources/lib/CachedSource');
} catch (_) {}
try {
SourceSchemas3[1].Source = require('webpack-sources/lib/ConcatSource');
} catch (_) {}
try {
SourceSchemas3[2].Source = require('webpack-sources/lib/LineToLineMappedSource');
} catch (_) {}
try {
SourceSchemas3[3].Source = require('webpack-sources/lib/OriginalSource');
} catch (_) {}
try {
SourceSchemas3[4].Source = require('webpack-sources/lib/RawSource');
} catch (_) {}
try {
SourceSchemas3[5].Source = require('webpack-sources/lib/ReplaceSource');
} catch (_) {}
try {
SourceSchemas3[6].Source = require('webpack-sources/lib/SourceMapSource');
} catch (_) {}
const freezeArgument = {
value(arg, { _value }, extra, methods) {
return _value;
},
name(arg, { _name }, { compilation }, methods) {
try {
return relateContext.relateNormalPath(compilation.compiler, _name);
} catch (e) {
console.error(e.stack);
process.exit();
}
},
sourceMap(arg, { _sourceMap }, extra, methods) {
return _sourceMap;
},
originalSource(arg, { _originalSource }, extra, methods) {
return _originalSource;
},
innerSourceMap(arg, { _innerSourceMap }, extra, methods) {
return _innerSourceMap;
},
source(arg, { constructor, _source }, extra, methods) {
if (constructor.name === 'ReplaceSource') {
return;
}
return methods.freeze('Source', null, _source, extra);
},
};
const thawArgument = {
name(arg, source, { compilation }, methods) {
try {
return relateContext.contextNormalPath(compilation.compiler, arg);
} catch (e) {
console.error(e.stack);
process.exit();
}
},
source(arg, { type }, extra, methods) {
if (type === 'ReplaceSource') {
return extra.source;
}
return methods.thaw('Source', null, arg, extra);
},
value(arg, frozen, extra, methods) {
if (arg && arg.type === 'Buffer') {
return new Buffer(arg.data);
}
return arg;
},
};
function freezeSource(source, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (source.constructor.name === schemas[i].Source.name) {
const frozen = {
type: schemas[i][0],
};
for (let j = 1; j < schemas[i].length; j++) {
let arg = source[schemas[i][j]];
if (freezeArgument[schemas[i][j]]) {
arg = freezeArgument[schemas[i][j]](arg, source, extra, methods);
}
frozen[schemas[i][j]] = arg;
}
return frozen;
}
}
throw new Error(`Unfrozen ${source.constructor.name}.`);
}
function thawSource(frozen, extra, methods) {
const schemas = extra.schemas;
for (let i = 0; i < schemas.length; i++) {
if (frozen.type === schemas[i][0]) {
const Source = schemas[i].Source;
const args = [];
for (let j = 1; j < schemas[i].length; j++) {
let arg = frozen[schemas[i][j]];
if (thawArgument[schemas[i][j]]) {
arg = thawArgument[schemas[i][j]](arg, frozen, extra, methods);
}
args.push(arg);
}
try {
return new Source(...args);
} catch (_) {
return new (Function.prototype.bind.apply(
Source,
[null].concat(args),
))();
}
}
}
}
class TransformSourcePlugin {
apply(compiler) {
let methods;
pluginCompat.tap(
compiler,
'_hardSourceMethods',
'TransformSourcePlugin',
_methods => {
methods = _methods;
},
);
pluginCompat.tap(
compiler,
'_hardSourceFreezeSource',
'TransformSourcePlugin freeze',
(frozen, source, extra) => {
if (typeof source === 'string') {
return {
type: 'String',
value: source,
};
} else if (Buffer.isBuffer && Buffer.isBuffer(source)) {
// Serialization layer might transform it into JSON or handle it as binary
// data
return source;
}
extra.schemas = SourceSchemas3;
frozen = freezeSource(source, extra, methods);
if (frozen.type === 'ReplaceSource') {
frozen.replacements = source.replacements;
} else if (frozen.type === 'CachedSource') {
frozen.cachedSource = source._cachedSource;
frozen.cachedSize = source._cachedSize;
frozen.cachedMaps = source._cachedMaps;
} else if (frozen.type === 'ConcatSource') {
frozen.children = methods.mapFreeze(
'Source',
null,
source.children,
extra,
);
}
return frozen;
},
);
pluginCompat.tap(
compiler,
'_hardSourceThawSource',
'TransformSourcePlugin thaw',
(source, frozen, extra) => {
if (frozen.type === 'String') {
return frozen.value;
} else if (frozen.type === 'Buffer') {
return new Buffer(frozen.data);
} else if (Buffer.isBuffer && Buffer.isBuffer(frozen)) {
return frozen;
}
extra.schemas = SourceSchemas3;
source = thawSource(frozen, extra, methods);
if (frozen.type === 'ReplaceSource') {
source.replacements = frozen.replacements;
} else if (frozen.type === 'CachedSource') {
source._cachedSource = frozen.cachedSource;
source._cachedSize = frozen.cachedSize;
source._cachedMaps = frozen.cachedMaps;
} else if (frozen.type === 'ConcatSource') {
source.children = methods.mapThaw(
'Source',
null,
frozen.children,
extra,
);
}
return source;
},
);
}
}
module.exports = TransformSourcePlugin;