webpack-dev-server 3.11.3 → 4.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +596 -0
  2. package/README.md +87 -12
  3. package/bin/cli-flags.js +338 -112
  4. package/bin/webpack-dev-server.js +135 -144
  5. package/client/clients/BaseClient.js +2 -4
  6. package/client/clients/SockJSClient.js +13 -13
  7. package/client/clients/WebsocketClient.js +10 -13
  8. package/client/index.js +106 -58
  9. package/client/modules/logger/SyncBailHookFake.js +10 -0
  10. package/client/modules/logger/index.js +3463 -0
  11. package/client/modules/sockjs-client/index.js +6633 -0
  12. package/client/modules/strip-ansi/index.js +87 -0
  13. package/client/overlay.js +5 -4
  14. package/client/socket.js +5 -10
  15. package/client/utils/createSocketURL.js +81 -0
  16. package/client/utils/getCurrentScriptSource.js +7 -4
  17. package/client/utils/log.js +9 -38
  18. package/client/utils/parseURL.js +43 -0
  19. package/client/utils/reloadApp.js +2 -3
  20. package/client/utils/sendMessage.js +1 -1
  21. package/client/webpack.config.js +57 -0
  22. package/lib/Server.js +425 -403
  23. package/lib/options.json +370 -334
  24. package/lib/servers/SockJSServer.js +14 -8
  25. package/lib/servers/WebsocketServer.js +5 -4
  26. package/lib/utils/DevServerPlugin.js +218 -0
  27. package/lib/utils/createDomain.js +13 -11
  28. package/lib/utils/findPort.js +3 -10
  29. package/lib/utils/getCertificate.js +7 -2
  30. package/lib/utils/getColorsOption.js +15 -0
  31. package/lib/utils/getCompilerConfigArray.js +8 -0
  32. package/lib/utils/getSocketClientPath.d.ts +3 -0
  33. package/lib/utils/getSocketClientPath.js +1 -0
  34. package/lib/utils/getSocketServerImplementation.js +1 -1
  35. package/lib/utils/getStatsOption.js +16 -0
  36. package/lib/utils/normalizeOptions.js +96 -15
  37. package/lib/utils/routes.js +34 -62
  38. package/lib/utils/runBonjour.js +4 -3
  39. package/lib/utils/runOpen.js +67 -21
  40. package/lib/utils/setupExitSignals.js +15 -11
  41. package/package.json +65 -70
  42. package/bin/options.js +0 -187
  43. package/client/index.bundle.js +0 -1
  44. package/client/live.bundle.js +0 -25
  45. package/client/live.html +0 -1
  46. package/client/sockjs.bundle.js +0 -1
  47. package/client/utils/createSocketUrl.js +0 -88
  48. package/lib/utils/addEntries.js +0 -160
  49. package/lib/utils/createConfig.js +0 -233
  50. package/lib/utils/createLogger.js +0 -23
  51. package/lib/utils/defaultPort.js +0 -3
  52. package/lib/utils/defaultTo.js +0 -7
  53. package/lib/utils/getVersions.js +0 -10
  54. package/lib/utils/processOptions.js +0 -44
  55. package/lib/utils/status.js +0 -61
  56. package/lib/utils/tryParseInt.js +0 -13
  57. package/lib/utils/updateCompiler.js +0 -73
  58. package/ssl/.gitkeep +0 -0
@@ -1,8 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  /* eslint-disable
4
- class-methods-use-this,
5
- func-names
4
+ class-methods-use-this
6
5
  */
7
6
  const sockjs = require('sockjs');
8
7
  const BaseServer = require('./BaseServer');
@@ -13,9 +12,13 @@ const BaseServer = require('./BaseServer');
13
12
  {
14
13
  const SockjsSession = require('sockjs/lib/transport').Session;
15
14
  const decorateConnection = SockjsSession.prototype.decorateConnection;
16
- SockjsSession.prototype.decorateConnection = function(req) {
15
+
16
+ // eslint-disable-next-line func-names
17
+ SockjsSession.prototype.decorateConnection = function (req) {
17
18
  decorateConnection.call(this, req);
19
+
18
20
  const connection = this.connection;
21
+
19
22
  if (
20
23
  connection.headers &&
21
24
  !('origin' in connection.headers) &&
@@ -30,21 +33,24 @@ module.exports = class SockJSServer extends BaseServer {
30
33
  // options has: error (function), debug (function), server (http/s server), path (string)
31
34
  constructor(server) {
32
35
  super(server);
36
+
33
37
  this.socket = sockjs.createServer({
34
38
  // Use provided up-to-date sockjs-client
35
39
  sockjs_url: '/__webpack_dev_server__/sockjs.bundle.js',
36
- // Limit useless logs
40
+ // Default logger is very annoy. Limit useless logs.
37
41
  log: (severity, line) => {
38
42
  if (severity === 'error') {
39
- this.server.log.error(line);
43
+ this.server.logger.error(line);
44
+ } else if (severity === 'info') {
45
+ this.server.logger.log(line);
40
46
  } else {
41
- this.server.log.debug(line);
47
+ this.server.logger.debug(line);
42
48
  }
43
49
  },
44
50
  });
45
51
 
46
- this.socket.installHandlers(this.server.listeningApp, {
47
- prefix: this.server.sockPath,
52
+ this.socket.installHandlers(this.server.server, {
53
+ prefix: this.server.options.client.path,
48
54
  });
49
55
  }
50
56
 
@@ -9,12 +9,13 @@ const BaseServer = require('./BaseServer');
9
9
  module.exports = class WebsocketServer extends BaseServer {
10
10
  constructor(server) {
11
11
  super(server);
12
+
12
13
  this.wsServer = new ws.Server({
13
14
  noServer: true,
14
- path: this.server.sockPath,
15
+ path: this.server.options.client.path,
15
16
  });
16
17
 
17
- this.server.listeningApp.on('upgrade', (req, sock, head) => {
18
+ this.server.server.on('upgrade', (req, sock, head) => {
18
19
  if (!this.wsServer.shouldHandle(req)) {
19
20
  return;
20
21
  }
@@ -25,7 +26,7 @@ module.exports = class WebsocketServer extends BaseServer {
25
26
  });
26
27
 
27
28
  this.wsServer.on('error', (err) => {
28
- this.server.log.error(err.message);
29
+ this.server.logger.error(err.message);
29
30
  });
30
31
 
31
32
  const noop = () => {};
@@ -39,7 +40,7 @@ module.exports = class WebsocketServer extends BaseServer {
39
40
  socket.isAlive = false;
40
41
  socket.ping(noop);
41
42
  });
42
- }, this.server.heartbeatInterval);
43
+ }, this.server.wsHeartbeatInterval);
43
44
  }
44
45
 
45
46
  send(connection, message) {
@@ -0,0 +1,218 @@
1
+ 'use strict';
2
+
3
+ const webpack = require('webpack');
4
+ const createDomain = require('./createDomain');
5
+ const getSocketClientPath = require('./getSocketClientPath');
6
+
7
+ // @ts-ignore
8
+ const EntryPlugin = webpack.EntryPlugin;
9
+
10
+ class DevServerPlugin {
11
+ /**
12
+ * @param {?Object} options - Dev-Server options
13
+ */
14
+ constructor(options) {
15
+ this.options = options;
16
+ }
17
+
18
+ /**
19
+ * An Entry, it can be of type string or string[] or Object<string | string[],string>
20
+ * @typedef {(string[] | string | Object<string | string[],string>)} Entry
21
+ */
22
+
23
+ /**
24
+ * Apply the plugin
25
+ * @param {Object} compiler the compiler instance
26
+ * @returns {void}
27
+ */
28
+ apply(compiler) {
29
+ const { options } = this;
30
+
31
+ /** @type {string} */
32
+ const domain = createDomain(options);
33
+ /** @type {string} */
34
+ const host =
35
+ options.client && options.client.host
36
+ ? `&host=${options.client.host}`
37
+ : '';
38
+ /** @type {string} */
39
+ let path = '';
40
+
41
+ // only add the path if it is not default
42
+ if (
43
+ options.client &&
44
+ options.client.path &&
45
+ options.client.path !== '/ws'
46
+ ) {
47
+ path = `&path=${options.client.path}`;
48
+ }
49
+
50
+ /** @type {string} */
51
+ const port =
52
+ (options.client && options.client.port) || options.port
53
+ ? `&port=${options.client.port || options.port}`
54
+ : '';
55
+
56
+ /** @type {string} */
57
+ const logging =
58
+ options.client && options.client.logging
59
+ ? `&logging=${options.client.logging}`
60
+ : '';
61
+
62
+ /** @type {string} */
63
+ const clientEntry = `${require.resolve(
64
+ '../../client/'
65
+ )}?${domain}${host}${path}${port}${logging}`;
66
+
67
+ /** @type {(string[] | string)} */
68
+ let hotEntry;
69
+
70
+ if (options.hot === 'only') {
71
+ hotEntry = require.resolve('webpack/hot/only-dev-server');
72
+ } else if (options.hot) {
73
+ hotEntry = require.resolve('webpack/hot/dev-server');
74
+ }
75
+ /**
76
+ * prependEntry Method for webpack 4
77
+ * @param {Entry} originalEntry
78
+ * @param {Entry} additionalEntries
79
+ * @returns {Entry}
80
+ */
81
+ const prependEntry = (originalEntry, additionalEntries) => {
82
+ if (typeof originalEntry === 'function') {
83
+ return () =>
84
+ Promise.resolve(originalEntry()).then((entry) =>
85
+ prependEntry(entry, additionalEntries)
86
+ );
87
+ }
88
+
89
+ if (typeof originalEntry === 'object' && !Array.isArray(originalEntry)) {
90
+ /** @type {Object<string,string>} */
91
+ const clone = {};
92
+
93
+ Object.keys(originalEntry).forEach((key) => {
94
+ // entry[key] should be a string here
95
+ const entryDescription = originalEntry[key];
96
+ clone[key] = prependEntry(entryDescription, additionalEntries);
97
+ });
98
+
99
+ return clone;
100
+ }
101
+
102
+ // in this case, entry is a string or an array.
103
+ // make sure that we do not add duplicates.
104
+ /** @type {Entry} */
105
+ const entriesClone = additionalEntries.slice(0);
106
+ [].concat(originalEntry).forEach((newEntry) => {
107
+ if (!entriesClone.includes(newEntry)) {
108
+ entriesClone.push(newEntry);
109
+ }
110
+ });
111
+ return entriesClone;
112
+ };
113
+
114
+ /**
115
+ *
116
+ * Description of the option for checkInject method
117
+ * @typedef {Function} checkInjectOptionsParam
118
+ * @param {Object} _config - compilerConfig
119
+ * @return {Boolean}
120
+ */
121
+
122
+ /**
123
+ *
124
+ * @param {Boolean | checkInjectOptionsParam} option - inject(Hot|Client) it is Boolean | fn => Boolean
125
+ * @param {Object} _config
126
+ * @param {Boolean} defaultValue
127
+ * @return {Boolean}
128
+ */
129
+ // eslint-disable-next-line no-shadow
130
+ const checkInject = (option, _config, defaultValue) => {
131
+ if (typeof option === 'boolean') {
132
+ return option;
133
+ }
134
+
135
+ if (typeof option === 'function') {
136
+ return option(_config);
137
+ }
138
+
139
+ return defaultValue;
140
+ };
141
+
142
+ const compilerOptions = compiler.options;
143
+
144
+ compilerOptions.plugins = compilerOptions.plugins || [];
145
+
146
+ /** @type {boolean} */
147
+ const isWebTarget = compilerOptions.externalsPresets
148
+ ? compilerOptions.externalsPresets.web
149
+ : [
150
+ 'web',
151
+ 'webworker',
152
+ 'electron-renderer',
153
+ 'node-webkit',
154
+ // eslint-disable-next-line no-undefined
155
+ undefined,
156
+ null,
157
+ ].includes(compilerOptions.target);
158
+
159
+ /** @type {Entry} */
160
+ const additionalEntries = checkInject(
161
+ options.client ? options.client.needClientEntry : null,
162
+ compilerOptions,
163
+ isWebTarget
164
+ )
165
+ ? [clientEntry]
166
+ : [];
167
+
168
+ if (
169
+ hotEntry &&
170
+ checkInject(
171
+ options.client ? options.client.needHotEntry : null,
172
+ compilerOptions,
173
+ true
174
+ )
175
+ ) {
176
+ additionalEntries.push(hotEntry);
177
+ }
178
+
179
+ // use a hook to add entries if available
180
+ if (EntryPlugin) {
181
+ for (const additionalEntry of additionalEntries) {
182
+ new EntryPlugin(compiler.context, additionalEntry, {
183
+ // eslint-disable-next-line no-undefined
184
+ name: undefined,
185
+ }).apply(compiler);
186
+ }
187
+ } else {
188
+ compilerOptions.entry = prependEntry(
189
+ compilerOptions.entry || './src',
190
+ additionalEntries
191
+ );
192
+ compiler.hooks.entryOption.call(
193
+ compilerOptions.context,
194
+ compilerOptions.entry
195
+ );
196
+ }
197
+
198
+ const providePlugin = new webpack.ProvidePlugin({
199
+ __webpack_dev_server_client__: getSocketClientPath(options),
200
+ });
201
+
202
+ providePlugin.apply(compiler);
203
+
204
+ if (
205
+ hotEntry &&
206
+ !compilerOptions.plugins.find(
207
+ (p) => p.constructor === webpack.HotModuleReplacementPlugin
208
+ )
209
+ ) {
210
+ // apply the HMR plugin, if it didn't exist before.
211
+ const plugin = new webpack.HotModuleReplacementPlugin();
212
+
213
+ plugin.apply(compiler);
214
+ }
215
+ }
216
+ }
217
+
218
+ module.exports = DevServerPlugin;
@@ -1,16 +1,21 @@
1
1
  'use strict';
2
2
 
3
3
  const url = require('url');
4
- const ip = require('internal-ip');
5
4
 
6
5
  function createDomain(options, server) {
7
6
  const protocol = options.https ? 'https' : 'http';
8
- const hostname = options.useLocalIp
9
- ? ip.v4.sync() || 'localhost'
10
- : options.host || 'localhost';
7
+ // use location hostname and port by default in createSocketURL
8
+ // ipv6 detection is not required as 0.0.0.0 is just used as a placeholder
9
+ let hostname;
10
+
11
+ if (server) {
12
+ hostname = server.address().address;
13
+ } else {
14
+ hostname = '0.0.0.0';
15
+ }
16
+
17
+ const port = server ? server.address().port : 0;
11
18
 
12
- // eslint-disable-next-line no-nested-ternary
13
- const port = options.socket ? 0 : server ? server.address().port : 0;
14
19
  // use explicitly defined public url
15
20
  // (prefix with protocol if not explicitly given)
16
21
  if (options.public) {
@@ -18,12 +23,9 @@ function createDomain(options, server) {
18
23
  ? `${options.public}`
19
24
  : `${protocol}://${options.public}`;
20
25
  }
26
+
21
27
  // the formatted domain (url without path) of the webpack server
22
- return url.format({
23
- protocol,
24
- hostname,
25
- port,
26
- });
28
+ return url.format({ protocol, hostname, port });
27
29
  }
28
30
 
29
31
  module.exports = createDomain;
@@ -2,13 +2,11 @@
2
2
 
3
3
  const pRetry = require('p-retry');
4
4
  const portfinder = require('portfinder');
5
- const defaultPort = require('./defaultPort');
6
- const defaultTo = require('./defaultTo');
7
- const tryParseInt = require('./tryParseInt');
8
5
 
9
6
  function runPortFinder() {
10
7
  return new Promise((resolve, reject) => {
11
- portfinder.basePort = defaultPort;
8
+ // default port
9
+ portfinder.basePort = 8080;
12
10
  portfinder.getPort((error, port) => {
13
11
  if (error) {
14
12
  return reject(error);
@@ -26,12 +24,7 @@ function findPort(port) {
26
24
 
27
25
  // Try to find unused port and listen on it for 3 times,
28
26
  // if port is not specified in options.
29
- // Because NaN == null is false, defaultTo fails if parseInt returns NaN
30
- // so the tryParseInt function is introduced to handle NaN
31
- const defaultPortRetry = defaultTo(
32
- tryParseInt(process.env.DEFAULT_PORT_RETRY),
33
- 3
34
- );
27
+ const defaultPortRetry = parseInt(process.env.DEFAULT_PORT_RETRY, 10) || 3;
35
28
 
36
29
  return pRetry(runPortFinder, { retries: defaultPortRetry });
37
30
  }
@@ -1,14 +1,18 @@
1
1
  'use strict';
2
2
 
3
3
  const path = require('path');
4
- const fs = require('fs');
4
+ const os = require('os');
5
+ const fs = require('graceful-fs');
5
6
  const del = require('del');
7
+ const findCacheDir = require('find-cache-dir');
6
8
  const createCertificate = require('./createCertificate');
7
9
 
8
10
  function getCertificate(logger) {
9
11
  // Use a self-signed certificate if no certificate was configured.
10
12
  // Cycle certs every 24 hours
11
- const certificatePath = path.join(__dirname, '../../ssl/server.pem');
13
+ const certificateDir =
14
+ findCacheDir({ name: 'webpack-dev-server' }) || os.tmpdir();
15
+ const certificatePath = path.join(certificateDir, 'server.pem');
12
16
 
13
17
  let certificateExists = fs.existsSync(certificatePath);
14
18
 
@@ -34,6 +38,7 @@ function getCertificate(logger) {
34
38
  const attributes = [{ name: 'commonName', value: 'localhost' }];
35
39
  const pems = createCertificate(attributes);
36
40
 
41
+ fs.mkdirSync(certificateDir, { recursive: true });
37
42
  fs.writeFileSync(certificatePath, pems.private + pems.cert, {
38
43
  encoding: 'utf8',
39
44
  });
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ const getStatsOption = require('./getStatsOption');
4
+
5
+ function getColorsOption(configArr) {
6
+ const statsOption = getStatsOption(configArr);
7
+ let colors = false;
8
+ if (typeof statsOption === 'object' && statsOption.colors) {
9
+ colors = statsOption.colors;
10
+ }
11
+
12
+ return colors;
13
+ }
14
+
15
+ module.exports = getColorsOption;
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ function getCompilerConfigArray(compiler) {
4
+ const compilers = compiler.compilers ? compiler.compilers : [compiler];
5
+ return compilers.map((comp) => comp.options);
6
+ }
7
+
8
+ module.exports = getCompilerConfigArray;
@@ -0,0 +1,3 @@
1
+ declare function getSocketClientPath(options: Object): string;
2
+
3
+ export = getSocketClientPath;
@@ -3,6 +3,7 @@
3
3
  function getSocketClientPath(options) {
4
4
  let ClientImplementation;
5
5
  let clientImplFound = true;
6
+
6
7
  switch (typeof options.transportMode.client) {
7
8
  case 'string':
8
9
  // could be 'sockjs', 'ws', or a path that should be required
@@ -30,7 +30,7 @@ function getSocketServerImplementation(options) {
30
30
 
31
31
  if (!serverImplFound) {
32
32
  throw new Error(
33
- "transportMode.server must be a string denoting a default implementation (e.g. 'sockjs', 'ws'), a full path to " +
33
+ "transportMode.server must be a string denoting a default implementation (e.g. 'ws', 'sockjs'), a full path to " +
34
34
  'a JS file which exports a class extending BaseServer (webpack-dev-server/lib/servers/BaseServer) ' +
35
35
  'via require.resolve(...), or the class itself which extends BaseServer'
36
36
  );
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ function getStatsOption(configArr) {
4
+ const isEmptyObject = (val) =>
5
+ typeof val === 'object' && Object.keys(val).length === 0;
6
+
7
+ // in webpack@4 stats will not be defined if not provided,
8
+ // but in webpack@5 it will be an empty object
9
+ const statsConfig = configArr.find(
10
+ (conf) =>
11
+ typeof conf === 'object' && conf.stats && !isEmptyObject(conf.stats)
12
+ );
13
+ return statsConfig ? statsConfig.stats : {};
14
+ }
15
+
16
+ module.exports = getStatsOption;
@@ -1,22 +1,83 @@
1
1
  'use strict';
2
2
 
3
- /* eslint-disable
4
- no-undefined
5
- */
3
+ const path = require('path');
4
+ const isAbsoluteUrl = require('is-absolute-url');
5
+ const getCompilerConfigArray = require('./getCompilerConfigArray');
6
6
 
7
7
  function normalizeOptions(compiler, options) {
8
- // Setup default value
9
- options.contentBase =
10
- options.contentBase !== undefined ? options.contentBase : process.cwd();
8
+ // TODO: improve this to not use .find for compiler watchOptions
9
+ const configArr = getCompilerConfigArray(compiler);
10
+ const watchOptionsConfig = configArr.find(
11
+ (config) => config.watch !== false && config.watchOptions
12
+ );
13
+ const watchOptions = watchOptionsConfig
14
+ ? watchOptionsConfig.watchOptions
15
+ : {};
11
16
 
12
- // Setup default value
13
- options.contentBasePublicPath = options.contentBasePublicPath || '/';
17
+ const defaultOptionsForStatic = {
18
+ directory: path.join(process.cwd(), 'public'),
19
+ staticOptions: {},
20
+ publicPath: ['/'],
21
+ serveIndex: { icons: true },
22
+ // Respect options from compiler watchOptions
23
+ watch: watchOptions,
24
+ };
25
+
26
+ if (typeof options.static === 'undefined') {
27
+ options.static = [defaultOptionsForStatic];
28
+ } else if (typeof options.static === 'boolean') {
29
+ options.static = options.static ? [defaultOptionsForStatic] : false;
30
+ } else if (typeof options.static === 'string') {
31
+ options.static = [
32
+ { ...defaultOptionsForStatic, directory: options.static },
33
+ ];
34
+ } else if (Array.isArray(options.static)) {
35
+ options.static = options.static.map((item) => {
36
+ if (typeof item === 'string') {
37
+ return { ...defaultOptionsForStatic, directory: item };
38
+ }
39
+
40
+ return { ...defaultOptionsForStatic, ...item };
41
+ });
42
+ } else {
43
+ options.static = [{ ...defaultOptionsForStatic, ...options.static }];
44
+ }
45
+
46
+ if (options.static) {
47
+ options.static.forEach((staticOption) => {
48
+ if (isAbsoluteUrl(staticOption.directory)) {
49
+ throw new Error('Using a URL as static.directory is not supported');
50
+ }
51
+
52
+ // ensure that publicPath is an array
53
+ if (typeof staticOption.publicPath === 'string') {
54
+ staticOption.publicPath = [staticOption.publicPath];
55
+ }
56
+
57
+ // ensure that watch is an object if true
58
+ if (staticOption.watch === true) {
59
+ staticOption.watch = defaultOptionsForStatic.watch;
60
+ }
61
+
62
+ // ensure that serveIndex is an object if true
63
+ if (staticOption.serveIndex === true) {
64
+ staticOption.serveIndex = defaultOptionsForStatic.serveIndex;
65
+ }
66
+ });
67
+ }
68
+
69
+ options.hot =
70
+ typeof options.hot === 'boolean' || options.hot === 'only'
71
+ ? options.hot
72
+ : true;
73
+ options.liveReload =
74
+ typeof options.liveReload !== 'undefined' ? options.liveReload : true;
14
75
 
15
76
  // normalize transportMode option
16
- if (options.transportMode === undefined) {
77
+ if (typeof options.transportMode === 'undefined') {
17
78
  options.transportMode = {
18
- server: 'sockjs',
19
- client: 'sockjs',
79
+ server: 'ws',
80
+ client: 'ws',
20
81
  };
21
82
  } else {
22
83
  switch (typeof options.transportMode) {
@@ -28,13 +89,33 @@ function normalizeOptions(compiler, options) {
28
89
  break;
29
90
  // if not a string, it is an object
30
91
  default:
31
- options.transportMode.server = options.transportMode.server || 'sockjs';
32
- options.transportMode.client = options.transportMode.client || 'sockjs';
92
+ options.transportMode.server = options.transportMode.server || 'ws';
93
+ options.transportMode.client = options.transportMode.client || 'ws';
33
94
  }
34
95
  }
35
96
 
36
- if (!options.watchOptions) {
37
- options.watchOptions = {};
97
+ if (!options.client) {
98
+ options.client = {};
99
+ }
100
+
101
+ // Enable client overlay by default
102
+ if (typeof options.client.overlay === 'undefined') {
103
+ options.client.overlay = true;
104
+ }
105
+
106
+ options.client.path = `/${
107
+ options.client.path ? options.client.path.replace(/^\/|\/$/g, '') : 'ws'
108
+ }`;
109
+
110
+ options.devMiddleware = options.devMiddleware || {};
111
+
112
+ if (typeof options.firewall === 'undefined') {
113
+ // firewall is enabled by default
114
+ options.firewall = true;
115
+ }
116
+
117
+ if (typeof options.setupExitSignals === 'undefined') {
118
+ options.setupExitSignals = true;
38
119
  }
39
120
  }
40
121