/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const util = require("util"); 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 validateSchema = require("./validateSchema"); /** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */ /** @typedef {import("./Compiler").WatchOptions} WatchOptions */ /** @typedef {import("./MultiCompiler").MultiCompilerOptions} MultiCompilerOptions */ /** @typedef {import("./MultiStats")} MultiStats */ /** @typedef {import("./Stats")} Stats */ /** * @template T * @callback Callback * @param {Error=} err * @param {T=} stats * @returns {void} */ /** * @param {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); compiler.options = 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=} callback callback * @returns {Compiler} the compiler object */ /** * @callback WebpackFunctionMulti * @param {WebpackOptions[] & MultiCompilerOptions} options options objects * @param {Callback=} callback callback * @returns {MultiCompiler} the multi compiler object */ const webpack = /** @type {WebpackFunctionSingle & WebpackFunctionMulti} */ ( /** * @param {WebpackOptions | (WebpackOptions[] & MultiCompilerOptions)} options options * @param {Callback & Callback=} callback callback * @returns {Compiler | MultiCompiler} */ (options, callback) => { const create = () => { validateSchema(webpackOptionsSchema, options); /** @type {MultiCompiler|Compiler} */ let compiler; let watch = false; /** @type {WatchOptions|WatchOptions[]} */ let watchOptions; if (Array.isArray(options)) { /** @type {MultiCompiler} */ compiler = createMultiCompiler(options, options); watch = options.some(options => options.watch); watchOptions = options.map(options => options.watchOptions || {}); } else { /** @type {Compiler} */ compiler = createCompiler(options); watch = options.watch; watchOptions = options.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 need 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;