parcel 2.0.0-nightly.99 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/cli.js CHANGED
@@ -1,50 +1,70 @@
1
1
  // @flow
2
2
 
3
- import type {ParcelConfigFile, InitialParcelOptions} from '@parcel/types';
3
+ import type {InitialParcelOptions} from '@parcel/types';
4
4
  import {BuildError} from '@parcel/core';
5
- import {NodePackageManager} from '@parcel/package-manager';
6
5
  import {NodeFS} from '@parcel/fs';
7
6
  import ThrowableDiagnostic from '@parcel/diagnostic';
8
- import {prettyDiagnostic} from '@parcel/utils';
7
+ import {prettyDiagnostic, openInBrowser} from '@parcel/utils';
8
+ import {Disposable} from '@parcel/events';
9
+ import {INTERNAL_ORIGINAL_CONSOLE} from '@parcel/logger';
10
+ import chalk from 'chalk';
11
+ import commander from 'commander';
12
+ import path from 'path';
13
+ import getPort from 'get-port';
14
+ import {version} from '../package.json';
9
15
 
10
16
  require('v8-compile-cache');
11
17
 
12
- function logUncaughtError(e: mixed) {
18
+ const program = new commander.Command();
19
+
20
+ // Exit codes in response to signals are traditionally
21
+ // 128 + signal value
22
+ // https://tldp.org/LDP/abs/html/exitcodes.html
23
+ const SIGINT_EXIT_CODE = 130;
24
+
25
+ async function logUncaughtError(e: mixed) {
13
26
  if (e instanceof ThrowableDiagnostic) {
14
27
  for (let diagnostic of e.diagnostics) {
15
- let out = prettyDiagnostic(diagnostic);
16
- console.error(out.message);
17
- console.error(out.codeframe || out.stack);
18
- for (let h of out.hints) {
19
- console.error(h);
28
+ let {message, codeframe, stack, hints, documentation} =
29
+ await prettyDiagnostic(diagnostic);
30
+ INTERNAL_ORIGINAL_CONSOLE.error(chalk.red(message));
31
+ if (codeframe || stack) {
32
+ INTERNAL_ORIGINAL_CONSOLE.error('');
33
+ }
34
+ INTERNAL_ORIGINAL_CONSOLE.error(codeframe);
35
+ INTERNAL_ORIGINAL_CONSOLE.error(stack);
36
+ if ((stack || codeframe) && hints.length > 0) {
37
+ INTERNAL_ORIGINAL_CONSOLE.error('');
38
+ }
39
+ for (let h of hints) {
40
+ INTERNAL_ORIGINAL_CONSOLE.error(chalk.blue(h));
41
+ }
42
+ if (documentation) {
43
+ INTERNAL_ORIGINAL_CONSOLE.error(chalk.magenta.bold(documentation));
20
44
  }
21
45
  }
22
46
  } else {
23
- console.error(e);
47
+ INTERNAL_ORIGINAL_CONSOLE.error(e);
24
48
  }
49
+
50
+ // A hack to definitely ensure we logged the uncaught exception
51
+ await new Promise(resolve => setTimeout(resolve, 100));
25
52
  }
26
53
 
27
- process.on('unhandledRejection', (reason: mixed) => {
28
- logUncaughtError(reason);
54
+ const handleUncaughtException = async exception => {
55
+ try {
56
+ await logUncaughtError(exception);
57
+ } catch (err) {
58
+ console.error(exception);
59
+ console.error(err);
60
+ }
61
+
29
62
  process.exit(1);
30
- });
63
+ };
31
64
 
32
- const chalk = require('chalk');
33
- const program = require('commander');
34
- const path = require('path');
35
- const getPort = require('get-port');
36
- const version = require('../package.json').version;
37
-
38
- // Capture the NODE_ENV this process was launched with, so that it can be
39
- // used in Parcel (such as in process.env inlining).
40
- const initialNodeEnv = process.env.NODE_ENV;
41
- // Then, override NODE_ENV to be PARCEL_BUILD_ENV (replaced with `production` in builds)
42
- // so that dependencies of Parcel like React (which renders the cli through `ink`)
43
- // run in the appropriate mode.
44
- if (typeof process.env.PARCEL_BUILD_ENV === 'string') {
45
- process.env.NODE_ENV = process.env.PARCEL_BUILD_ENV;
46
- }
65
+ process.on('unhandledRejection', handleUncaughtException);
47
66
 
67
+ program.storeOptionsAsProperties();
48
68
  program.version(version);
49
69
 
50
70
  // --no-cache, --cache-dir, --no-source-maps, --no-autoinstall, --global?, --public-url, --log-level
@@ -52,57 +72,77 @@ program.version(version);
52
72
 
53
73
  const commonOptions = {
54
74
  '--no-cache': 'disable the filesystem cache',
75
+ '--config <path>':
76
+ 'specify which config to use. can be a path or a package name',
55
77
  '--cache-dir <path>': 'set the cache directory. defaults to ".parcel-cache"',
56
78
  '--no-source-maps': 'disable sourcemaps',
57
- '--no-autoinstall': 'disable autoinstall',
58
79
  '--target [name]': [
59
80
  'only build given target(s)',
60
81
  (val, list) => list.concat([val]),
61
82
  [],
62
83
  ],
63
- '--log-level <level>': [
64
- 'set the log level, either "none", "error", "warn", "info", or "verbose".',
65
- /^(none|error|warn|info|verbose)$/,
66
- ],
84
+ '--log-level <level>': new commander.Option(
85
+ '--log-level <level>',
86
+ 'set the log level',
87
+ ).choices(['none', 'error', 'warn', 'info', 'verbose']),
88
+ '--dist-dir <dir>':
89
+ 'output directory to write to when unspecified by targets',
90
+ '--no-autoinstall': 'disable autoinstall',
67
91
  '--profile': 'enable build profiling',
68
92
  '-V, --version': 'output the version number',
93
+ '--detailed-report [count]': [
94
+ 'print the asset timings and sizes in the build report',
95
+ parseOptionInt,
96
+ ],
97
+ '--reporter <name>': [
98
+ 'additional reporters to run',
99
+ (val, acc) => {
100
+ acc.push(val);
101
+ return acc;
102
+ },
103
+ [],
104
+ ],
69
105
  };
70
106
 
71
107
  var hmrOptions = {
72
108
  '--no-hmr': 'disable hot module replacement',
109
+ '-p, --port <port>': [
110
+ 'set the port to serve on. defaults to $PORT or 1234',
111
+ process.env.PORT,
112
+ ],
113
+ '--host <host>':
114
+ 'set the host to listen on, defaults to listening on all interfaces',
73
115
  '--https': 'serves files over HTTPS',
74
116
  '--cert <path>': 'path to certificate to use with HTTPS',
75
117
  '--key <path>': 'path to private key to use with HTTPS',
118
+ '--hmr-port <port>': ['hot module replacement port', process.env.HMR_PORT],
76
119
  };
77
120
 
78
121
  function applyOptions(cmd, options) {
79
122
  for (let opt in options) {
80
- cmd.option(
81
- opt,
82
- ...(Array.isArray(options[opt]) ? options[opt] : [options[opt]]),
83
- );
123
+ const option = options[opt];
124
+ if (option instanceof commander.Option) {
125
+ cmd.addOption(option);
126
+ } else {
127
+ cmd.option(opt, ...(Array.isArray(option) ? option : [option]));
128
+ }
84
129
  }
85
130
  }
86
131
 
87
132
  let serve = program
88
133
  .command('serve [input...]')
89
134
  .description('starts a development server')
90
- .option(
91
- '-p, --port <port>',
92
- 'set the port to serve on. defaults to 1234',
93
- parseInt,
94
- )
95
135
  .option('--public-url <url>', 'the path prefix for absolute urls')
96
- .option(
97
- '--host <host>',
98
- 'set the host to listen on, defaults to listening on all interfaces',
99
- )
100
136
  .option(
101
137
  '--open [browser]',
102
138
  'automatically open in specified browser, defaults to default browser',
103
139
  )
104
140
  .option('--watch-for-stdin', 'exit when stdin closes')
105
- .action(run);
141
+ .option(
142
+ '--lazy',
143
+ 'Build async bundles on demand, when requested in the browser',
144
+ )
145
+ .action(runCommand);
106
146
 
107
147
  applyOptions(serve, hmrOptions);
108
148
  applyOptions(serve, commonOptions);
@@ -110,13 +150,10 @@ applyOptions(serve, commonOptions);
110
150
  let watch = program
111
151
  .command('watch [input...]')
112
152
  .description('starts the bundler in watch mode')
113
- .option(
114
- '--dist-dir <dir>',
115
- 'output directory to write to when unspecified by targets',
116
- )
117
153
  .option('--public-url <url>', 'the path prefix for absolute urls')
154
+ .option('--no-content-hash', 'disable content hashing')
118
155
  .option('--watch-for-stdin', 'exit when stdin closes')
119
- .action(run);
156
+ .action(runCommand);
120
157
 
121
158
  applyOptions(watch, hmrOptions);
122
159
  applyOptions(watch, commonOptions);
@@ -124,143 +161,237 @@ applyOptions(watch, commonOptions);
124
161
  let build = program
125
162
  .command('build [input...]')
126
163
  .description('bundles for production')
127
- .option('--no-minify', 'disable minification')
164
+ .option('--no-optimize', 'disable minification')
128
165
  .option('--no-scope-hoist', 'disable scope-hoisting')
129
166
  .option('--public-url <url>', 'the path prefix for absolute urls')
130
- .option(
131
- '--dist-dir <dir>',
132
- 'Output directory to write to when unspecified by targets',
133
- )
134
- .action(run);
167
+ .option('--no-content-hash', 'disable content hashing')
168
+ .action(runCommand);
135
169
 
136
170
  applyOptions(build, commonOptions);
137
171
 
138
172
  program
139
173
  .command('help [command]')
140
174
  .description('display help information for a command')
141
- .action(function(command) {
175
+ .action(function (command) {
142
176
  let cmd = program.commands.find(c => c.name() === command) || program;
143
177
  cmd.help();
144
178
  });
145
179
 
146
- program.on('--help', function() {
147
- console.log('');
148
- console.log(
180
+ program.on('--help', function () {
181
+ INTERNAL_ORIGINAL_CONSOLE.log('');
182
+ INTERNAL_ORIGINAL_CONSOLE.log(
149
183
  ' Run `' +
150
184
  chalk.bold('parcel help <command>') +
151
185
  '` for more information on specific commands',
152
186
  );
153
- console.log('');
187
+ INTERNAL_ORIGINAL_CONSOLE.log('');
154
188
  });
155
189
 
190
+ // Override to output option description if argument was missing
191
+ commander.Command.prototype.optionMissingArgument = function (option) {
192
+ INTERNAL_ORIGINAL_CONSOLE.error(
193
+ "error: option `%s' argument missing",
194
+ option.flags,
195
+ );
196
+ INTERNAL_ORIGINAL_CONSOLE.log(program.createHelp().optionDescription(option));
197
+ process.exit(1);
198
+ };
199
+
156
200
  // Make serve the default command except for --help
157
201
  var args = process.argv;
158
202
  if (args[2] === '--help' || args[2] === '-h') args[2] = 'help';
203
+
159
204
  if (!args[2] || !program.commands.some(c => c.name() === args[2])) {
160
205
  args.splice(2, 0, 'serve');
161
206
  }
162
207
 
163
208
  program.parse(args);
164
209
 
165
- async function run(entries: Array<string>, command: any) {
166
- entries = entries.map(entry => path.resolve(entry));
210
+ function runCommand(...args) {
211
+ run(...args).catch(handleUncaughtException);
212
+ }
167
213
 
214
+ async function run(
215
+ entries: Array<string>,
216
+ _opts: any, // using pre v7 Commander options as properties
217
+ command: any,
218
+ ) {
168
219
  if (entries.length === 0) {
169
- console.log('No entries found');
170
- return;
220
+ entries = ['.'];
171
221
  }
222
+
223
+ entries = entries.map(entry => path.resolve(entry));
224
+
172
225
  let Parcel = require('@parcel/core').default;
173
- let packageManager = new NodePackageManager(new NodeFS());
174
- let defaultConfig: ParcelConfigFile = await packageManager.require(
175
- '@parcel/config-default',
176
- __filename,
177
- );
226
+ let fs = new NodeFS();
227
+ let options = await normalizeOptions(command, fs);
178
228
  let parcel = new Parcel({
179
229
  entries,
180
- packageManager,
181
- defaultConfig: {
182
- ...defaultConfig,
183
- filePath: (
184
- await packageManager.resolve('@parcel/config-default', __filename)
185
- ).resolved,
186
- },
187
- patchConsole: true,
188
- ...(await normalizeOptions(command)),
230
+ // $FlowFixMe[extra-arg] - flow doesn't know about the `paths` option (added in Node v8.9.0)
231
+ defaultConfig: require.resolve('@parcel/config-default', {
232
+ paths: [fs.cwd(), __dirname],
233
+ }),
234
+ shouldPatchConsole: true,
235
+ ...options,
189
236
  });
190
237
 
191
- if (command.name() === 'watch' || command.name() === 'serve') {
192
- let {unsubscribe} = await parcel.watch(err => {
193
- if (err) {
194
- throw err;
195
- }
196
- });
238
+ let disposable = new Disposable();
239
+ let unsubscribe: () => Promise<mixed>;
240
+ let isExiting;
241
+ async function exit(exitCode: number = 0) {
242
+ if (isExiting) {
243
+ return;
244
+ }
197
245
 
198
- let isExiting;
199
- const exit = async () => {
200
- if (isExiting) {
246
+ isExiting = true;
247
+ if (unsubscribe != null) {
248
+ await unsubscribe();
249
+ } else if (parcel.isProfiling) {
250
+ await parcel.stopProfiling();
251
+ }
252
+
253
+ if (process.stdin.isTTY && process.stdin.isRaw) {
254
+ // $FlowFixMe
255
+ process.stdin.setRawMode(false);
256
+ }
257
+
258
+ disposable.dispose();
259
+ process.exit(exitCode);
260
+ }
261
+
262
+ const isWatching = command.name() === 'watch' || command.name() === 'serve';
263
+ if (process.stdin.isTTY) {
264
+ // $FlowFixMe
265
+ process.stdin.setRawMode(true);
266
+ require('readline').emitKeypressEvents(process.stdin);
267
+
268
+ let stream = process.stdin.on('keypress', async (char, key) => {
269
+ if (!key.ctrl) {
201
270
  return;
202
271
  }
203
272
 
204
- isExiting = true;
205
- await unsubscribe();
206
- process.exit();
207
- };
273
+ switch (key.name) {
274
+ case 'c':
275
+ // Detect the ctrl+c key, and gracefully exit after writing the asset graph to the cache.
276
+ // This is mostly for tools that wrap Parcel as a child process like yarn and npm.
277
+ //
278
+ // Setting raw mode prevents SIGINT from being sent in response to ctrl-c:
279
+ // https://nodejs.org/api/tty.html#tty_readstream_setrawmode_mode
280
+ //
281
+ // We don't use the SIGINT event for this because when run inside yarn, the parent
282
+ // yarn process ends before Parcel and it appears that Parcel has ended while it may still
283
+ // be cleaning up. Handling events from stdin prevents this impression.
284
+
285
+ // Enqueue a busy message to be shown if Parcel doesn't shut down
286
+ // within the timeout.
287
+ setTimeout(
288
+ () =>
289
+ INTERNAL_ORIGINAL_CONSOLE.log(
290
+ chalk.bold.yellowBright('Parcel is shutting down...'),
291
+ ),
292
+ 500,
293
+ );
294
+ // When watching, a 0 success code is acceptable when Parcel is interrupted with ctrl-c.
295
+ // When building, fail with a code as if we received a SIGINT.
296
+ await exit(isWatching ? 0 : SIGINT_EXIT_CODE);
297
+ break;
298
+ case 'e':
299
+ await (parcel.isProfiling
300
+ ? parcel.stopProfiling()
301
+ : parcel.startProfiling());
302
+ break;
303
+ case 'y':
304
+ await parcel.takeHeapSnapshot();
305
+ break;
306
+ }
307
+ });
308
+
309
+ disposable.add(() => {
310
+ stream.destroy();
311
+ });
312
+ }
313
+
314
+ if (isWatching) {
315
+ ({unsubscribe} = await parcel.watch(err => {
316
+ if (err) {
317
+ throw err;
318
+ }
319
+ }));
320
+
321
+ if (command.open && options.serveOptions) {
322
+ await openInBrowser(
323
+ `${options.serveOptions.https ? 'https' : 'http'}://${
324
+ options.serveOptions.host || 'localhost'
325
+ }:${options.serveOptions.port}`,
326
+ command.open,
327
+ );
328
+ }
208
329
 
209
330
  if (command.watchForStdin) {
210
331
  process.stdin.on('end', async () => {
211
- console.log('STDIN closed, ending');
332
+ INTERNAL_ORIGINAL_CONSOLE.log('STDIN closed, ending');
212
333
 
213
334
  await exit();
214
335
  });
215
336
  process.stdin.resume();
216
337
  }
217
338
 
218
- // Detect the ctrl+c key, and gracefully exit after writing the asset graph to the cache.
219
- // This is mostly for tools that wrap Parcel as a child process like yarn and npm.
220
- //
221
- // Setting raw mode prevents SIGINT from being sent in response to ctrl-c:
222
- // https://nodejs.org/api/tty.html#tty_readstream_setrawmode_mode
223
- //
224
- // We don't use the SIGINT event for this because when run inside yarn, the parent
225
- // yarn process ends before Parcel and it appears that Parcel has ended while it may still
226
- // be cleaning up. Handling events from stdin prevents this impression.
227
- if (process.stdin.isTTY) {
228
- // $FlowFixMe
229
- process.stdin.setRawMode(true);
230
- require('readline').emitKeypressEvents(process.stdin);
231
-
232
- process.stdin.on('keypress', async (char, key) => {
233
- if (key.ctrl && key.name === 'c') {
234
- await exit();
235
- }
236
- });
237
- }
238
-
239
- // In non-tty cases, respond to SIGINT by cleaning up.
339
+ // In non-tty cases, respond to SIGINT by cleaning up. Since we're watching,
340
+ // a 0 success code is acceptable.
240
341
  process.on('SIGINT', exit);
241
342
  process.on('SIGTERM', exit);
242
343
  } else {
243
344
  try {
244
345
  await parcel.run();
245
- } catch (e) {
346
+ } catch (err) {
246
347
  // If an exception is thrown during Parcel.build, it is given to reporters in a
247
348
  // buildFailure event, and has been shown to the user.
248
- if (!(e instanceof BuildError)) {
249
- logUncaughtError(e);
349
+ if (!(err instanceof BuildError)) {
350
+ await logUncaughtError(err);
250
351
  }
251
- process.exit(1);
352
+ await exit(1);
252
353
  }
354
+
355
+ await exit();
253
356
  }
254
357
  }
255
358
 
256
- async function normalizeOptions(command): Promise<InitialParcelOptions> {
359
+ function parsePort(portValue: string): number {
360
+ let parsedPort = Number(portValue);
361
+
362
+ // Throw an error if port value is invalid...
363
+ if (!Number.isInteger(parsedPort)) {
364
+ throw new Error(`Port ${portValue} is not a valid integer.`);
365
+ }
366
+
367
+ return parsedPort;
368
+ }
369
+
370
+ function parseOptionInt(value) {
371
+ const parsedValue = parseInt(value, 10);
372
+ if (isNaN(parsedValue)) {
373
+ throw new commander.InvalidOptionArgumentError('Must be an integer.');
374
+ }
375
+ return parsedValue;
376
+ }
377
+
378
+ async function normalizeOptions(
379
+ command,
380
+ inputFS,
381
+ ): Promise<InitialParcelOptions> {
257
382
  let nodeEnv;
258
383
  if (command.name() === 'build') {
259
- nodeEnv = initialNodeEnv || 'production';
384
+ nodeEnv = process.env.NODE_ENV || 'production';
385
+ // Autoinstall unless explicitly disabled or we detect a CI environment.
386
+ command.autoinstall = !(command.autoinstall === false || process.env.CI);
260
387
  } else {
261
- nodeEnv = initialNodeEnv || 'development';
388
+ nodeEnv = process.env.NODE_ENV || 'development';
262
389
  }
263
390
 
391
+ // Set process.env.NODE_ENV to a default if undefined so that it is
392
+ // available in JS configs and plugins.
393
+ process.env.NODE_ENV = nodeEnv;
394
+
264
395
  let https = !!command.https;
265
396
  if (command.cert && command.key) {
266
397
  https = {
@@ -269,19 +400,41 @@ async function normalizeOptions(command): Promise<InitialParcelOptions> {
269
400
  };
270
401
  }
271
402
 
272
- let serve = false;
273
- if (command.name() === 'serve') {
274
- let {port = 1234, host, publicUrl} = command;
275
- port = await getPort({port, host});
403
+ let serveOptions = false;
404
+ let {host} = command;
276
405
 
277
- if (command.port && port !== command.port) {
278
- // Parcel logger is not set up at this point, so just use native console.
279
- console.warn(
280
- chalk.bold.yellowBright(`⚠️ Port ${command.port} could not be used.`),
281
- );
406
+ // Ensure port is valid and available
407
+ let port = parsePort(command.port || '1234');
408
+ let originalPort = port;
409
+ if (command.name() === 'serve' || command.hmr) {
410
+ try {
411
+ port = await getPort({port, host});
412
+ } catch (err) {
413
+ throw new ThrowableDiagnostic({
414
+ diagnostic: {
415
+ message: `Could not get available port: ${err.message}`,
416
+ origin: 'parcel',
417
+ stack: err.stack,
418
+ },
419
+ });
420
+ }
421
+
422
+ if (port !== originalPort) {
423
+ let errorMessage = `Port "${originalPort}" could not be used`;
424
+ if (command.port != null) {
425
+ // Throw the error if the user defined a custom port
426
+ throw new Error(errorMessage);
427
+ } else {
428
+ // Parcel logger is not set up at this point, so just use native INTERNAL_ORIGINAL_CONSOLE
429
+ INTERNAL_ORIGINAL_CONSOLE.warn(errorMessage);
430
+ }
282
431
  }
432
+ }
433
+
434
+ if (command.name() === 'serve') {
435
+ let {publicUrl} = command;
283
436
 
284
- serve = {
437
+ serveOptions = {
285
438
  https,
286
439
  port,
287
440
  host,
@@ -289,29 +442,56 @@ async function normalizeOptions(command): Promise<InitialParcelOptions> {
289
442
  };
290
443
  }
291
444
 
292
- let hmr = false;
445
+ let hmrOptions = null;
293
446
  if (command.name() !== 'build' && command.hmr !== false) {
294
- hmr = true;
447
+ let hmrport = command.hmrPort ? parsePort(command.hmrPort) : port;
448
+
449
+ hmrOptions = {port: hmrport, host};
450
+ }
451
+
452
+ if (command.detailedReport === true) {
453
+ command.detailedReport = '10';
295
454
  }
296
455
 
456
+ let additionalReporters = [
457
+ {packageName: '@parcel/reporter-cli', resolveFrom: __filename},
458
+ ...(command.reporter: Array<string>).map(packageName => ({
459
+ packageName,
460
+ resolveFrom: path.join(inputFS.cwd(), 'index'),
461
+ })),
462
+ ];
463
+
297
464
  let mode = command.name() === 'build' ? 'production' : 'development';
298
465
  return {
299
- disableCache: command.cache === false,
466
+ shouldDisableCache: command.cache === false,
300
467
  cacheDir: command.cacheDir,
468
+ config: command.config,
301
469
  mode,
302
- minify: command.minify != null ? command.minify : mode === 'production',
303
- sourceMaps: command.sourceMaps ?? true,
304
- scopeHoist: command.scopeHoist,
305
- publicUrl: command.publicUrl,
306
- distDir: command.distDir,
307
- hot: hmr,
308
- serve,
470
+ hmrOptions,
471
+ shouldContentHash: hmrOptions ? false : command.contentHash,
472
+ serveOptions,
309
473
  targets: command.target.length > 0 ? command.target : null,
310
- autoinstall: command.autoinstall ?? true,
474
+ shouldAutoInstall: command.autoinstall ?? true,
311
475
  logLevel: command.logLevel,
312
- profile: command.profile,
476
+ shouldProfile: command.profile,
477
+ shouldBuildLazily: command.lazy,
478
+ detailedReport:
479
+ command.detailedReport != null
480
+ ? {
481
+ assetsPerBundle: parseInt(command.detailedReport, 10),
482
+ }
483
+ : null,
313
484
  env: {
314
485
  NODE_ENV: nodeEnv,
315
486
  },
487
+ additionalReporters,
488
+ defaultTargetOptions: {
489
+ shouldOptimize:
490
+ command.optimize != null ? command.optimize : mode === 'production',
491
+ sourceMaps: command.sourceMaps ?? true,
492
+ shouldScopeHoist: command.scopeHoist,
493
+ publicUrl: command.publicUrl,
494
+ distDir: command.distDir,
495
+ },
316
496
  };
317
497
  }