Skip to content

Commit bb7c9d3

Browse files
feat: new CLI options API for serve (#2754)
1 parent 557ad05 commit bb7c9d3

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed

packages/serve/src/index.ts

+81-3
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,34 @@ import startDevServer from "./startDevServer";
33
class ServeCommand {
44
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
55
async apply(cli: any): Promise<void> {
6-
const { logger } = cli;
6+
const { logger, webpack } = cli;
77

88
const loadDevServerOptions = () => {
9+
// TODO simplify this after drop webpack v4 and webpack-dev-server v3
910
// eslint-disable-next-line @typescript-eslint/no-var-requires, node/no-extraneous-require
10-
const options = require("webpack-dev-server/bin/cli-flags");
11+
const devServer = require("webpack-dev-server");
12+
const isNewDevServerCLIAPI = typeof devServer.schema !== "undefined";
13+
14+
let options = {};
15+
16+
if (isNewDevServerCLIAPI) {
17+
if (typeof webpack.cli.getArguments === "function") {
18+
options = webpack.cli.getArguments(devServer.schema);
19+
} else {
20+
options = devServer.cli.getArguments();
21+
}
22+
} else {
23+
// eslint-disable-next-line node/no-extraneous-require
24+
options = require("webpack-dev-server/bin/cli-flags");
25+
}
1126

1227
// Old options format
1328
// { devServer: [{...}, {}...] }
29+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
30+
// @ts-ignore
1431
if (options.devServer) {
32+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
33+
// @ts-ignore
1534
return options.devServer;
1635
}
1736

@@ -64,7 +83,7 @@ class ServeCommand {
6483
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6584
const webpackOptions: Record<string, any> = {};
6685
// eslint-disable-next-line @typescript-eslint/no-explicit-any
67-
const devServerOptions: Record<string, any> = {};
86+
let devServerOptions: Record<string, any> = {};
6887

6988
// eslint-disable-next-line @typescript-eslint/no-explicit-any
7089
const processors: Array<(opts: Record<string, any>) => void> = [];
@@ -139,6 +158,65 @@ class ServeCommand {
139158
process.stdin.resume();
140159
}
141160

161+
// eslint-disable-next-line @typescript-eslint/no-var-requires, node/no-extraneous-require
162+
const devServer = require("webpack-dev-server");
163+
const isNewDevServerCLIAPI = typeof devServer.schema !== "undefined";
164+
165+
if (isNewDevServerCLIAPI) {
166+
const args = devServerFlags.reduce((accumulator, flag) => {
167+
accumulator[flag.name] = flag;
168+
return accumulator;
169+
}, {});
170+
const values = Object.keys(devServerOptions).reduce((accumulator, name) => {
171+
const kebabName = cli.utils.toKebabCase(name);
172+
if (args[kebabName]) {
173+
accumulator[kebabName] = options[name];
174+
}
175+
return accumulator;
176+
}, {});
177+
const result = Object.assign({}, compiler.options.devServer);
178+
const problems = (
179+
typeof webpack.cli.processArguments === "function"
180+
? webpack.cli
181+
: devServer.cli
182+
).processArguments(args, result, values);
183+
184+
if (problems) {
185+
const groupBy = (xs, key) => {
186+
return xs.reduce((rv, x) => {
187+
(rv[x[key]] = rv[x[key]] || []).push(x);
188+
189+
return rv;
190+
}, {});
191+
};
192+
193+
const problemsByPath = groupBy(problems, "path");
194+
195+
for (const path in problemsByPath) {
196+
const problems = problemsByPath[path];
197+
problems.forEach((problem) => {
198+
cli.logger.error(
199+
`${cli.utils.capitalizeFirstLetter(
200+
problem.type.replace(/-/g, " "),
201+
)}${problem.value ? ` '${problem.value}'` : ""} for the '--${
202+
problem.argument
203+
}' option${
204+
problem.index ? ` by index '${problem.index}'` : ""
205+
}`,
206+
);
207+
208+
if (problem.expected) {
209+
cli.logger.error(`Expected: '${problem.expected}'`);
210+
}
211+
});
212+
}
213+
214+
process.exit(2);
215+
}
216+
217+
devServerOptions = result;
218+
}
219+
142220
try {
143221
servers = await startDevServer(compiler, devServerOptions, options, logger);
144222
} catch (error) {

test/serve/serve-variable/webpack.config.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
const isInProcess = process.env.WEBPACK_SERVE;
1+
const HAS_WEBPACK_SERVE = process.env.WEBPACK_SERVE || process.env.WEBPACK_DEV_SERVER;
22

33
class CustomTestPlugin {
44
constructor(isInEnvironment) {
55
this.isInEnvironment = isInEnvironment;
66
}
77
apply(compiler) {
88
compiler.hooks.done.tap("testPlugin", () => {
9-
if (!isInProcess && this.isInEnvironment) {
9+
if (this.isInEnvironment) {
1010
console.log("PASS");
1111
} else {
1212
console.log("FAIL");
@@ -19,6 +19,6 @@ module.exports = (env) => {
1919
return {
2020
mode: "development",
2121
devtool: false,
22-
plugins: [new CustomTestPlugin(env.WEBPACK_SERVE)],
22+
plugins: [new CustomTestPlugin(HAS_WEBPACK_SERVE && env.WEBPACK_SERVE)],
2323
};
2424
};

0 commit comments

Comments
 (0)