webpack.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. #!/usr/bin/env node
  2. /*
  3. MIT License http://www.opensource.org/licenses/mit-license.php
  4. Author Tobias Koppers @sokra
  5. */
  6. var path = require("path");
  7. // Local version replace global one
  8. try {
  9. var localWebpack = require.resolve(path.join(process.cwd(), "node_modules", "webpack", "bin", "webpack.js"));
  10. if(__filename !== localWebpack) {
  11. return require(localWebpack);
  12. }
  13. } catch(e) {}
  14. var yargs = require("yargs")
  15. .usage("webpack " + require("../package.json").version + "\n" +
  16. "Usage: https://webpack.js.org/api/cli/\n" +
  17. "Usage without config file: webpack <entry> [<entry>] <output>\n" +
  18. "Usage with config file: webpack");
  19. require("./config-yargs")(yargs);
  20. var DISPLAY_GROUP = "Stats options:";
  21. var BASIC_GROUP = "Basic options:";
  22. yargs.options({
  23. "json": {
  24. type: "boolean",
  25. alias: "j",
  26. describe: "Prints the result as JSON."
  27. },
  28. "progress": {
  29. type: "boolean",
  30. describe: "Print compilation progress in percentage",
  31. group: BASIC_GROUP
  32. },
  33. "color": {
  34. type: "boolean",
  35. alias: "colors",
  36. default: function supportsColor() {
  37. return require("supports-color");
  38. },
  39. group: DISPLAY_GROUP,
  40. describe: "Enables/Disables colors on the console"
  41. },
  42. "sort-modules-by": {
  43. type: "string",
  44. group: DISPLAY_GROUP,
  45. describe: "Sorts the modules list by property in module"
  46. },
  47. "sort-chunks-by": {
  48. type: "string",
  49. group: DISPLAY_GROUP,
  50. describe: "Sorts the chunks list by property in chunk"
  51. },
  52. "sort-assets-by": {
  53. type: "string",
  54. group: DISPLAY_GROUP,
  55. describe: "Sorts the assets list by property in asset"
  56. },
  57. "hide-modules": {
  58. type: "boolean",
  59. group: DISPLAY_GROUP,
  60. describe: "Hides info about modules"
  61. },
  62. "display-exclude": {
  63. type: "string",
  64. group: DISPLAY_GROUP,
  65. describe: "Exclude modules in the output"
  66. },
  67. "display-modules": {
  68. type: "boolean",
  69. group: DISPLAY_GROUP,
  70. describe: "Display even excluded modules in the output"
  71. },
  72. "display-max-modules": {
  73. type: "number",
  74. group: DISPLAY_GROUP,
  75. describe: "Sets the maximum number of visible modules in output"
  76. },
  77. "display-chunks": {
  78. type: "boolean",
  79. group: DISPLAY_GROUP,
  80. describe: "Display chunks in the output"
  81. },
  82. "display-entrypoints": {
  83. type: "boolean",
  84. group: DISPLAY_GROUP,
  85. describe: "Display entry points in the output"
  86. },
  87. "display-origins": {
  88. type: "boolean",
  89. group: DISPLAY_GROUP,
  90. describe: "Display origins of chunks in the output"
  91. },
  92. "display-cached": {
  93. type: "boolean",
  94. group: DISPLAY_GROUP,
  95. describe: "Display also cached modules in the output"
  96. },
  97. "display-cached-assets": {
  98. type: "boolean",
  99. group: DISPLAY_GROUP,
  100. describe: "Display also cached assets in the output"
  101. },
  102. "display-reasons": {
  103. type: "boolean",
  104. group: DISPLAY_GROUP,
  105. describe: "Display reasons about module inclusion in the output"
  106. },
  107. "display-depth": {
  108. type: "boolean",
  109. group: DISPLAY_GROUP,
  110. describe: "Display distance from entry point for each module"
  111. },
  112. "display-used-exports": {
  113. type: "boolean",
  114. group: DISPLAY_GROUP,
  115. describe: "Display information about used exports in modules (Tree Shaking)"
  116. },
  117. "display-provided-exports": {
  118. type: "boolean",
  119. group: DISPLAY_GROUP,
  120. describe: "Display information about exports provided from modules"
  121. },
  122. "display-optimization-bailout": {
  123. type: "boolean",
  124. group: DISPLAY_GROUP,
  125. describe: "Display information about why optimization bailed out for modules"
  126. },
  127. "display-error-details": {
  128. type: "boolean",
  129. group: DISPLAY_GROUP,
  130. describe: "Display details about errors"
  131. },
  132. "display": {
  133. type: "string",
  134. group: DISPLAY_GROUP,
  135. describe: "Select display preset (verbose, detailed, normal, minimal, errors-only, none)"
  136. },
  137. "verbose": {
  138. type: "boolean",
  139. group: DISPLAY_GROUP,
  140. describe: "Show more details"
  141. }
  142. });
  143. // yargs will terminate the process early when the user uses help or version.
  144. // This causes large help outputs to be cut short (https://github.com/nodejs/node/wiki/API-changes-between-v0.10-and-v4#process).
  145. // To prevent this we use the yargs.parse API and exit the process normally
  146. yargs.parse(process.argv.slice(2), (err, argv, output) => {
  147. // arguments validation failed
  148. if(err && output) {
  149. console.error(output);
  150. process.exitCode = 1;
  151. return;
  152. }
  153. // help or version info
  154. if(output) {
  155. console.log(output);
  156. return;
  157. }
  158. if(argv.verbose) {
  159. argv["display"] = "verbose";
  160. }
  161. var options = require("./convert-argv")(yargs, argv);
  162. function ifArg(name, fn, init) {
  163. if(Array.isArray(argv[name])) {
  164. if(init) init();
  165. argv[name].forEach(fn);
  166. } else if(typeof argv[name] !== "undefined") {
  167. if(init) init();
  168. fn(argv[name], -1);
  169. }
  170. }
  171. function processOptions(options) {
  172. // process Promise
  173. if(typeof options.then === "function") {
  174. options.then(processOptions).catch(function(err) {
  175. console.error(err.stack || err);
  176. process.exit(1); // eslint-disable-line
  177. });
  178. return;
  179. }
  180. var firstOptions = [].concat(options)[0];
  181. var statsPresetToOptions = require("../lib/Stats.js").presetToOptions;
  182. var outputOptions = options.stats;
  183. if(typeof outputOptions === "boolean" || typeof outputOptions === "string") {
  184. outputOptions = statsPresetToOptions(outputOptions);
  185. } else if(!outputOptions) {
  186. outputOptions = {};
  187. }
  188. ifArg("display", function(preset) {
  189. outputOptions = statsPresetToOptions(preset);
  190. });
  191. outputOptions = Object.create(outputOptions);
  192. if(Array.isArray(options) && !outputOptions.children) {
  193. outputOptions.children = options.map(o => o.stats);
  194. }
  195. if(typeof outputOptions.context === "undefined")
  196. outputOptions.context = firstOptions.context;
  197. ifArg("env", function(value) {
  198. if(outputOptions.env) {
  199. outputOptions._env = value;
  200. }
  201. });
  202. ifArg("json", function(bool) {
  203. if(bool)
  204. outputOptions.json = bool;
  205. });
  206. if(typeof outputOptions.colors === "undefined")
  207. outputOptions.colors = require("supports-color");
  208. ifArg("sort-modules-by", function(value) {
  209. outputOptions.modulesSort = value;
  210. });
  211. ifArg("sort-chunks-by", function(value) {
  212. outputOptions.chunksSort = value;
  213. });
  214. ifArg("sort-assets-by", function(value) {
  215. outputOptions.assetsSort = value;
  216. });
  217. ifArg("display-exclude", function(value) {
  218. outputOptions.exclude = value;
  219. });
  220. if(!outputOptions.json) {
  221. if(typeof outputOptions.cached === "undefined")
  222. outputOptions.cached = false;
  223. if(typeof outputOptions.cachedAssets === "undefined")
  224. outputOptions.cachedAssets = false;
  225. ifArg("display-chunks", function(bool) {
  226. if(bool) {
  227. outputOptions.modules = false;
  228. outputOptions.chunks = true;
  229. outputOptions.chunkModules = true;
  230. }
  231. });
  232. ifArg("display-entrypoints", function(bool) {
  233. if(bool)
  234. outputOptions.entrypoints = true;
  235. });
  236. ifArg("display-reasons", function(bool) {
  237. if(bool)
  238. outputOptions.reasons = true;
  239. });
  240. ifArg("display-depth", function(bool) {
  241. if(bool)
  242. outputOptions.depth = true;
  243. });
  244. ifArg("display-used-exports", function(bool) {
  245. if(bool)
  246. outputOptions.usedExports = true;
  247. });
  248. ifArg("display-provided-exports", function(bool) {
  249. if(bool)
  250. outputOptions.providedExports = true;
  251. });
  252. ifArg("display-optimization-bailout", function(bool) {
  253. if(bool)
  254. outputOptions.optimizationBailout = bool;
  255. });
  256. ifArg("display-error-details", function(bool) {
  257. if(bool)
  258. outputOptions.errorDetails = true;
  259. });
  260. ifArg("display-origins", function(bool) {
  261. if(bool)
  262. outputOptions.chunkOrigins = true;
  263. });
  264. ifArg("display-max-modules", function(value) {
  265. outputOptions.maxModules = +value;
  266. });
  267. ifArg("display-cached", function(bool) {
  268. if(bool)
  269. outputOptions.cached = true;
  270. });
  271. ifArg("display-cached-assets", function(bool) {
  272. if(bool)
  273. outputOptions.cachedAssets = true;
  274. });
  275. if(!outputOptions.exclude)
  276. outputOptions.exclude = ["node_modules", "bower_components", "components"];
  277. if(argv["display-modules"]) {
  278. outputOptions.maxModules = Infinity;
  279. outputOptions.exclude = undefined;
  280. outputOptions.modules = true;
  281. }
  282. }
  283. ifArg("hide-modules", function(bool) {
  284. if(bool) {
  285. outputOptions.modules = false;
  286. outputOptions.chunkModules = false;
  287. }
  288. });
  289. var webpack = require("../lib/webpack.js");
  290. Error.stackTraceLimit = 30;
  291. var lastHash = null;
  292. var compiler;
  293. try {
  294. compiler = webpack(options);
  295. } catch(err) {
  296. if(err.name === "WebpackOptionsValidationError") {
  297. if(argv.color)
  298. console.error(
  299. `\u001b[1m\u001b[31m${err.message}\u001b[39m\u001b[22m`
  300. );
  301. else
  302. console.error(err.message);
  303. // eslint-disable-next-line no-process-exit
  304. process.exit(1);
  305. }
  306. throw err;
  307. }
  308. if(argv.progress) {
  309. var ProgressPlugin = require("../lib/ProgressPlugin");
  310. compiler.apply(new ProgressPlugin({
  311. profile: argv.profile
  312. }));
  313. }
  314. function compilerCallback(err, stats) {
  315. if(!options.watch || err) {
  316. // Do not keep cache anymore
  317. compiler.purgeInputFileSystem();
  318. }
  319. if(err) {
  320. lastHash = null;
  321. console.error(err.stack || err);
  322. if(err.details) console.error(err.details);
  323. process.exitCode = 1;
  324. return;
  325. }
  326. if(outputOptions.json) {
  327. process.stdout.write(JSON.stringify(stats.toJson(outputOptions), null, 2) + "\n");
  328. } else if(stats.hash !== lastHash) {
  329. lastHash = stats.hash;
  330. var statsString = stats.toString(outputOptions);
  331. if(statsString)
  332. process.stdout.write(statsString + "\n");
  333. }
  334. if(!options.watch && stats.hasErrors()) {
  335. process.exitCode = 2;
  336. }
  337. }
  338. if(firstOptions.watch || options.watch) {
  339. var watchOptions = firstOptions.watchOptions || firstOptions.watch || options.watch || {};
  340. if(watchOptions.stdin) {
  341. process.stdin.on("end", function() {
  342. process.exit(); // eslint-disable-line
  343. });
  344. process.stdin.resume();
  345. }
  346. compiler.watch(watchOptions, compilerCallback);
  347. console.log("\nWebpack is watching the files…\n");
  348. } else
  349. compiler.run(compilerCallback);
  350. }
  351. processOptions(options);
  352. });