Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

cli.js 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. #!/usr/bin/env node
  2. /*
  3. MIT License http://www.opensource.org/licenses/mit-license.php
  4. Author Tobias Koppers @sokra
  5. */
  6. const { NON_COMPILATION_ARGS } = require("./utils/constants");
  7. (function() {
  8. // wrap in IIFE to be able to use return
  9. const importLocal = require("import-local");
  10. // Prefer the local installation of webpack-cli
  11. if (importLocal(__filename)) {
  12. return;
  13. }
  14. require("v8-compile-cache");
  15. const ErrorHelpers = require("./utils/errorHelpers");
  16. const NON_COMPILATION_CMD = process.argv.find(arg => {
  17. if (arg === "serve") {
  18. global.process.argv = global.process.argv.filter(a => a !== "serve");
  19. process.argv = global.process.argv;
  20. }
  21. return NON_COMPILATION_ARGS.find(a => a === arg);
  22. });
  23. if (NON_COMPILATION_CMD) {
  24. return require("./utils/prompt-command")(NON_COMPILATION_CMD, ...process.argv);
  25. }
  26. const yargs = require("yargs").usage(`webpack-cli ${require("../package.json").version}
  27. Usage: webpack-cli [options]
  28. webpack-cli [options] --entry <entry> --output <output>
  29. webpack-cli [options] <entries...> --output <output>
  30. webpack-cli <command> [options]
  31. For more information, see https://webpack.js.org/api/cli/.`);
  32. require("./config/config-yargs")(yargs);
  33. // yargs will terminate the process early when the user uses help or version.
  34. // This causes large help outputs to be cut short (https://github.com/nodejs/node/wiki/API-changes-between-v0.10-and-v4#process).
  35. // To prevent this we use the yargs.parse API and exit the process normally
  36. yargs.parse(process.argv.slice(2), (err, argv, output) => {
  37. Error.stackTraceLimit = 30;
  38. // arguments validation failed
  39. if (err && output) {
  40. console.error(output);
  41. process.exitCode = 1;
  42. return;
  43. }
  44. // help or version info
  45. if (output) {
  46. console.log(output);
  47. return;
  48. }
  49. if (argv.verbose) {
  50. argv["display"] = "verbose";
  51. }
  52. let options;
  53. try {
  54. options = require("./utils/convert-argv")(argv);
  55. } catch (err) {
  56. if (err.code === "MODULE_NOT_FOUND") {
  57. const moduleName = err.message.split("'")[1];
  58. let instructions = "";
  59. let errorMessage = "";
  60. if (moduleName === "webpack") {
  61. errorMessage = `\n${moduleName} not installed`;
  62. instructions = `Install webpack to start bundling: \u001b[32m\n $ npm install --save-dev ${moduleName}\n`;
  63. if (process.env.npm_execpath !== undefined && process.env.npm_execpath.includes("yarn")) {
  64. instructions = `Install webpack to start bundling: \u001b[32m\n $ yarn add ${moduleName} --dev\n`;
  65. }
  66. Error.stackTraceLimit = 1;
  67. console.error(`${errorMessage}\n\n${instructions}`);
  68. process.exitCode = 1;
  69. return;
  70. }
  71. }
  72. if (err.name !== "ValidationError") {
  73. throw err;
  74. }
  75. const stack = ErrorHelpers.cleanUpWebpackOptions(err.stack, err.message);
  76. const message = err.message + "\n" + stack;
  77. if (argv.color) {
  78. console.error(`\u001b[1m\u001b[31m${message}\u001b[39m\u001b[22m`);
  79. } else {
  80. console.error(message);
  81. }
  82. process.exitCode = 1;
  83. return;
  84. }
  85. /**
  86. * When --silent flag is present, an object with a no-op write method is
  87. * used in place of process.stout
  88. */
  89. const stdout = argv.silent ? { write: () => {} } : process.stdout;
  90. function ifArg(name, fn, init) {
  91. if (Array.isArray(argv[name])) {
  92. if (init) init();
  93. argv[name].forEach(fn);
  94. } else if (typeof argv[name] !== "undefined") {
  95. if (init) init();
  96. fn(argv[name], -1);
  97. }
  98. }
  99. function processOptions(options) {
  100. // process Promise
  101. if (typeof options.then === "function") {
  102. options.then(processOptions).catch(function(err) {
  103. console.error(err.stack || err);
  104. // eslint-disable-next-line no-process-exit
  105. process.exit(1);
  106. });
  107. return;
  108. }
  109. const firstOptions = [].concat(options)[0];
  110. const statsPresetToOptions = require("webpack").Stats.presetToOptions;
  111. let outputOptions = options.stats;
  112. if (typeof outputOptions === "boolean" || typeof outputOptions === "string") {
  113. outputOptions = statsPresetToOptions(outputOptions);
  114. } else if (!outputOptions) {
  115. outputOptions = {};
  116. }
  117. ifArg("display", function(preset) {
  118. outputOptions = statsPresetToOptions(preset);
  119. });
  120. outputOptions = Object.create(outputOptions);
  121. if (Array.isArray(options) && !outputOptions.children) {
  122. outputOptions.children = options.map(o => o.stats);
  123. }
  124. if (typeof outputOptions.context === "undefined") outputOptions.context = firstOptions.context;
  125. ifArg("env", function(value) {
  126. if (outputOptions.env) {
  127. outputOptions._env = value;
  128. }
  129. });
  130. ifArg("json", function(bool) {
  131. if (bool) {
  132. outputOptions.json = bool;
  133. outputOptions.modules = bool;
  134. }
  135. });
  136. if (typeof outputOptions.colors === "undefined") outputOptions.colors = require("supports-color").stdout;
  137. ifArg("sort-modules-by", function(value) {
  138. outputOptions.modulesSort = value;
  139. });
  140. ifArg("sort-chunks-by", function(value) {
  141. outputOptions.chunksSort = value;
  142. });
  143. ifArg("sort-assets-by", function(value) {
  144. outputOptions.assetsSort = value;
  145. });
  146. ifArg("display-exclude", function(value) {
  147. outputOptions.exclude = value;
  148. });
  149. if (!outputOptions.json) {
  150. if (typeof outputOptions.cached === "undefined") outputOptions.cached = false;
  151. if (typeof outputOptions.cachedAssets === "undefined") outputOptions.cachedAssets = false;
  152. ifArg("display-chunks", function(bool) {
  153. if (bool) {
  154. outputOptions.modules = false;
  155. outputOptions.chunks = true;
  156. outputOptions.chunkModules = true;
  157. }
  158. });
  159. ifArg("display-entrypoints", function(bool) {
  160. outputOptions.entrypoints = bool;
  161. });
  162. ifArg("display-reasons", function(bool) {
  163. if (bool) outputOptions.reasons = true;
  164. });
  165. ifArg("display-depth", function(bool) {
  166. if (bool) outputOptions.depth = true;
  167. });
  168. ifArg("display-used-exports", function(bool) {
  169. if (bool) outputOptions.usedExports = true;
  170. });
  171. ifArg("display-provided-exports", function(bool) {
  172. if (bool) outputOptions.providedExports = true;
  173. });
  174. ifArg("display-optimization-bailout", function(bool) {
  175. if (bool) outputOptions.optimizationBailout = bool;
  176. });
  177. ifArg("display-error-details", function(bool) {
  178. if (bool) outputOptions.errorDetails = true;
  179. });
  180. ifArg("display-origins", function(bool) {
  181. if (bool) outputOptions.chunkOrigins = true;
  182. });
  183. ifArg("display-max-modules", function(value) {
  184. outputOptions.maxModules = +value;
  185. });
  186. ifArg("display-cached", function(bool) {
  187. if (bool) outputOptions.cached = true;
  188. });
  189. ifArg("display-cached-assets", function(bool) {
  190. if (bool) outputOptions.cachedAssets = true;
  191. });
  192. if (!outputOptions.exclude) outputOptions.exclude = ["node_modules", "bower_components", "components"];
  193. if (argv["display-modules"]) {
  194. outputOptions.maxModules = Infinity;
  195. outputOptions.exclude = undefined;
  196. outputOptions.modules = true;
  197. }
  198. }
  199. ifArg("hide-modules", function(bool) {
  200. if (bool) {
  201. outputOptions.modules = false;
  202. outputOptions.chunkModules = false;
  203. }
  204. });
  205. ifArg("info-verbosity", function(value) {
  206. outputOptions.infoVerbosity = value;
  207. });
  208. ifArg("build-delimiter", function(value) {
  209. outputOptions.buildDelimiter = value;
  210. });
  211. const webpack = require("webpack");
  212. let lastHash = null;
  213. let compiler;
  214. try {
  215. compiler = webpack(options);
  216. } catch (err) {
  217. if (err.name === "WebpackOptionsValidationError") {
  218. if (argv.color) console.error(`\u001b[1m\u001b[31m${err.message}\u001b[39m\u001b[22m`);
  219. else console.error(err.message);
  220. // eslint-disable-next-line no-process-exit
  221. process.exit(1);
  222. }
  223. throw err;
  224. }
  225. if (argv.progress) {
  226. const ProgressPlugin = require("webpack").ProgressPlugin;
  227. new ProgressPlugin({
  228. profile: argv.profile
  229. }).apply(compiler);
  230. }
  231. if (outputOptions.infoVerbosity === "verbose") {
  232. if (argv.w) {
  233. compiler.hooks.watchRun.tap("WebpackInfo", compilation => {
  234. const compilationName = compilation.name ? compilation.name : "";
  235. console.error("\nCompilation " + compilationName + " starting…\n");
  236. });
  237. } else {
  238. compiler.hooks.beforeRun.tap("WebpackInfo", compilation => {
  239. const compilationName = compilation.name ? compilation.name : "";
  240. console.error("\nCompilation " + compilationName + " starting…\n");
  241. });
  242. }
  243. compiler.hooks.done.tap("WebpackInfo", compilation => {
  244. const compilationName = compilation.name ? compilation.name : "";
  245. console.error("\nCompilation " + compilationName + " finished\n");
  246. });
  247. }
  248. function compilerCallback(err, stats) {
  249. if (!options.watch || err) {
  250. // Do not keep cache anymore
  251. compiler.purgeInputFileSystem();
  252. }
  253. if (err) {
  254. lastHash = null;
  255. console.error(err.stack || err);
  256. if (err.details) console.error(err.details);
  257. process.exitCode = 1;
  258. return;
  259. }
  260. if (outputOptions.json) {
  261. stdout.write(JSON.stringify(stats.toJson(outputOptions), null, 2) + "\n");
  262. } else if (stats.hash !== lastHash) {
  263. lastHash = stats.hash;
  264. if (stats.compilation && stats.compilation.errors.length !== 0) {
  265. const errors = stats.compilation.errors;
  266. if (errors[0].name === "EntryModuleNotFoundError") {
  267. console.error("\n\u001b[1m\u001b[31mInsufficient number of arguments or no entry found.");
  268. console.error(
  269. "\u001b[1m\u001b[31mAlternatively, run 'webpack(-cli) --help' for usage info.\u001b[39m\u001b[22m\n"
  270. );
  271. }
  272. }
  273. const statsString = stats.toString(outputOptions);
  274. const delimiter = outputOptions.buildDelimiter ? `${outputOptions.buildDelimiter}\n` : "";
  275. if (statsString) stdout.write(`${statsString}\n${delimiter}`);
  276. }
  277. if (!options.watch && stats.hasErrors()) {
  278. process.exitCode = 2;
  279. }
  280. }
  281. if (firstOptions.watch || options.watch) {
  282. const watchOptions =
  283. firstOptions.watchOptions || options.watchOptions || firstOptions.watch || options.watch || {};
  284. if (watchOptions.stdin) {
  285. process.stdin.on("end", function(_) {
  286. process.exit(); // eslint-disable-line
  287. });
  288. process.stdin.resume();
  289. }
  290. compiler.watch(watchOptions, compilerCallback);
  291. if (outputOptions.infoVerbosity !== "none") console.error("\nwebpack is watching the files…\n");
  292. } else {
  293. compiler.run((err, stats) => {
  294. if (compiler.close) {
  295. compiler.close(err2 => {
  296. compilerCallback(err || err2, stats);
  297. });
  298. } else {
  299. compilerCallback(err, stats);
  300. }
  301. });
  302. }
  303. }
  304. processOptions(options);
  305. });
  306. })();