Skip to content

Commit 7590f66

Browse files
feat: added build command (aliases - 'bundle' and 'b')
1 parent 87b51c3 commit 7590f66

File tree

13 files changed

+131
-57
lines changed

13 files changed

+131
-57
lines changed

OPTIONS.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
```
22
Usage: webpack [options]
3-
Alternative usage: webpack bundle [options]
43
Alternative usage: webpack --config <config> [options]
5-
Alternative usage: webpack bundle --config <config> [options]
4+
Alternative usage: webpack build [options]
5+
Alternative usage: webpack bundle [options]
6+
Alternative usage: webpack b [options]
7+
Alternative usage: webpack build --config <config> [options]
68
79
The build tool for modern web applications.
810
@@ -697,7 +699,7 @@ Global options:
697699
-h, --help [verbose] Display help for commands and options.
698700
699701
Commands:
700-
bundle|b [options] Run webpack (default command, can be omitted).
702+
build|bundle|b [options] Run webpack (default command, can be omitted).
701703
version|v Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands.
702704
help|h Display help for commands and options.
703705
serve|s [options] Run the webpack dev server.

packages/webpack-cli/lib/webpack-cli.js

+59-44
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class WebpackCLI {
3131

3232
async makeCommand(commandOptions, options, action) {
3333
const alreadyLoaded = this.program.commands.find(
34-
(command) => command.name() === commandOptions.name || command.alias() === commandOptions.alias,
34+
(command) => command.name() === commandOptions.name || command.aliases().includes(commandOptions.alias),
3535
);
3636

3737
if (alreadyLoaded) {
@@ -229,9 +229,9 @@ class WebpackCLI {
229229

230230
async run(args, parseOptions) {
231231
// Built-in internal commands
232-
const bundleCommandOptions = {
233-
name: 'bundle',
234-
alias: 'b',
232+
const buildCommandOptions = {
233+
name: 'build',
234+
alias: ['bundle', 'b'],
235235
description: 'Run webpack (default command, can be omitted).',
236236
usage: '[options]',
237237
};
@@ -286,8 +286,25 @@ class WebpackCLI {
286286
},
287287
];
288288

289-
const knownCommands = [bundleCommandOptions, versionCommandOptions, helpCommandOptions, ...externalBuiltInCommandsInfo];
290-
const isKnownCommand = (name) => knownCommands.find((command) => command.name === name || command.alias === name);
289+
const knownCommands = [buildCommandOptions, versionCommandOptions, helpCommandOptions, ...externalBuiltInCommandsInfo];
290+
const isKnownCommand = (name) =>
291+
knownCommands.find(
292+
(command) =>
293+
command.name === name || (Array.isArray(command.alias) ? command.alias.includes(name) : command.alias === name),
294+
);
295+
const isBuildCommand = (name) =>
296+
buildCommandOptions.name === name ||
297+
(Array.isArray(buildCommandOptions.alias) ? buildCommandOptions.alias.includes(name) : buildCommandOptions.alias === name);
298+
const isHelpCommand = (name) =>
299+
helpCommandOptions.name === name ||
300+
(Array.isArray(helpCommandOptions.alias) ? helpCommandOptions.alias.includes(name) : helpCommandOptions.alias === name);
301+
const isVersionCommand = (name) =>
302+
versionCommandOptions.name === name ||
303+
(Array.isArray(versionCommandOptions.alias)
304+
? versionCommandOptions.alias.includes(name)
305+
: versionCommandOptions.alias === name);
306+
const findCommandByName = (name) =>
307+
this.program.commands.find((command) => name === command.name() || command.alias().includes(name));
291308

292309
const getCommandNameAndOptions = (args) => {
293310
let commandName;
@@ -311,16 +328,15 @@ class WebpackCLI {
311328

312329
const isDefault = typeof commandName === 'undefined';
313330

314-
return { commandName: isDefault ? bundleCommandOptions.name : commandName, options, isDefault };
331+
return { commandName: isDefault ? buildCommandOptions.name : commandName, options, isDefault };
315332
};
316333
const loadCommandByName = async (commandName, allowToInstall = false) => {
317-
if (commandName === bundleCommandOptions.name || commandName === bundleCommandOptions.alias) {
318-
// Make `bundle|b [options]` command
319-
await this.makeCommand(bundleCommandOptions, this.getBuiltInOptions(), async (program) => {
334+
if (isBuildCommand(commandName)) {
335+
await this.makeCommand(buildCommandOptions, this.getBuiltInOptions(), async (program) => {
320336
const options = program.opts();
321337

322338
if (program.args.length > 0) {
323-
const possibleCommands = [].concat([bundleCommandOptions.name]).concat(program.args);
339+
const possibleCommands = [].concat([buildCommandOptions.name]).concat(program.args);
324340

325341
logger.error('Running multiple commands at the same time is not possible');
326342
logger.error(`Found commands: ${possibleCommands.map((item) => `'${item}'`).join(', ')}`);
@@ -330,16 +346,19 @@ class WebpackCLI {
330346

331347
await this.bundleCommand(options);
332348
});
333-
} else if (commandName === helpCommandOptions.name || commandName === helpCommandOptions.alias) {
349+
} else if (isHelpCommand(commandName)) {
334350
// Stub for the `help` command
335351
this.makeCommand(helpCommandOptions, [], () => {});
336-
} else if (commandName === versionCommandOptions.name || commandName === helpCommandOptions.alias) {
352+
} else if (isVersionCommand(commandName)) {
337353
// Stub for the `help` command
338354
this.makeCommand(versionCommandOptions, [], () => {});
339355
} else {
340356
const builtInExternalCommandInfo = externalBuiltInCommandsInfo.find(
341357
(externalBuiltInCommandInfo) =>
342-
externalBuiltInCommandInfo.name === commandName || externalBuiltInCommandInfo.alias === commandName,
358+
externalBuiltInCommandInfo.name === commandName ||
359+
(typeof Array.isArray(externalBuiltInCommandInfo.alias)
360+
? externalBuiltInCommandInfo.alias.includes(commandName)
361+
: externalBuiltInCommandInfo.alias === commandName),
343362
);
344363

345364
let pkg;
@@ -420,9 +439,7 @@ class WebpackCLI {
420439
const { commandName } = getCommandNameAndOptions(this.program.args);
421440

422441
if (commandName) {
423-
const command = this.program.commands.find(
424-
(command) => command.name() === commandName || command.alias() === commandName,
425-
);
442+
const command = findCommandByName(commandName);
426443

427444
if (!command) {
428445
logger.error(`Can't find and load command '${commandName}'`);
@@ -470,13 +487,7 @@ class WebpackCLI {
470487
const outputVersion = async (options) => {
471488
// Filter `bundle`, `version` and `help` commands
472489
const possibleCommandNames = options.filter(
473-
(options) =>
474-
options !== bundleCommandOptions.name &&
475-
options !== bundleCommandOptions.alias &&
476-
options !== versionCommandOptions.name &&
477-
options !== versionCommandOptions.alias &&
478-
options !== helpCommandOptions.name &&
479-
options !== helpCommandOptions.alias,
490+
(option) => !isBuildCommand(option) && !isVersionCommand(option) && !isHelpCommand(option),
480491
);
481492

482493
possibleCommandNames.forEach((possibleCommandName) => {
@@ -495,9 +506,7 @@ class WebpackCLI {
495506
await Promise.all(possibleCommandNames.map((possibleCommand) => loadCommandByName(possibleCommand)));
496507

497508
for (const possibleCommandName of possibleCommandNames) {
498-
const foundCommand = this.program.commands.find(
499-
(command) => command.name() === possibleCommandName || command.alias() === possibleCommandName,
500-
);
509+
const foundCommand = findCommandByName(possibleCommandName);
501510

502511
if (!foundCommand) {
503512
logger.error(`Unknown command '${possibleCommandName}'`);
@@ -563,9 +572,7 @@ class WebpackCLI {
563572
}),
564573
);
565574

566-
const bundleCommand = this.program.commands.find(
567-
(command) => command.name() === bundleCommandOptions.name || command.alias() === bundleCommandOptions.alias,
568-
);
575+
const bundleCommand = findCommandByName(buildCommandOptions.name);
569576

570577
if (!isVerbose) {
571578
hideVerboseOptions(bundleCommand);
@@ -574,10 +581,10 @@ class WebpackCLI {
574581
let helpInformation = bundleCommand
575582
.helpInformation()
576583
.trimRight()
577-
.replace(bundleCommandOptions.description, 'The build tool for modern web applications.')
584+
.replace(buildCommandOptions.description, 'The build tool for modern web applications.')
578585
.replace(
579586
/Usage:.+/,
580-
'Usage: webpack [options]\nAlternative usage: webpack bundle [options]\nAlternative usage: webpack --config <config> [options]\nAlternative usage: webpack bundle --config <config> [options]',
587+
'Usage: webpack [options]\nAlternative usage: webpack --config <config> [options]\nAlternative usage: webpack build [options]\nAlternative usage: webpack bundle [options]\nAlternative usage: webpack b [options]\nAlternative usage: webpack build --config <config> [options]',
581588
);
582589

583590
logger.raw(helpInformation);
@@ -598,7 +605,7 @@ class WebpackCLI {
598605

599606
await loadCommandByName(name);
600607

601-
const command = this.program.commands.find((command) => command.name() === name || command.alias() === name);
608+
const command = findCommandByName(name);
602609

603610
if (!command) {
604611
logger.error(`Can't find and load command '${name}'`);
@@ -612,30 +619,36 @@ class WebpackCLI {
612619

613620
let helpInformation = command.helpInformation().trimRight();
614621

615-
if (name === bundleCommandOptions.name || name === bundleCommandOptions.alias) {
622+
if (isBuildCommand(name)) {
616623
helpInformation = helpInformation
617-
.replace(bundleCommandOptions.description, 'The build tool for modern web applications.')
624+
.replace(buildCommandOptions.description, 'The build tool for modern web applications.')
618625
.replace(
619626
/Usage:.+/,
620-
'Usage: webpack [options]\nAlternative usage: webpack bundle [options]\nAlternative usage: webpack --config <config> [options]\nAlternative usage: webpack bundle --config <config> [options]',
627+
'Usage: webpack [options]\nAlternative usage: webpack --config <config> [options]\nAlternative usage: webpack build [options]\nAlternative usage: webpack bundle [options]\nAlternative usage: webpack b [options]\nAlternative usage: webpack build --config <config> [options]',
621628
);
622629
}
623630

624631
logger.raw(helpInformation);
625632
}
626633

627-
const globalOptions = program.helpInformation().match(/Options:\n(?<globalOptions>.+)\nCommands:\n/s);
634+
const programHelpInformation = program.helpInformation();
635+
const globalOptions = programHelpInformation.match(/Options:\n(?<globalOptions>.+)\nCommands:\n/s);
628636

629637
if (globalOptions && globalOptions.groups.globalOptions) {
630638
logger.raw('\nGlobal options:');
631639
logger.raw(globalOptions.groups.globalOptions.trimRight());
632640
}
633641

634-
if (isGlobal) {
635-
const globalCommands = program.helpInformation().match(/Commands:\n(?<globalCommands>.+)/s);
642+
const globalCommands = programHelpInformation.match(/Commands:\n(?<globalCommands>.+)/s);
636643

644+
if (isGlobal && globalCommands.groups.globalCommands) {
637645
logger.raw('\nCommands:');
638-
logger.raw(globalCommands.groups.globalCommands.trimRight());
646+
logger.raw(
647+
globalCommands.groups.globalCommands
648+
.trimRight()
649+
// `commander` doesn't support multiple alias in help
650+
.replace('build|bundle [options] ', 'build|bundle|b [options]'),
651+
);
639652
}
640653

641654
logger.raw("\nTo see list of all supported commands and options run 'webpack --help=verbose'.\n");
@@ -665,7 +678,7 @@ class WebpackCLI {
665678

666679
const opts = program.opts();
667680

668-
if (opts.help || commandName === helpCommandOptions.name || commandName === helpCommandOptions.alias) {
681+
if (opts.help || isHelpCommand(commandName)) {
669682
let isVerbose = false;
670683

671684
if (opts.help) {
@@ -686,7 +699,7 @@ class WebpackCLI {
686699
await outputHelp(optionsForHelp, isVerbose, program);
687700
}
688701

689-
if (opts.version || commandName === versionCommandOptions.name || commandName === versionCommandOptions.alias) {
702+
if (opts.version || isVersionCommand(commandName)) {
690703
const optionsForVersion = [].concat(opts.version ? [commandName] : []).concat(options);
691704

692705
await outputVersion(optionsForVersion, program);
@@ -700,7 +713,9 @@ class WebpackCLI {
700713
const found = knownCommands.find((commandOptions) => distance(commandName, commandOptions.name) < 3);
701714

702715
if (found) {
703-
logger.error(`Did you mean '${found.name}' (alias '${found.alias}')?`);
716+
logger.error(
717+
`Did you mean '${found.name}' (alias '${Array.isArray(found.alias) ? found.alias.join(', ') : found.alias}')?`,
718+
);
704719
}
705720

706721
logger.error("Run 'webpack --help' to see available commands and options");
@@ -1313,7 +1328,7 @@ class WebpackCLI {
13131328
}
13141329
};
13151330

1316-
options.argv = { ...options, env: { WEBPACK_BUNDLE: true, ...options.env } };
1331+
options.argv = { ...options, env: { WEBPACK_BUNDLE: true, WEBPACK_BUILD: true, ...options.env } };
13171332

13181333
compiler = await this.createCompiler(options, callback);
13191334

test/bundle/basic/basic.test.js renamed to test/build/basic/basic.test.js

+12-4
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,35 @@ const { run } = require('../../utils/test-utils');
44

55
describe('bundle command', () => {
66
it('should work', async () => {
7-
const { exitCode, stderr, stdout } = run(__dirname, ['bundle'], false);
7+
const { exitCode, stderr, stdout } = run(__dirname, ['build'], false);
88

99
expect(exitCode).toBe(0);
1010
expect(stderr).toBeFalsy();
1111
expect(stdout).toBeTruthy();
1212
});
1313

14-
it('should work with alias', async () => {
14+
it('should work with the "b" alias', async () => {
1515
const { exitCode, stderr, stdout } = run(__dirname, ['b'], false);
1616

1717
expect(exitCode).toBe(0);
1818
expect(stderr).toBeFalsy();
1919
expect(stdout).toBeTruthy();
2020
});
2121

22+
it('should work with "bundle" alias', async () => {
23+
const { exitCode, stderr, stdout } = run(__dirname, ['bundle'], false);
24+
25+
expect(exitCode).toBe(0);
26+
expect(stderr).toBeFalsy();
27+
expect(stdout).toBeTruthy();
28+
});
29+
2230
it('should log error with multi commands', async () => {
2331
const { exitCode, stderr, stdout } = run(__dirname, ['bundle', 'info'], false);
2432

2533
expect(exitCode).toBe(2);
2634
expect(stderr).toContain('Running multiple commands at the same time is not possible');
27-
expect(stderr).toContain("Found commands: 'bundle', 'info'");
35+
expect(stderr).toContain("Found commands: 'build', 'info'");
2836
expect(stderr).toContain("Run 'webpack --help' to see available commands and options");
2937
expect(stdout).toBeFalsy();
3038
});
@@ -34,7 +42,7 @@ describe('bundle command', () => {
3442

3543
expect(exitCode).toBe(2);
3644
expect(stderr).toContain('Running multiple commands at the same time is not possible');
37-
expect(stderr).toContain("Found commands: 'bundle', 'i'");
45+
expect(stderr).toContain("Found commands: 'build', 'i'");
3846
expect(stderr).toContain("Run 'webpack --help' to see available commands and options");
3947
expect(stdout).toBeFalsy();
4048
});
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const isInProcess = process.env.WEBPACK_BUNDLE;
2+
3+
class CustomTestPlugin {
4+
constructor(isInEnvironment) {
5+
this.isInEnvironment = isInEnvironment;
6+
}
7+
apply(compiler) {
8+
compiler.hooks.done.tap('testPlugin', () => {
9+
if (!isInProcess && this.isInEnvironment) {
10+
console.log('PASS');
11+
} else {
12+
console.log('FAIL');
13+
}
14+
});
15+
}
16+
}
17+
18+
module.exports = (env) => {
19+
return {
20+
mode: 'development',
21+
devtool: false,
22+
plugins: [new CustomTestPlugin(env.WEBPACK_BUILD)],
23+
};
24+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
3+
const { run } = require('../../utils/test-utils');
4+
5+
describe('bundle variable', () => {
6+
it('compiles without flags and export variable', async () => {
7+
const { exitCode, stderr, stdout } = run(__dirname, [], false);
8+
9+
expect(exitCode).toBe(0);
10+
expect(stderr).toBeFalsy();
11+
expect(stdout).toContain('PASS');
12+
});
13+
});
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log('hello world');

test/config/type/function-with-argv/function-with-argv.test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ describe('function configuration', () => {
1010
expect(exitCode).toBe(0);
1111
expect(stderr).toBeFalsy();
1212
expect(stdout).toBeTruthy();
13-
expect(stdout).toContain("{ argv: { mode: 'development', env: { WEBPACK_BUNDLE: true } } }");
13+
expect(stdout).toContain('WEBPACK_BUNDLE: true');
14+
expect(stdout).toContain('WEBPACK_BUILD: true');
1415
expect(stdout).toContain("mode: 'development'");
1516
expect(existsSync(resolve(__dirname, './dist/dev.js')));
1617
});

0 commit comments

Comments
 (0)