const ChainedMap = require('./ChainedMap');
|
const ChainedSet = require('./ChainedSet');
|
const Resolve = require('./Resolve');
|
const ResolveLoader = require('./ResolveLoader');
|
const Output = require('./Output');
|
const DevServer = require('./DevServer');
|
const Plugin = require('./Plugin');
|
const Module = require('./Module');
|
const Optimization = require('./Optimization');
|
const Performance = require('./Performance');
|
|
module.exports = class extends ChainedMap {
|
constructor() {
|
super();
|
this.devServer = new DevServer(this);
|
this.entryPoints = new ChainedMap(this);
|
this.module = new Module(this);
|
this.node = new ChainedMap(this);
|
this.optimization = new Optimization(this);
|
this.output = new Output(this);
|
this.performance = new Performance(this);
|
this.plugins = new ChainedMap(this);
|
this.resolve = new Resolve(this);
|
this.resolveLoader = new ResolveLoader(this);
|
this.extend([
|
'amd',
|
'bail',
|
'cache',
|
'context',
|
'devtool',
|
'externals',
|
'loader',
|
'mode',
|
'name',
|
'parallelism',
|
'profile',
|
'recordsInputPath',
|
'recordsPath',
|
'recordsOutputPath',
|
'stats',
|
'target',
|
'watch',
|
'watchOptions',
|
]);
|
}
|
|
static toString(config, { verbose = false, configPrefix = 'config' } = {}) {
|
// eslint-disable-next-line global-require
|
const { stringify } = require('javascript-stringify');
|
|
return stringify(
|
config,
|
(value, indent, stringify) => {
|
// improve plugin output
|
if (value && value.__pluginName) {
|
const prefix = `/* ${configPrefix}.${value.__pluginType}('${value.__pluginName}') */\n`;
|
const constructorExpression = value.__pluginPath
|
? // The path is stringified to ensure special characters are escaped
|
// (such as the backslashes in Windows-style paths).
|
`(require(${stringify(value.__pluginPath)}))`
|
: value.__pluginConstructorName;
|
|
if (constructorExpression) {
|
// get correct indentation for args by stringifying the args array and
|
// discarding the square brackets.
|
const args = stringify(value.__pluginArgs).slice(1, -1);
|
return `${prefix}new ${constructorExpression}(${args})`;
|
}
|
return (
|
prefix +
|
stringify(
|
value.__pluginArgs && value.__pluginArgs.length
|
? { args: value.__pluginArgs }
|
: {},
|
)
|
);
|
}
|
|
// improve rule/use output
|
if (value && value.__ruleNames) {
|
const ruleTypes = value.__ruleTypes;
|
const prefix = `/* ${configPrefix}.module${value.__ruleNames
|
.map(
|
(r, index) => `.${ruleTypes ? ruleTypes[index] : 'rule'}('${r}')`,
|
)
|
.join('')}${
|
value.__useName ? `.use('${value.__useName}')` : ``
|
} */\n`;
|
return prefix + stringify(value);
|
}
|
|
if (value && value.__expression) {
|
return value.__expression;
|
}
|
|
// shorten long functions
|
if (typeof value === 'function') {
|
if (!verbose && value.toString().length > 100) {
|
return `function () { /* omitted long function */ }`;
|
}
|
}
|
|
return stringify(value);
|
},
|
2,
|
);
|
}
|
|
entry(name) {
|
return this.entryPoints.getOrCompute(name, () => new ChainedSet(this));
|
}
|
|
plugin(name) {
|
return this.plugins.getOrCompute(name, () => new Plugin(this, name));
|
}
|
|
toConfig() {
|
const entryPoints = this.entryPoints.entries() || {};
|
|
return this.clean(
|
Object.assign(this.entries() || {}, {
|
node: this.node.entries(),
|
output: this.output.entries(),
|
resolve: this.resolve.toConfig(),
|
resolveLoader: this.resolveLoader.toConfig(),
|
devServer: this.devServer.toConfig(),
|
module: this.module.toConfig(),
|
optimization: this.optimization.toConfig(),
|
plugins: this.plugins.values().map((plugin) => plugin.toConfig()),
|
performance: this.performance.entries(),
|
entry: Object.keys(entryPoints).reduce(
|
(acc, key) =>
|
Object.assign(acc, { [key]: entryPoints[key].values() }),
|
{},
|
),
|
}),
|
);
|
}
|
|
toString(options) {
|
return module.exports.toString(this.toConfig(), options);
|
}
|
|
merge(obj = {}, omit = []) {
|
const omissions = [
|
'node',
|
'output',
|
'resolve',
|
'resolveLoader',
|
'devServer',
|
'optimization',
|
'performance',
|
'module',
|
];
|
|
if (!omit.includes('entry') && 'entry' in obj) {
|
Object.keys(obj.entry).forEach((name) =>
|
this.entry(name).merge([].concat(obj.entry[name])),
|
);
|
}
|
|
if (!omit.includes('plugin') && 'plugin' in obj) {
|
Object.keys(obj.plugin).forEach((name) =>
|
this.plugin(name).merge(obj.plugin[name]),
|
);
|
}
|
|
omissions.forEach((key) => {
|
if (!omit.includes(key) && key in obj) {
|
this[key].merge(obj[key]);
|
}
|
});
|
|
return super.merge(obj, [...omit, ...omissions, 'entry', 'plugin']);
|
}
|
};
|