UNPKG

4.72 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const util = require("util");
9const webpackOptionsSchema = require("../schemas/WebpackOptions.json");
10const Compiler = require("./Compiler");
11const MultiCompiler = require("./MultiCompiler");
12const WebpackOptionsApply = require("./WebpackOptionsApply");
13const {
14 applyWebpackOptionsDefaults,
15 applyWebpackOptionsBaseDefaults
16} = require("./config/defaults");
17const { getNormalizedWebpackOptions } = require("./config/normalization");
18const NodeEnvironmentPlugin = require("./node/NodeEnvironmentPlugin");
19const validateSchema = require("./validateSchema");
20
21/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
22/** @typedef {import("./Compiler").WatchOptions} WatchOptions */
23/** @typedef {import("./MultiCompiler").MultiCompilerOptions} MultiCompilerOptions */
24/** @typedef {import("./MultiStats")} MultiStats */
25/** @typedef {import("./Stats")} Stats */
26
27/**
28 * @template T
29 * @callback Callback
30 * @param {Error=} err
31 * @param {T=} stats
32 * @returns {void}
33 */
34
35/**
36 * @param {WebpackOptions[]} childOptions options array
37 * @param {MultiCompilerOptions} options options
38 * @returns {MultiCompiler} a multi-compiler
39 */
40const createMultiCompiler = (childOptions, options) => {
41 const compilers = childOptions.map(options => createCompiler(options));
42 const compiler = new MultiCompiler(compilers, options);
43 for (const childCompiler of compilers) {
44 if (childCompiler.options.dependencies) {
45 compiler.setDependencies(
46 childCompiler,
47 childCompiler.options.dependencies
48 );
49 }
50 }
51 return compiler;
52};
53
54/**
55 * @param {WebpackOptions} rawOptions options object
56 * @returns {Compiler} a compiler
57 */
58const createCompiler = rawOptions => {
59 const options = getNormalizedWebpackOptions(rawOptions);
60 applyWebpackOptionsBaseDefaults(options);
61 const compiler = new Compiler(options.context);
62 compiler.options = options;
63 new NodeEnvironmentPlugin({
64 infrastructureLogging: options.infrastructureLogging
65 }).apply(compiler);
66 if (Array.isArray(options.plugins)) {
67 for (const plugin of options.plugins) {
68 if (typeof plugin === "function") {
69 plugin.call(compiler, compiler);
70 } else {
71 plugin.apply(compiler);
72 }
73 }
74 }
75 applyWebpackOptionsDefaults(options);
76 compiler.hooks.environment.call();
77 compiler.hooks.afterEnvironment.call();
78 new WebpackOptionsApply().process(options, compiler);
79 compiler.hooks.initialize.call();
80 return compiler;
81};
82
83/**
84 * @callback WebpackFunctionSingle
85 * @param {WebpackOptions} options options object
86 * @param {Callback<Stats>=} callback callback
87 * @returns {Compiler} the compiler object
88 */
89
90/**
91 * @callback WebpackFunctionMulti
92 * @param {WebpackOptions[] & MultiCompilerOptions} options options objects
93 * @param {Callback<MultiStats>=} callback callback
94 * @returns {MultiCompiler} the multi compiler object
95 */
96
97const webpack = /** @type {WebpackFunctionSingle & WebpackFunctionMulti} */ (
98 /**
99 * @param {WebpackOptions | (WebpackOptions[] & MultiCompilerOptions)} options options
100 * @param {Callback<Stats> & Callback<MultiStats>=} callback callback
101 * @returns {Compiler | MultiCompiler}
102 */
103 (options, callback) => {
104 const create = () => {
105 validateSchema(webpackOptionsSchema, options);
106 /** @type {MultiCompiler|Compiler} */
107 let compiler;
108 let watch = false;
109 /** @type {WatchOptions|WatchOptions[]} */
110 let watchOptions;
111 if (Array.isArray(options)) {
112 /** @type {MultiCompiler} */
113 compiler = createMultiCompiler(options, options);
114 watch = options.some(options => options.watch);
115 watchOptions = options.map(options => options.watchOptions || {});
116 } else {
117 /** @type {Compiler} */
118 compiler = createCompiler(options);
119 watch = options.watch;
120 watchOptions = options.watchOptions || {};
121 }
122 return { compiler, watch, watchOptions };
123 };
124 if (callback) {
125 try {
126 const { compiler, watch, watchOptions } = create();
127 if (watch) {
128 compiler.watch(watchOptions, callback);
129 } else {
130 compiler.run((err, stats) => {
131 compiler.close(err2 => {
132 callback(err || err2, stats);
133 });
134 });
135 }
136 return compiler;
137 } catch (err) {
138 process.nextTick(() => callback(err));
139 return null;
140 }
141 } else {
142 const { compiler, watch } = create();
143 if (watch) {
144 util.deprecate(
145 () => {},
146 "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.",
147 "DEP_WEBPACK_WATCH_WITHOUT_CALLBACK"
148 )();
149 }
150 return compiler;
151 }
152 }
153);
154
155module.exports = webpack;