Skip to content

Commit

Permalink
feat(webpack-cli): allow multiple entry files (#1619)
Browse files Browse the repository at this point in the history
  • Loading branch information
snitin315 authored Jun 17, 2020
1 parent 1a4947b commit ac2e52c
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 21 deletions.
2 changes: 1 addition & 1 deletion packages/webpack-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Available Commands
Options
--entry string The entry point of your application.
--entry string[] The entry point(s) of your application.
-c, --config string Provide path to a webpack configuration file
-m, --merge string Merge a configuration file using webpack-merge
--progress Print compilation progress during build
Expand Down
19 changes: 18 additions & 1 deletion packages/webpack-cli/__tests__/arg-parser.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ const basicOptions = [
},
description: 'custom type flag',
},
{
name: 'multi-flag',
usage: '--multi-flag <value>',
type: String,
multiple: true,
description: 'multi flag',
},
];

const helpAndVersionOptions = basicOptions.slice(0);
Expand Down Expand Up @@ -163,6 +170,16 @@ describe('arg-parser', () => {
expect(warnMock.mock.calls.length).toEqual(0);
});

it('handles multiple same args', () => {
const res = argParser(basicOptions, ['--multi-flag', 'a.js', '--multi-flag', 'b.js'], true);
expect(res.unknownArgs.length).toEqual(0);
expect(res.opts).toEqual({
multiFlag: ['a.js', 'b.js'],
stringFlagWithDefault: 'default-value',
});
expect(warnMock.mock.calls.length).toEqual(0);
});

it('handles additional node args from argv', () => {
const res = argParser(basicOptions, ['node', 'index.js', '--bool-flag', '--string-flag', 'val'], false);
expect(res.unknownArgs.length).toEqual(0);
Expand Down Expand Up @@ -210,7 +227,7 @@ describe('arg-parser', () => {
it('parses webpack args', () => {
const res = argParser(core, ['--entry', 'test.js', '--hot', '-o', './dist/'], true);
expect(res.unknownArgs.length).toEqual(0);
expect(res.opts.entry).toEqual('test.js');
expect(res.opts.entry).toEqual(['test.js']);
expect(res.opts.hot).toBeTruthy();
expect(res.opts.output).toEqual('./dist/');
expect(warnMock.mock.calls.length).toEqual(0);
Expand Down
21 changes: 14 additions & 7 deletions packages/webpack-cli/lib/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,21 @@ async function runCLI(cli, commandIsUsed) {
// if the unknown arg starts with a '-', it will be considered
// an unknown flag rather than an entry
let entry;
if (parsedArgs.unknownArgs.length === 1 && !parsedArgs.unknownArgs[0].startsWith('-')) {
entry = parsedArgs.unknownArgs[0];
} else if (parsedArgs.unknownArgs.length > 0) {
parsedArgs.unknownArgs
.filter((e) => e)
.forEach((unknown) => {
logger.warn('Unknown argument:', unknown);
if (parsedArgs.unknownArgs.length > 0 && !parsedArgs.unknownArgs[0].startsWith('-')) {
if (parsedArgs.unknownArgs.length === 1) {
entry = parsedArgs.unknownArgs[0];
} else {
entry = [];
parsedArgs.unknownArgs.forEach((unknown) => {
if (!unknown.startsWith('-')) {
entry.push(unknown);
}
});
}
} else if (parsedArgs.unknownArgs.length > 0) {
parsedArgs.unknownArgs.forEach((unknown) => {
logger.warn('Unknown argument:', unknown);
});
cliExecuter();
return;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/webpack-cli/lib/groups/BasicGroup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const GroupHelper = require('../utils/GroupHelper');
const chalk = require('chalk');
const { core, groups } = require('../utils/cli-flags');

class BasicGroup extends GroupHelper {
Expand Down Expand Up @@ -35,6 +36,9 @@ class BasicGroup extends GroupHelper {
}
if (arg === 'entry') {
options[arg] = this.resolveFilePath(args[arg], 'index.js');
if (options[arg].length === 0) {
process.stdout.write(chalk.red('\nError: you provided an invalid entry point.\n'));
}
}
});
if (outputOptions['dev']) {
Expand Down
7 changes: 6 additions & 1 deletion packages/webpack-cli/lib/utils/arg-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ function argParser(options, args, argsOnly = false, name = '', helpFunction = un
const flags = option.alias ? `-${option.alias}, --${option.name}` : `--${option.name}`;
const flagsWithType = option.type !== Boolean ? flags + ' <value>' : flags;
if (option.type === Boolean || option.type === String) {
parserInstance.option(flagsWithType, option.description, option.defaultValue);
if (!option.multiple) {
parserInstance.option(flagsWithType, option.description, option.defaultValue);
} else {
const multiArg = (value, previous = []) => previous.concat([value]);
parserInstance.option(flagsWithType, option.description, multiArg, option.defaultValue);
}
} else {
// in this case the type is a parsing function
parserInstance.option(flagsWithType, option.description, option.type, option.defaultValue);
Expand Down
5 changes: 3 additions & 2 deletions packages/webpack-cli/lib/utils/cli-flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ module.exports = {
core: [
{
name: 'entry',
usage: '--entry <path to entry file>',
usage: '--entry <path to entry file> | --entry <path> --entry <path>',
type: String,
multiple: true,
defaultOption: true,
group: BASIC_GROUP,
description: 'The entry point of your application e.g. ./src/main.js',
description: 'The entry point(s) of your application e.g. ./src/main.js',
link: 'https://webpack.js.org/concepts/#entry',
},
{
Expand Down
4 changes: 2 additions & 2 deletions test/entry/flag-entry/entry-with-flag.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('entry flag', () => {

it('should throw error for invalid entry file', () => {
const { stderr, stdout } = run(__dirname, ['--entry', './src/test.js']);
expect(stderr).toBeFalsy();
expect(stdout).toContain('not found');
expect(stderr).toBeTruthy();
expect(stdout).toContain('Error: you provided an invalid entry point.');
});
});
43 changes: 43 additions & 0 deletions test/entry/multiple-entries/multi-entries.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

const { run } = require('../../utils/test-utils');
const { stat, readFile } = require('fs');
const { resolve } = require('path');

describe(' multiple entries', () => {
it('should allow multiple entry files', (done) => {
const { stderr, stdout } = run(__dirname, ['./src/a.js', './src/b.js']);
expect(stderr).toBeFalsy();
expect(stdout).toBeTruthy();

stat(resolve(__dirname, './bin/main.js'), (err, stats) => {
expect(err).toBe(null);
expect(stats.isFile()).toBe(true);
done();
});
readFile(resolve(__dirname, './bin/main.js'), 'utf-8', (err, data) => {
expect(err).toBe(null);
expect(data).toContain('Hello from a.js');
expect(data).toContain('Hello from b.js');
done();
});
});

it('should allow multiple entry flags', (done) => {
const { stderr, stdout } = run(__dirname, ['--entry', 'src/a.js', '--entry', 'src/b.js']);
expect(stderr).toBeFalsy();
expect(stdout).toBeTruthy();

stat(resolve(__dirname, './bin/main.js'), (err, stats) => {
expect(err).toBe(null);
expect(stats.isFile()).toBe(true);
done();
});
readFile(resolve(__dirname, './bin/main.js'), 'utf-8', (err, data) => {
expect(err).toBe(null);
expect(data).toContain('Hello from a.js');
expect(data).toContain('Hello from b.js');
done();
});
});
});
1 change: 1 addition & 0 deletions test/entry/multiple-entries/src/a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('Hello from a.js');
1 change: 1 addition & 0 deletions test/entry/multiple-entries/src/b.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('Hello from b.js');
1 change: 1 addition & 0 deletions test/entry/multiple-entries/src/c.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('Hello from c.js');
1 change: 0 additions & 1 deletion test/init/auto/init-auto.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const { run } = require('../../utils/test-utils');
const firstPrompt = 'Will your application have multiple bundles?';
const genPath = join(__dirname, 'test-assets');

jest.setTimeout(60000);
describe('init auto flag', () => {
beforeAll(() => {
rimraf.sync(genPath);
Expand Down
2 changes: 0 additions & 2 deletions test/init/force/init-force.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ const firstPrompt = 'Will your application have multiple bundles?';
const ENTER = '\x0D';
const genPath = join(__dirname, 'test-assets');

jest.setTimeout(100000);

describe('init force flag', () => {
beforeAll(() => {
rimraf.sync(genPath);
Expand Down
2 changes: 0 additions & 2 deletions test/init/generator/init-inquirer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ const firstPrompt = 'Will your application have multiple bundles?';
const ENTER = '\x0D';
const genPath = join(__dirname, 'test-assets');

jest.setTimeout(100000);

describe('init', () => {
beforeAll(() => {
rimraf.sync(genPath);
Expand Down
2 changes: 0 additions & 2 deletions test/init/multipleEntries/init-multipleEntries.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ const firstPrompt = 'Will your application have multiple bundles?';
const ENTER = '\x0D';
const genPath = path.join(__dirname, 'test-assets');

jest.setTimeout(100000);

describe('init with multiple entries', () => {
beforeAll(() => {
rimraf.sync(genPath);
Expand Down

0 comments on commit ac2e52c

Please sign in to comment.