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.
171 lines
5.3 KiB
171 lines
5.3 KiB
/* |
|
MIT License http://www.opensource.org/licenses/mit-license.php |
|
Author Tobias Koppers @sokra |
|
*/ |
|
|
|
"use strict"; |
|
|
|
const util = require("util"); |
|
const webpackOptionsSchemaCheck = require("../schemas/WebpackOptions.check.js"); |
|
const webpackOptionsSchema = require("../schemas/WebpackOptions.json"); |
|
const Compiler = require("./Compiler"); |
|
const MultiCompiler = require("./MultiCompiler"); |
|
const WebpackOptionsApply = require("./WebpackOptionsApply"); |
|
const { |
|
applyWebpackOptionsDefaults, |
|
applyWebpackOptionsBaseDefaults |
|
} = require("./config/defaults"); |
|
const { getNormalizedWebpackOptions } = require("./config/normalization"); |
|
const NodeEnvironmentPlugin = require("./node/NodeEnvironmentPlugin"); |
|
const memoize = require("./util/memoize"); |
|
|
|
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */ |
|
/** @typedef {import("./Compiler").WatchOptions} WatchOptions */ |
|
/** @typedef {import("./MultiCompiler").MultiCompilerOptions} MultiCompilerOptions */ |
|
/** @typedef {import("./MultiStats")} MultiStats */ |
|
/** @typedef {import("./Stats")} Stats */ |
|
|
|
const getValidateSchema = memoize(() => require("./validateSchema")); |
|
|
|
/** |
|
* @template T |
|
* @callback Callback |
|
* @param {Error=} err |
|
* @param {T=} stats |
|
* @returns {void} |
|
*/ |
|
|
|
/** |
|
* @param {ReadonlyArray<WebpackOptions>} childOptions options array |
|
* @param {MultiCompilerOptions} options options |
|
* @returns {MultiCompiler} a multi-compiler |
|
*/ |
|
const createMultiCompiler = (childOptions, options) => { |
|
const compilers = childOptions.map(options => createCompiler(options)); |
|
const compiler = new MultiCompiler(compilers, options); |
|
for (const childCompiler of compilers) { |
|
if (childCompiler.options.dependencies) { |
|
compiler.setDependencies( |
|
childCompiler, |
|
childCompiler.options.dependencies |
|
); |
|
} |
|
} |
|
return compiler; |
|
}; |
|
|
|
/** |
|
* @param {WebpackOptions} rawOptions options object |
|
* @returns {Compiler} a compiler |
|
*/ |
|
const createCompiler = rawOptions => { |
|
const options = getNormalizedWebpackOptions(rawOptions); |
|
applyWebpackOptionsBaseDefaults(options); |
|
const compiler = new Compiler(options.context, options); |
|
new NodeEnvironmentPlugin({ |
|
infrastructureLogging: options.infrastructureLogging |
|
}).apply(compiler); |
|
if (Array.isArray(options.plugins)) { |
|
for (const plugin of options.plugins) { |
|
if (typeof plugin === "function") { |
|
plugin.call(compiler, compiler); |
|
} else { |
|
plugin.apply(compiler); |
|
} |
|
} |
|
} |
|
applyWebpackOptionsDefaults(options); |
|
compiler.hooks.environment.call(); |
|
compiler.hooks.afterEnvironment.call(); |
|
new WebpackOptionsApply().process(options, compiler); |
|
compiler.hooks.initialize.call(); |
|
return compiler; |
|
}; |
|
|
|
/** |
|
* @callback WebpackFunctionSingle |
|
* @param {WebpackOptions} options options object |
|
* @param {Callback<Stats>=} callback callback |
|
* @returns {Compiler} the compiler object |
|
*/ |
|
|
|
/** |
|
* @callback WebpackFunctionMulti |
|
* @param {ReadonlyArray<WebpackOptions> & MultiCompilerOptions} options options objects |
|
* @param {Callback<MultiStats>=} callback callback |
|
* @returns {MultiCompiler} the multi compiler object |
|
*/ |
|
|
|
const asArray = options => |
|
Array.isArray(options) ? Array.from(options) : [options]; |
|
|
|
const webpack = /** @type {WebpackFunctionSingle & WebpackFunctionMulti} */ ( |
|
/** |
|
* @param {WebpackOptions | (ReadonlyArray<WebpackOptions> & MultiCompilerOptions)} options options |
|
* @param {Callback<Stats> & Callback<MultiStats>=} callback callback |
|
* @returns {Compiler | MultiCompiler} |
|
*/ |
|
(options, callback) => { |
|
const create = () => { |
|
if (!asArray(options).every(webpackOptionsSchemaCheck)) { |
|
getValidateSchema()(webpackOptionsSchema, options); |
|
util.deprecate( |
|
() => {}, |
|
"webpack bug: Pre-compiled schema reports error while real schema is happy. This has performance drawbacks.", |
|
"DEP_WEBPACK_PRE_COMPILED_SCHEMA_INVALID" |
|
)(); |
|
} |
|
/** @type {MultiCompiler|Compiler} */ |
|
let compiler; |
|
let watch = false; |
|
/** @type {WatchOptions|WatchOptions[]} */ |
|
let watchOptions; |
|
if (Array.isArray(options)) { |
|
/** @type {MultiCompiler} */ |
|
compiler = createMultiCompiler( |
|
options, |
|
/** @type {MultiCompilerOptions} */ (options) |
|
); |
|
watch = options.some(options => options.watch); |
|
watchOptions = options.map(options => options.watchOptions || {}); |
|
} else { |
|
const webpackOptions = /** @type {WebpackOptions} */ (options); |
|
/** @type {Compiler} */ |
|
compiler = createCompiler(webpackOptions); |
|
watch = webpackOptions.watch; |
|
watchOptions = webpackOptions.watchOptions || {}; |
|
} |
|
return { compiler, watch, watchOptions }; |
|
}; |
|
if (callback) { |
|
try { |
|
const { compiler, watch, watchOptions } = create(); |
|
if (watch) { |
|
compiler.watch(watchOptions, callback); |
|
} else { |
|
compiler.run((err, stats) => { |
|
compiler.close(err2 => { |
|
callback(err || err2, stats); |
|
}); |
|
}); |
|
} |
|
return compiler; |
|
} catch (err) { |
|
process.nextTick(() => callback(err)); |
|
return null; |
|
} |
|
} else { |
|
const { compiler, watch } = create(); |
|
if (watch) { |
|
util.deprecate( |
|
() => {}, |
|
"A 'callback' argument needs to be provided to the 'webpack(options, callback)' function when the 'watch' option is set. There is no way to handle the 'watch' option without a callback.", |
|
"DEP_WEBPACK_WATCH_WITHOUT_CALLBACK" |
|
)(); |
|
} |
|
return compiler; |
|
} |
|
} |
|
); |
|
|
|
module.exports = webpack;
|
|
|