build/lib/extensions.ts/webpackExtensions
export async function webpackExtensions(taskName: string, isWatch: boolean, webpackConfigLocations: { configPath: string; outputRoot?: string }[]) {
	const webpack = require('webpack') as typeof import('webpack');

	const webpackConfigs: webpack.Configuration[] = [];

	for (const { configPath, outputRoot } of webpackConfigLocations) {
		const configOrFnOrArray = require(configPath);
		function addConfig(configOrFn: webpack.Configuration | Function) {
			let config;
			if (typeof configOrFn === 'function') {
				config = (configOrFn as Function)({}, {});
				webpackConfigs.push(config);
			} else {
				config = configOrFn;
			}

			if (outputRoot) {
				config.output.path = path.join(outputRoot, path.relative(path.dirname(configPath), config.output.path));
			}

			webpackConfigs.push(configOrFn);
		}
		addConfig(configOrFnOrArray);
	}
	function reporter(fullStats: any) {
		if (Array.isArray(fullStats.children)) {
			for (const stats of fullStats.children) {
				const outputPath = stats.outputPath;
				if (outputPath) {
					const relativePath = path.relative(extensionsPath, outputPath).replace(/\\/g, '/');
					const match = relativePath.match(/[^\/]+(\/server|\/client)?/);
					fancyLog(`Finished ${ansiColors.green(taskName)} ${ansiColors.cyan(match![0])} with ${stats.errors.length} errors.`);
				}
				if (Array.isArray(stats.errors)) {
					stats.errors.forEach((error: any) => {
						fancyLog.error(error);
					});
				}
				if (Array.isArray(stats.warnings)) {
					stats.warnings.forEach((warning: any) => {
						fancyLog.warn(warning);
					});
				}
			}
		}
	}
	return new Promise<void>((resolve, reject) => {
		if (isWatch) {
			webpack(webpackConfigs).watch({}, (err, stats) => {
				if (err) {
					reject();
				} else {
					reporter(stats?.toJson());
				}
			});
		} else {
			webpack(webpackConfigs).run((err, stats) => {
				if (err) {
					fancyLog.error(err);
					reject();
				} else {
					reporter(stats?.toJson());
					resolve();
				}
			});
		}
	});
}