Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(webpack-cli): import flags from webpack core #1630

Merged
merged 21 commits into from
Jul 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
const { cli } = require('webpack');

//ignore core-flags test for webpack@4
const ignorePattern = typeof cli !== 'undefined' ? ['<rootDir>/node_modules/'] : ['<rootDir>/node_modules/', '<rootDir>/test/core-flags'];

module.exports = {
testPathIgnorePatterns: ['<rootDir>/node_modules/'],
testPathIgnorePatterns: ignorePattern,
// transformIgnorePatterns: ['<rootDir>.*(node_modules)(?!.*webpack-cli.*).*$'],
testEnvironment: 'node',
collectCoverage: true,
Expand Down
614 changes: 610 additions & 4 deletions packages/webpack-cli/README.md

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion packages/webpack-cli/lib/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ const logger = require('./utils/logger');
const cliExecuter = require('./utils/cli-executer');
const argParser = require('./utils/arg-parser');
require('./utils/process-log');

process.title = 'webpack-cli';

const isCommandUsed = (commands) =>
Expand Down
1 change: 0 additions & 1 deletion packages/webpack-cli/lib/utils/arg-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ function argParser(options, args, argsOnly = false, name = '', helpFunction = un
const opts = result.opts();

const unknownArgs = result.args;

args.forEach((arg) => {
const flagName = arg.slice(5);
const option = options.find((opt) => opt.name === flagName);
Expand Down
33 changes: 33 additions & 0 deletions packages/webpack-cli/lib/utils/cli-flags.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const { cli } = require('webpack');

const HELP_GROUP = 'help';
const CONFIG_GROUP = 'config';
const BASIC_GROUP = 'basic';
Expand All @@ -6,6 +8,35 @@ const ADVANCED_GROUP = 'advanced';
const DISPLAY_GROUP = 'stats';
const ZERO_CONFIG_GROUP = 'zero-config';

// Extract all the flags being exported from core. A list of cli flags generated by core
// can be found here https://github.com/webpack/webpack/blob/master/test/__snapshots__/Cli.test.js.snap
let flagsFromCore =
typeof cli !== 'undefined'
? Object.entries(cli.getArguments()).map(([flag, meta]) => {
if (meta.simpleType === 'string') {
meta.type = String;
meta.usage = `--${flag} <value>`;
} else if (meta.simpleType === 'number') {
meta.type = Number;
meta.usage = `--${flag} <value>`;
} else {
meta.type = Boolean;
meta.negative = true;
meta.usage = `--${flag}`;
}
return {
...meta,
name: flag,
group: 'core',
};
})
: [];

// duplicate flags
const duplicateFlags = ['entry', 'mode', 'stats', 'watch', 'target'];

flagsFromCore = flagsFromCore.filter((flag) => !duplicateFlags.includes(flag.name));

module.exports = {
groups: {
HELP_GROUP,
Expand Down Expand Up @@ -227,6 +258,7 @@ module.exports = {
group: CONFIG_GROUP,
description: 'Environment passed to the configuration when it is a function',
},
...flagsFromCore,
/* {
name: "analyze",
type: Boolean,
Expand All @@ -241,4 +273,5 @@ module.exports = {
group: BASIC_GROUP
} */
],
flagsFromCore,
};
22 changes: 22 additions & 0 deletions packages/webpack-cli/lib/webpack-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class WebpackCLI extends GroupHelper {
super();
this.groupMap = new Map();
this.groups = [];
this.args = {};
this.processingMessageBuffer = [];
this.compilation = new Compiler();
this.defaultEntry = 'index';
Expand Down Expand Up @@ -42,6 +43,26 @@ class WebpackCLI extends GroupHelper {
}
}

/**
* Responsible for handling flags coming from webpack/webpack
* @private\
* @returns {void}
*/
_handleCoreFlags() {
if (!this.groupMap.has('core')) {
return;
}
const coreFlags = this.groupMap.get('core');

// convert all the flags from map to single object
const coreConfig = coreFlags.reduce((allFlag, curFlag) => ({ ...allFlag, ...curFlag }), {});

const coreCliHelper = require('webpack').cli;
const coreCliArgs = coreCliHelper.getArguments();
// Merge the core flag config with the compilerConfiguration
coreCliHelper.processArguments(coreCliArgs, this.compilerConfiguration, coreConfig);
}

/**
* Expose commander argParser
* @param {...any} args args for argParser
Expand Down Expand Up @@ -222,6 +243,7 @@ class WebpackCLI extends GroupHelper {
.then(() => this._handleDefaultEntry())
.then(() => this._handleGroupHelper(this.configGroup))
.then(() => this._handleGroupHelper(this.outputGroup))
.then(() => this._handleCoreFlags())
.then(() => this._handleGroupHelper(this.basicGroup))
.then(() => this._handleGroupHelper(this.advancedGroup))
.then(() => this._handleGroupHelper(this.statsGroup))
Expand Down
2 changes: 1 addition & 1 deletion scripts/cleanupTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const rimraf = require('rimraf');
const { join } = require('path');
const collectTestFolders = require('./utils');

const outputDirectories = ['bin', 'binary', 'dist', 'test-assets', 'test-plugin', 'test-loader'];
const outputDirectories = ['bin', 'binary', 'dist', 'test', 'test-assets', 'test-plugin', 'test-loader'];

function folderStrategy(stats, file) {
return stats.isDirectory() && outputDirectories.includes(file);
Expand Down
12 changes: 12 additions & 0 deletions test/core-flags/amd-flag.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

const { run } = require('../utils/test-utils');

describe('--no-amd flag', () => {
it('should accept --no-amd', () => {
const { stderr, stdout } = run(__dirname, ['--no-amd']);

expect(stderr).toBeFalsy();
expect(stdout).toContain('amd: false');
});
});
19 changes: 19 additions & 0 deletions test/core-flags/bail-flag.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const { run } = require('../utils/test-utils');

describe('--bail flag', () => {
it('should set bail to true', () => {
const { stderr, stdout } = run(__dirname, ['--bail']);

expect(stderr).toBeFalsy();
expect(stdout).toContain('bail: true');
});

it('should set bail to false', () => {
const { stderr, stdout } = run(__dirname, ['--no-bail']);

expect(stderr).toBeFalsy();
expect(stdout).toContain('bail: false');
});
});
82 changes: 82 additions & 0 deletions test/core-flags/cache-flags.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict';

const { run } = require('../utils/test-utils');

describe('cache related flags from core', () => {
it('should be successful with --cache ', () => {
const { stderr, stdout } = run(__dirname, ['--cache']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`type: 'memory'`);
});

it('should be successful with --no-cache ', () => {
const { stderr, stdout } = run(__dirname, ['--no-cache']);

expect(stderr).toBeFalsy();
expect(stdout).toContain('cache: false');
});

it('should set cache.type', () => {
const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`type: 'filesystem'`);
});

it('should set cache.cacheDirectory with --cache-cache-directory', () => {
const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-cache-directory', '/test-cache-path']);

expect(stderr).toBeFalsy();
expect(stdout).toContain('test-cache-path');
});

it('should set cache.cacheLocation with --cache-cache-locations', () => {
const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-cache-location', '/test-locate-cache']);

expect(stderr).toBeFalsy();
expect(stdout).toContain('test-locate-cache');
});

it('should set cache.hashAlgorithm with --cache-hash-algorithm', () => {
const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-hash-algorithm', 'sha256']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`hashAlgorithm: 'sha256'`);
});

it('should set cache.managedPaths with --cache-managed-paths', () => {
const { stderr, stdout } = run(__dirname, ['--cache-type', 'memory', '--cache-managed-paths', '/test-manage-path']);

expect(stderr).toBeFalsy();
expect(stdout).toContain('test-manage-path');
});

it('should reset cache.managedPaths with --cache-managed-paths-reset', () => {
const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-managed-paths-reset']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`managedPaths: []`);
});

it('should set cache.name with --cache-name', () => {
const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-name', 'cli-test']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`name: 'cli-test'`);
});

it('should set cache.store with --cache-store', () => {
const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-store', 'pack']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`store: 'pack'`);
});

it('should set cache.version with --cache-version', () => {
const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-version', '1.1.3']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`version: '1.1.3'`);
});
});
12 changes: 12 additions & 0 deletions test/core-flags/context-flag.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

const { run } = require('../utils/test-utils');

describe('--context flag', () => {
it('should allow to set context', () => {
const { stderr, stdout } = run(__dirname, ['--context', '/test-context-path']);

expect(stderr).toBeFalsy();
expect(stdout).toContain('test-context-path');
});
});
19 changes: 19 additions & 0 deletions test/core-flags/dependencies-flag.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const { run } = require('../utils/test-utils');

describe('--dependencies and related flags', () => {
it('should allow to set dependencies option', () => {
const { stderr, stdout } = run(__dirname, ['--dependencies', 'lodash']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`dependencies: [ 'lodash' ]`);
});

it('should reset dependencies option', () => {
const { stderr, stdout } = run(__dirname, ['--dependencies-reset']);

expect(stderr).toBeFalsy();
expect(stdout).toContain('dependencies: []');
});
});
18 changes: 18 additions & 0 deletions test/core-flags/devtool-flag.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict';

const { run } = require('../utils/test-utils');

describe('--devtool flag', () => {
it('should set devtool option', () => {
const { stderr, stdout } = run(__dirname, ['--devtool', 'source-map']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`devtool: 'source-map'`);
});

it('should throw error for invalid config', () => {
const { stderr } = run(__dirname, ['--devtool', 'invalid']);

expect(stderr).toContain('ValidationError: Invalid configuration object');
});
});
26 changes: 26 additions & 0 deletions test/core-flags/experiments-flag.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

const { run, hyphenToUpperCase } = require('../utils/test-utils');
const { flagsFromCore } = require('../../packages/webpack-cli/lib/utils/cli-flags');

const experimentsFlags = flagsFromCore.filter(({ name }) => name.startsWith('experiments-'));

describe('experiments option related flag', () => {
experimentsFlags.forEach((flag) => {
// extract property name from flag name
const property = flag.name.split('experiments-')[1];
const propName = hyphenToUpperCase(property);

it(`should config ${flag.name} correctly`, () => {
const { stderr, stdout } = run(__dirname, [`--${flag.name}`]);
expect(stderr).toBeFalsy();
expect(stdout).toContain(`${propName}: true`);
});

it(`should config --no-${flag.name} correctly`, () => {
const { stderr, stdout } = run(__dirname, [`--no-${flag.name}`]);
expect(stderr).toBeFalsy();
expect(stdout).toContain(`${propName}: false`);
});
});
});
33 changes: 33 additions & 0 deletions test/core-flags/externals-flags.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

const { run } = require('../utils/test-utils');

describe('externals related flag', () => {
it('should set externals properly', () => {
const { stderr, stdout } = run(__dirname, ['--externals', './main.js']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`externals: [ './main.js' ]`);
});

it('should set externalsType properly', () => {
const { stderr, stdout } = run(__dirname, ['--externals', 'var']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`externalsType: 'var'`);
});

it('should accept --external-type values', () => {
const { stderr, stdout } = run(__dirname, ['--externals-type', 'var']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`externalsType: 'var'`);
});

it('should reset externals', () => {
const { stderr, stdout } = run(__dirname, ['--externals-reset']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`externals: []`);
});
});
26 changes: 26 additions & 0 deletions test/core-flags/infrastructure-logging.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

const { run } = require('../utils/test-utils');

describe('externals related flag', () => {
it('should set infrastructureLogging.debug properly', () => {
const { stderr, stdout } = run(__dirname, ['--infrastructure-logging-debug', 'myPlugin']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`debug: [ 'myPlugin' ]`);
});

it('should reset infrastructureLogging.debug to []', () => {
const { stderr, stdout } = run(__dirname, ['--infrastructure-logging-debug-reset']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`debug: []`);
});

it('should set infrastructureLogging.level properly', () => {
const { stderr, stdout } = run(__dirname, ['--infrastructure-logging-level', 'log']);

expect(stderr).toBeFalsy();
expect(stdout).toContain(`level: 'log'`);
});
});
1 change: 1 addition & 0 deletions test/core-flags/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('core-flags tests');