Skip to content

Commit 10790c8

Browse files
Merge pull request #1011 from Loonride/feat/serve-wip
[NEXT]: webpack-cli serve refactor draft
2 parents d80edfe + 3c92b0a commit 10790c8

File tree

15 files changed

+7046
-424
lines changed

15 files changed

+7046
-424
lines changed

lib/bootstrap.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
const webpackCli = require('./webpack-cli');
1+
const WebpackCLI = require('./webpack-cli');
22
const { core, commands } = require('./utils/cli-flags');
33
const cmdArgs = require('command-line-args');
44

55
require('./utils/process-log');
66

77
const isFlagPresent = (args, flag) => args.find(arg => [flag, `--${flag}`].includes(arg));
8-
const stripDashedFlags = (args, cmd) => args.slice(2).filter(arg => ~arg.indexOf('--') && arg !== cmd.name && arg !== cmd.alias);
8+
const isArgCommandName = (arg, cmd) => arg === cmd.name || arg === cmd.alias;
9+
const stripDashedFlags = (args, cmd) => args.filter(arg => !arg.includes('--') && !isArgCommandName(arg, cmd));
10+
const normalizeFlags = (args, cmd) => {
11+
const slicedArgs = args.slice(2);
12+
if (cmd.name === 'serve') {
13+
return slicedArgs.filter(arg => !isArgCommandName(arg, cmd));
14+
}
15+
return stripDashedFlags(slicedArgs, cmd);
16+
};
917

1018
const isCommandUsed = commands =>
1119
commands.find(cmd => {
@@ -27,7 +35,7 @@ async function runCLI(cli, commandIsUsed) {
2735

2836
if (commandIsUsed) {
2937
commandIsUsed.defaultOption = true;
30-
args = stripDashedFlags(process.argv, commandIsUsed);
38+
args = normalizeFlags(process.argv, commandIsUsed);
3139
return await cli.runCommand(commandIsUsed, ...args);
3240
} else {
3341
try {
@@ -41,8 +49,7 @@ async function runCLI(cli, commandIsUsed) {
4149
if (err.name === 'UNKNOWN_VALUE') {
4250
process.cliLogger.error(`Parse Error (unknown argument): ${err.value}`);
4351
return;
44-
}
45-
else if (err.name === 'ALREADY_SET') {
52+
} else if (err.name === 'ALREADY_SET') {
4653
const argsMap = {};
4754
const keysToDelete = [];
4855
process.argv.forEach((arg, idx) => {
@@ -75,9 +82,6 @@ async function runCLI(cli, commandIsUsed) {
7582
}
7683
}
7784

78-
// eslint-disable-next-line space-before-function-paren
79-
(async () => {
80-
const commandIsUsed = isCommandUsed(commands);
81-
const cli = new webpackCli();
82-
runCLI(cli, commandIsUsed);
83-
})();
85+
const commandIsUsed = isCommandUsed(commands);
86+
const cli = new WebpackCLI();
87+
runCLI(cli, commandIsUsed);

lib/commands/external.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,6 @@ class ExternalCommand {
6060
if (!pkgLoc) {
6161
pkgLoc = await ExternalCommand.promptInstallation(scopeName, name);
6262
}
63-
// Serve needs to be checked for
64-
if (name === 'serve') {
65-
return pkgLoc ? require(pkgLoc).serve(args) : null;
66-
}
6763
return pkgLoc ? require(pkgLoc).default(args) : null;
6864
}
6965
}

lib/utils/cli-flags.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ module.exports = {
3939
type: String,
4040
description: 'Outputs information about your system and dependencies',
4141
},
42+
{
43+
name: 'serve',
44+
scope: 'external',
45+
type: String,
46+
description: 'Run the webpack Dev Server',
47+
},
4248
],
4349
core: [
4450
{

lib/utils/compiler.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,11 @@ function compilerCallback(compiler, err, stats, lastHash, options, outputOptions
112112
}
113113
}
114114

115-
module.exports = async function webpackInstance(opts, shouldUseMem) {
115+
function getCompiler(opts) {
116+
return webpack(opts.options);
117+
}
118+
119+
async function webpackInstance(opts, shouldUseMem) {
116120
const { outputOptions, processingErrors, options } = opts;
117121
if (outputOptions.color) {
118122
require('supports-color').stdout;
@@ -122,7 +126,8 @@ module.exports = async function webpackInstance(opts, shouldUseMem) {
122126
if (processingErrors.length > 0) {
123127
throw new Error(processingErrors);
124128
}
125-
const compiler = await webpack(options);
129+
130+
const compiler = await getCompiler(opts);
126131
let lastHash = null;
127132

128133
const ProgressPlugin = webpack.ProgressPlugin;
@@ -197,3 +202,6 @@ module.exports = async function webpackInstance(opts, shouldUseMem) {
197202
return await invokeCompilerInstance(compiler, lastHash, options, outputOptions);
198203
}
199204
};
205+
206+
module.exports.getCompiler = getCompiler;
207+
module.exports.webpackInstance = webpackInstance;

lib/utils/dev-server-flags.js

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
const CONFIG_GROUP = 'Config options:';
2+
const ADVANCED_GROUP = 'Advanced options:';
3+
const DISPLAY_GROUP = 'Stats options:';
4+
const SSL_GROUP = 'SSL options:';
5+
const CONNECTION_GROUP = 'Connection options:';
6+
const RESPONSE_GROUP = 'Response options:';
7+
const BASIC_GROUP = 'Basic options:';
8+
9+
module.exports = {
10+
devServer: [
11+
{
12+
name: 'bonjour',
13+
type: Boolean,
14+
describe: 'Broadcasts the server via ZeroConf networking on start',
15+
},
16+
{
17+
name: 'lazy',
18+
type: Boolean,
19+
describe: 'Lazy',
20+
},
21+
{
22+
name: 'liveReload',
23+
type: Boolean,
24+
defaultValue: true,
25+
describe: 'Enables/Disables live reloading on changing files',
26+
},
27+
{
28+
name: 'serveIndex',
29+
type: Boolean,
30+
describe: 'Enables/Disables serveIndex middleware',
31+
defaultValue: true,
32+
},
33+
{
34+
name: 'inline',
35+
type: Boolean,
36+
defaultValue: true,
37+
describe:
38+
'Inline mode (set to false to disable including client scripts like livereload)',
39+
},
40+
{
41+
name: 'profile',
42+
type: Boolean,
43+
describe: 'Print compilation profile data for progress steps',
44+
},
45+
{
46+
name: 'progress',
47+
type: Boolean,
48+
describe: 'Print compilation progress in percentage',
49+
group: BASIC_GROUP,
50+
},
51+
{
52+
name: 'hot-only',
53+
type: Boolean,
54+
describe: 'Do not refresh page if HMR fails',
55+
group: ADVANCED_GROUP,
56+
},
57+
{
58+
name: 'stdin',
59+
type: Boolean,
60+
describe: 'close when stdin ends',
61+
},
62+
{
63+
name: 'open',
64+
type: String,
65+
describe: 'Open the default browser, or optionally specify a browser name',
66+
},
67+
{
68+
name: 'useLocalIp',
69+
type: Boolean,
70+
describe: 'Open default browser with local IP',
71+
},
72+
{
73+
name: 'open-page',
74+
type: String,
75+
describe: 'Open default browser with the specified page',
76+
},
77+
{
78+
name: 'client-log-level',
79+
type: String,
80+
group: DISPLAY_GROUP,
81+
defaultValue: 'info',
82+
describe:
83+
'Log level in the browser (trace, debug, info, warn, error or silent)',
84+
},
85+
{
86+
name: 'https',
87+
type: Boolean,
88+
group: SSL_GROUP,
89+
describe: 'HTTPS',
90+
},
91+
{
92+
name: 'http2',
93+
type: Boolean,
94+
group: SSL_GROUP,
95+
describe: 'HTTP/2, must be used with HTTPS',
96+
},
97+
{
98+
name: 'key',
99+
type: String,
100+
describe: 'Path to a SSL key.',
101+
group: SSL_GROUP,
102+
},
103+
{
104+
name: 'cert',
105+
type: String,
106+
describe: 'Path to a SSL certificate.',
107+
group: SSL_GROUP,
108+
},
109+
{
110+
name: 'cacert',
111+
type: String,
112+
describe: 'Path to a SSL CA certificate.',
113+
group: SSL_GROUP,
114+
},
115+
{
116+
name: 'pfx',
117+
type: String,
118+
describe: 'Path to a SSL pfx file.',
119+
group: SSL_GROUP,
120+
},
121+
{
122+
name: 'pfx-passphrase',
123+
type: String,
124+
describe: 'Passphrase for pfx file.',
125+
group: SSL_GROUP,
126+
},
127+
{
128+
name: 'content-base',
129+
type: String,
130+
describe: 'A directory or URL to serve HTML content from.',
131+
group: RESPONSE_GROUP,
132+
},
133+
{
134+
name: 'watch-content-base',
135+
type: Boolean,
136+
describe: 'Enable live-reloading of the content-base.',
137+
group: RESPONSE_GROUP,
138+
},
139+
{
140+
name: 'history-api-fallback',
141+
type: Boolean,
142+
describe: 'Fallback to /index.html for Single Page Applications.',
143+
group: RESPONSE_GROUP,
144+
},
145+
{
146+
name: 'compress',
147+
type: Boolean,
148+
describe: 'Enable gzip compression',
149+
group: RESPONSE_GROUP,
150+
},
151+
// findPort is currently not set up
152+
{
153+
name: 'port',
154+
type: Number,
155+
describe: 'The port',
156+
group: CONNECTION_GROUP,
157+
},
158+
{
159+
name: 'disable-host-check',
160+
type: Boolean,
161+
describe: 'Will not check the host',
162+
group: CONNECTION_GROUP,
163+
},
164+
{
165+
name: 'socket',
166+
type: String,
167+
describe: 'Socket to listen',
168+
group: CONNECTION_GROUP,
169+
},
170+
{
171+
name: 'public',
172+
type: String,
173+
describe: 'The public hostname/ip address of the server',
174+
group: CONNECTION_GROUP,
175+
},
176+
{
177+
name: 'host',
178+
type: String,
179+
describe: 'The hostname/ip address the server will bind to',
180+
group: CONNECTION_GROUP,
181+
},
182+
// use command-line-args "multiple" option, allowing the usage: --allowed-hosts host1 host2 host3
183+
// instead of the old, comma-separated syntax: --allowed-hosts host1,host2,host3
184+
{
185+
name: 'allowed-hosts',
186+
type: String,
187+
describe:
188+
'A list of hosts that are allowed to access the dev server, separated by spaces',
189+
group: CONNECTION_GROUP,
190+
multiple: true,
191+
},
192+
],
193+
};

lib/webpack-cli.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const Compiler = require('./utils/compiler');
55

66
const webpackMerge = require('webpack-merge');
77

8-
class webpackCLI extends GroupHelper {
8+
class WebpackCLI extends GroupHelper {
99
constructor() {
1010
super();
1111
this.groupMap = new Map();
@@ -104,12 +104,22 @@ class webpackCLI extends GroupHelper {
104104
return wrappedConfig;
105105
}
106106

107-
async run(args, yargsOptions) {
107+
async processArgs(args, yargsOptions) {
108108
await this.setMappedGroups(args, yargsOptions);
109109
await this.resolveGroups();
110110
let groupResult = await this.runOptionGroups();
111111
groupResult = this.checkDefaults(groupResult);
112-
const webpack = await Compiler(groupResult, this.shouldUseMem);
112+
return groupResult;
113+
}
114+
115+
async getCompiler(args, yargsOptions) {
116+
const groupResult = await this.processArgs(args, yargsOptions);
117+
return await Compiler.getCompiler(groupResult);
118+
}
119+
120+
async run(args, yargsOptions) {
121+
const groupResult = await this.processArgs(args, yargsOptions);
122+
const webpack = await Compiler.webpackInstance(groupResult, this.shouldUseMem);
113123
return webpack;
114124
}
115125

@@ -122,7 +132,7 @@ class webpackCLI extends GroupHelper {
122132
} else if (command.name === 'plugin') {
123133
command.name = 'generate-plugin';
124134
}
125-
return require('./commands/external').run(command.name, ...args);
135+
return await require('./commands/external').run(command.name, ...args);
126136
}
127137

128138
runHelp() {
@@ -137,4 +147,4 @@ class webpackCLI extends GroupHelper {
137147

138148
}
139149

140-
module.exports = webpackCLI;
150+
module.exports = WebpackCLI;

packages/generators/types/json-loader.d.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

packages/serve/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
*.js.map
12
*.js

packages/serve/args-to-camel-case.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
*
3+
* Converts dash-seperated strings to camel case
4+
*
5+
* @param {String} str - the string to convert
6+
*
7+
* @returns {String} - new camel case string
8+
*/
9+
function dashesToCamelCase(str): string {
10+
return str.replace(/-([a-z])/g, (g): string => g[1].toUpperCase());
11+
}
12+
13+
/**
14+
*
15+
* Converts CLI args to camel case from dash-separated words
16+
*
17+
* @param {Object} args - argument object parsed by command-line-args
18+
*
19+
* @returns {Object} - the same args object as passed in, with new keys
20+
*/
21+
export default function argsToCamelCase(args): object {
22+
Object.keys(args).forEach((key): void => {
23+
const newKey = dashesToCamelCase(key);
24+
if (key !== newKey) {
25+
const arg = args[key];
26+
delete args[key];
27+
args[newKey] = arg;
28+
}
29+
});
30+
return args;
31+
}

0 commit comments

Comments
 (0)