/
startDevServer.ts
138 lines (110 loc) · 5.03 KB
/
startDevServer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { devServerOptionsType } from './types';
/**
*
* Starts the devServer
*
* @param {Object} compiler - a webpack compiler
* @param {Object} devServerCliOptions - dev server CLI options
* @param {Object} cliOptions - CLI options
* @param {Object} logger - logger
*
* @returns {Object[]} array of resulting servers
*/
export default async function startDevServer(compiler, devServerCliOptions, cliOptions, logger): Promise<object[]> {
let devServerVersion, Server, findPort;
try {
// eslint-disable-next-line node/no-extraneous-require
devServerVersion = require('webpack-dev-server/package.json').version;
// eslint-disable-next-line node/no-extraneous-require
Server = require('webpack-dev-server/lib/Server');
// eslint-disable-next-line node/no-extraneous-require
findPort = require('webpack-dev-server/lib/utils/findPort');
} catch (err) {
logger.error(`You need to install 'webpack-dev-server' for running 'webpack serve'.\n${err}`);
process.exit(2);
}
const mergeOptions = (devServerOptions: devServerOptionsType, devServerCliOptions: devServerOptionsType): devServerOptionsType => {
// CLI options should take precedence over devServer options,
// and CLI options should have no default values included
const options = { ...devServerOptions, ...devServerCliOptions };
if (devServerOptions.client && devServerCliOptions.client) {
// the user could set some client options in their devServer config,
// then also specify client options on the CLI
options.client = { ...devServerOptions.client, ...devServerCliOptions.client };
}
return options;
};
const isMultiCompiler = Boolean(compiler.compilers);
let compilersWithDevServerOption;
if (isMultiCompiler) {
compilersWithDevServerOption = compiler.compilers.filter((compiler) => compiler.options.devServer);
// No compilers found with the `devServer` option, let's use first compiler
if (compilersWithDevServerOption.length === 0) {
compilersWithDevServerOption = [compiler.compilers[0]];
}
} else {
compilersWithDevServerOption = [compiler];
}
const isDevServer4 = devServerVersion.startsWith('4');
const usedPorts = [];
const devServersOptions = [];
for (const compilerWithDevServerOption of compilersWithDevServerOption) {
const options = mergeOptions(compilerWithDevServerOption.options.devServer || {}, devServerCliOptions);
if (isDevServer4) {
options.port = await findPort(options.port);
options.client = options.client || {};
options.client.port = options.client.port || options.port;
} else {
const getPublicPathOption = () => {
const normalizePublicPath = (publicPath) => (typeof publicPath === 'undefined' || publicPath === 'auto' ? '/' : publicPath);
if (cliOptions.outputPublicPath) {
return normalizePublicPath(compilerWithDevServerOption.options.output.publicPath);
}
// webpack-dev-server@3
if (options.publicPath) {
return normalizePublicPath(options.publicPath);
}
// webpack-dev-server@4
if (options.dev && options.dev.publicPath) {
return normalizePublicPath(options.dev.publicPath);
}
return normalizePublicPath(compilerWithDevServerOption.options.output.publicPath);
};
const getStatsOption = () => {
if (cliOptions.stats) {
return compilerWithDevServerOption.options.stats;
}
if (options.stats) {
return options.stats;
}
return compilerWithDevServerOption.options.stats;
};
options.host = options.host || 'localhost';
options.port = options.port || 8080;
options.stats = getStatsOption();
options.publicPath = getPublicPathOption();
}
if (options.port) {
const portNumber = Number(options.port);
if (usedPorts.find((port) => portNumber === port)) {
throw new Error(
'Unique ports must be specified for each devServer option in your webpack configuration. Alternatively, run only 1 devServer config using the --config-name flag to specify your desired config.',
);
}
usedPorts.push(portNumber);
}
devServersOptions.push({ compiler, options });
}
const servers = [];
for (const devServerOptions of devServersOptions) {
const { compiler, options } = devServerOptions;
const server = new Server(compiler, options);
server.listen(options.port, options.host, (error): void => {
if (error) {
throw error;
}
});
servers.push(server);
}
return servers;
}