webpack-dev-server 4.1.1 → 4.3.1

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.
package/README.md CHANGED
@@ -73,76 +73,78 @@ Options:
73
73
  --node-env <value> Sets process.env.NODE_ENV to the specified value.
74
74
  --progress [value] Print compilation progress during build.
75
75
  -j, --json [value] Prints result as JSON or store it in a file.
76
+ --entry <value...> The entry point(s) of your application e.g. ./src/main.js.
77
+ -o, --output-path <value> Output location of the file generated by webpack e.g. ./dist/.
78
+ -t, --target <value> Sets the build target e.g. node.
76
79
  -d, --devtool <value> Determine source maps to use.
77
80
  --no-devtool Do not generate source maps.
78
- --entry <value...> The entry point(s) of your application e.g. ./src/main.js.
79
81
  --mode <value> Defines the mode to pass to webpack.
80
82
  --name <value> Name of the configuration. Used when loading multiple configurations.
81
- -o, --output-path <value> Output location of the file generated by webpack e.g. ./dist/.
82
83
  --stats [value] It instructs webpack on how to treat the stats e.g. verbose.
83
84
  --no-stats Disable stats output.
84
- -t, --target <value...> Sets the build target e.g. node.
85
- --no-target Negative 'target' option.
86
85
  --watch-options-stdin Stop watching when stdin stream has ended.
87
86
  --no-watch-options-stdin Do not stop watching when stdin stream has ended.
88
- --allowed-hosts <value...> Allows to enumerate the hosts from which access to the dev server are allowed (useful when you are proxying
89
- dev server, by default is 'auto').
90
- --allowed-hosts-reset Clear all items provided in 'allowedHosts' configuration. Allows to enumerate the hosts from which access to
91
- the dev server are allowed (useful when you are proxying dev server, by default is 'auto').
87
+ --allowed-hosts <value...> Allows to enumerate the hosts from which access to the dev server are allowed (useful when you are proxying dev server, by default is 'auto').
88
+ --allowed-hosts-reset Clear all items provided in 'allowedHosts' configuration. Allows to enumerate the hosts from which access to the dev server are allowed (useful when you are proxying dev server, by default is 'auto').
92
89
  --bonjour Allows to broadcasts dev server via ZeroConf networking on start.
93
- --no-bonjour Negative 'bonjour' option.
90
+ --no-bonjour Disallows to broadcasts dev server via ZeroConf networking on start.
91
+ --client-web-socket-transport <value> Allows to set custom web socket transport to communicate with dev server.
94
92
  --no-client Negative 'client' option.
95
93
  --client-logging <value> Allows to specify options for client script in the browser or disable client script.
94
+ --client-progress Prints compilation progress in percentage in the browser.
95
+ --no-client-progress Does not print compilation progress in percentage in the browser.
96
96
  --client-overlay Enables a full-screen overlay in the browser when there are compiler errors or warnings.
97
- --no-client-overlay Negative 'client-overlay' option.
97
+ --no-client-overlay Disables a full-screen overlay in the browser when there are compiler errors or warnings.
98
98
  --client-overlay-errors Enables a full-screen overlay in the browser when there are compiler errors.
99
99
  --no-client-overlay-errors Negative 'client-overlay-errors' option.
100
100
  --client-overlay-warnings Enables a full-screen overlay in the browser when there are compiler warnings.
101
101
  --no-client-overlay-warnings Negative 'client-overlay-warnings' option.
102
- --client-progress Prints compilation progress in percentage in the browser.
103
- --no-client-progress Negative 'client-progress' option.
104
- --client-web-socket-transport <value> Allows to set custom web socket transport to communicate with dev server.
105
- --client-web-socket-url <value> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does
106
- not always know where to connect to).
102
+ --client-web-socket-url <value> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to).
107
103
  --client-web-socket-url-hostname <value> Tells clients connected to devServer to use the provided hostname.
108
- --client-web-socket-url-pathname <value> Tells clients connected to devServer to use the provided path to connect.
109
- --client-web-socket-url-password <value> Tells clients connected to devServer to use the provided password to authenticate.
110
104
  --client-web-socket-url-port <value> Tells clients connected to devServer to use the provided port.
105
+ --client-web-socket-url-pathname <value> Tells clients connected to devServer to use the provided path to connect.
111
106
  --client-web-socket-url-protocol <value> Tells clients connected to devServer to use the provided protocol.
112
107
  --client-web-socket-url-username <value> Tells clients connected to devServer to use the provided username to authenticate.
108
+ --client-web-socket-url-password <value> Tells clients connected to devServer to use the provided password to authenticate.
109
+ --web-socket-server <value> Allows to set web socket server and options (by default 'ws').
110
+ --no-web-socket-server Negative 'web-socket-server' option.
113
111
  --compress Enables gzip compression for everything served.
114
- --no-compress Negative 'compress' option.
115
- --history-api-fallback Allows to proxy requests through a specified index page (by default 'index.html'), useful for Single Page
116
- Applications that utilise the HTML5 History API.
112
+ --no-compress Disables gzip compression for everything served.
113
+ --history-api-fallback Allows to proxy requests through a specified index page (by default 'index.html'), useful for Single Page Applications that utilise the HTML5 History API.
117
114
  --no-history-api-fallback Negative 'history-api-fallback' option.
118
115
  --host <value> Allows to specify a hostname to use.
119
116
  --hot [value] Enables Hot Module Replacement.
120
- --no-hot Negative 'hot' option.
117
+ --no-hot Disables Hot Module Replacement.
121
118
  --http2 Allows to serve over HTTP/2 using SPDY.
122
- --no-http2 Negative 'http2' option.
119
+ --no-http2 Does not serve over HTTP/2 using SPDY.
123
120
  --https Allows to configure the server's listening socket for TLS (by default, dev server will be served over HTTP).
124
- --no-https Negative 'https' option.
121
+ --no-https Disallows to configure the server's listening socket for TLS (by default, dev server will be served over HTTP).
125
122
  --https-passphrase <value> Passphrase for a pfx file.
126
123
  --https-request-cert Request for an SSL certificate.
127
- --no-https-request-cert Negative 'https-request-cert' option.
128
- --https-cacert <value> Path to an SSL CA certificate.
129
- --https-key <value> Path to an SSL key.
130
- --https-pfx <value> Path to an SSL pfx file.
131
- --https-cert <value> Path to an SSL certificate.
124
+ --no-https-request-cert Does not request for an SSL certificate.
125
+ --https-ca <value...> Path to an SSL CA certificate or content of an SSL CA certificate.
126
+ --https-ca-reset Clear all items provided in 'https.ca' configuration. Path to an SSL CA certificate or content of an SSL CA certificate.
127
+ --https-cacert <value...> Path to an SSL CA certificate or content of an SSL CA certificate.
128
+ --https-cacert-reset Clear all items provided in 'https.cacert' configuration. Path to an SSL CA certificate or content of an SSL CA certificate.
129
+ --https-key <value...> Path to an SSL key or content of an SSL key.
130
+ --https-key-reset Clear all items provided in 'https.key' configuration. Path to an SSL key or content of an SSL key.
131
+ --https-pfx <value...> Path to an SSL pfx file or content of an SSL pfx file.
132
+ --https-pfx-reset Clear all items provided in 'https.pfx' configuration. Path to an SSL pfx file or content of an SSL pfx file.
133
+ --https-cert <value...> Path to an SSL certificate or content of an SSL certificate.
134
+ --https-cert-reset Clear all items provided in 'https.cert' configuration. Path to an SSL certificate or content of an SSL certificate.
135
+ --https-crl <value...> Path to PEM formatted CRLs (Certificate Revocation Lists) or content of PEM formatted CRLs (Certificate Revocation Lists).
136
+ --https-crl-reset Clear all items provided in 'https.crl' configuration. Path to PEM formatted CRLs (Certificate Revocation Lists) or content of PEM formatted CRLs (Certificate Revocation Lists).
132
137
  --ipc [value] Listen to a unix socket.
133
138
  --live-reload Enables reload/refresh the page(s) when file changes are detected (enabled by default).
134
- --no-live-reload Negative 'live-reload' option.
135
- --magic-html Tells dev-server whether to enable magic HTML routes (routes corresponding to your webpack output, for
136
- example '/main' for 'main.js').
137
- --no-magic-html Negative 'magic-html' option.
138
- --open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to
139
- true to open your default browser).
140
- --no-open Negative 'open' option.
139
+ --no-live-reload Disables reload/refresh the page(s) when file changes are detected (enabled by default)
140
+ --magic-html Tells dev-server whether to enable magic HTML routes (routes corresponding to your webpack output, for example '/main' for 'main.js').
141
+ --no-magic-html Disables magic HTML routes (routes corresponding to your webpack output, for example '/main' for 'main.js').
142
+ --open [value...] Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to true to open your default browser).
143
+ --no-open Does not open the default browser.
141
144
  --open-target <value...> Opens specified page in browser.
142
145
  --open-app-name <value...> Open specified browser.
143
146
  --open-app <value...> Open specified browser.
144
- --open-reset Clear all items provided in 'open' configuration. Allows to configure dev server to open the browser(s) and
145
- page(s) after server had been started (set it to true to open your default browser).
147
+ --open-reset Clear all items provided in 'open' configuration. Allows to configure dev server to open the browser(s) and page(s) after server had been started (set it to true to open your default browser).
146
148
  --open-target-reset Clear all items provided in 'open.target' configuration. Opens specified page in browser.
147
149
  --open-app-name-reset Clear all items provided in 'open.app.name' configuration. Open specified browser.
148
150
  --port <value> Allows to specify a port to use.
@@ -151,18 +153,13 @@ Options:
151
153
  --static-directory <value...> Directory for static contents.
152
154
  --static-public-path <value...> The static files will be available in the browser under this public path.
153
155
  --static-serve-index Tells dev server to use serveIndex middleware when enabled.
154
- --no-static-serve-index Negative 'static-serve-index' option.
156
+ --no-static-serve-index Does not tell dev server to use serveIndex middleware.
155
157
  --static-watch Watches for files in static content directory.
156
- --no-static-watch Negative 'static-watch' option.
157
- --static-reset Clear all items provided in 'static' configuration. Allows to configure options for serving static files
158
- from directory (by default 'public' directory).
159
- --static-public-path-reset Clear all items provided in 'static.publicPath' configuration. The static files will be available in the
160
- browser under this public path.
158
+ --no-static-watch Does not watch for files in static content directory.
159
+ --static-reset Clear all items provided in 'static' configuration. Allows to configure options for serving static files from directory (by default 'public' directory).
160
+ --static-public-path-reset Clear all items provided in 'static.publicPath' configuration. The static files will be available in the browser under this public path.
161
161
  --watch-files <value...> Allows to configure list of globs/directories/files to watch for file changes.
162
- --watch-files-reset Clear all items provided in 'watchFiles' configuration. Allows to configure list of globs/directories/files
163
- to watch for file changes.
164
- --web-socket-server <value> Allows to set web socket server and options (by default 'ws').
165
- --no-web-socket-server Negative 'web-socket-server' option.
162
+ --watch-files-reset Clear all items provided in 'watchFiles' configuration. Allows to configure list of globs/directories/files to watch for file changes.
166
163
 
167
164
  Global options:
168
165
  --color Enable colors on console.
package/bin/cli-flags.js CHANGED
@@ -445,57 +445,180 @@ module.exports = {
445
445
  simpleType: "boolean",
446
446
  multiple: false,
447
447
  },
448
+ "https-ca": {
449
+ configs: [
450
+ {
451
+ type: "string",
452
+ multiple: true,
453
+ description:
454
+ "Path to an SSL CA certificate or content of an SSL CA certificate.",
455
+ path: "https.ca[]",
456
+ },
457
+ ],
458
+ description:
459
+ "Path to an SSL CA certificate or content of an SSL CA certificate.",
460
+ simpleType: "string",
461
+ multiple: true,
462
+ },
463
+ "https-ca-reset": {
464
+ configs: [
465
+ {
466
+ description:
467
+ "Clear all items provided in 'https.ca' configuration. Path to an SSL CA certificate or content of an SSL CA certificate.",
468
+ multiple: false,
469
+ path: "https.ca",
470
+ type: "reset",
471
+ },
472
+ ],
473
+ description:
474
+ "Clear all items provided in 'https.ca' configuration. Path to an SSL CA certificate or content of an SSL CA certificate.",
475
+ multiple: false,
476
+ simpleType: "boolean",
477
+ },
448
478
  "https-cacert": {
449
479
  configs: [
450
480
  {
451
481
  type: "string",
482
+ multiple: true,
483
+ description:
484
+ "Path to an SSL CA certificate or content of an SSL CA certificate.",
485
+ path: "https.cacert[]",
486
+ },
487
+ ],
488
+ description:
489
+ "Path to an SSL CA certificate or content of an SSL CA certificate.",
490
+ simpleType: "string",
491
+ multiple: true,
492
+ },
493
+ "https-cacert-reset": {
494
+ configs: [
495
+ {
496
+ description:
497
+ "Clear all items provided in 'https.cacert' configuration. Path to an SSL CA certificate or content of an SSL CA certificate.",
452
498
  multiple: false,
453
- description: "Path to an SSL CA certificate.",
454
499
  path: "https.cacert",
500
+ type: "reset",
455
501
  },
456
502
  ],
457
- description: "Path to an SSL CA certificate.",
458
- simpleType: "string",
503
+ description:
504
+ "Clear all items provided in 'https.cacert' configuration. Path to an SSL CA certificate or content of an SSL CA certificate.",
459
505
  multiple: false,
506
+ simpleType: "boolean",
460
507
  },
461
508
  "https-key": {
462
509
  configs: [
463
510
  {
464
511
  type: "string",
512
+ multiple: true,
513
+ description: "Path to an SSL key or content of an SSL key.",
514
+ path: "https.key[]",
515
+ },
516
+ ],
517
+ description: "Path to an SSL key or content of an SSL key.",
518
+ simpleType: "string",
519
+ multiple: true,
520
+ },
521
+ "https-key-reset": {
522
+ configs: [
523
+ {
524
+ description:
525
+ "Clear all items provided in 'https.key' configuration. Path to an SSL key or content of an SSL key.",
465
526
  multiple: false,
466
- description: "Path to an SSL key.",
467
527
  path: "https.key",
528
+ type: "reset",
468
529
  },
469
530
  ],
470
- description: "Path to an SSL key.",
471
- simpleType: "string",
531
+ description:
532
+ "Clear all items provided in 'https.key' configuration. Path to an SSL key or content of an SSL key.",
472
533
  multiple: false,
534
+ simpleType: "boolean",
473
535
  },
474
536
  "https-pfx": {
475
537
  configs: [
476
538
  {
477
539
  type: "string",
540
+ multiple: true,
541
+ description: "Path to an SSL pfx file or content of an SSL pfx file.",
542
+ path: "https.pfx[]",
543
+ },
544
+ ],
545
+ description: "Path to an SSL pfx file or content of an SSL pfx file.",
546
+ simpleType: "string",
547
+ multiple: true,
548
+ },
549
+ "https-pfx-reset": {
550
+ configs: [
551
+ {
552
+ description:
553
+ "Clear all items provided in 'https.pfx' configuration. Path to an SSL pfx file or content of an SSL pfx file.",
478
554
  multiple: false,
479
- description: "Path to an SSL pfx file.",
480
555
  path: "https.pfx",
556
+ type: "reset",
481
557
  },
482
558
  ],
483
- description: "Path to an SSL pfx file.",
484
- simpleType: "string",
559
+ description:
560
+ "Clear all items provided in 'https.pfx' configuration. Path to an SSL pfx file or content of an SSL pfx file.",
485
561
  multiple: false,
562
+ simpleType: "boolean",
486
563
  },
487
564
  "https-cert": {
488
565
  configs: [
489
566
  {
490
567
  type: "string",
568
+ multiple: true,
569
+ description:
570
+ "Path to an SSL certificate or content of an SSL certificate.",
571
+ path: "https.cert[]",
572
+ },
573
+ ],
574
+ description: "Path to an SSL certificate or content of an SSL certificate.",
575
+ simpleType: "string",
576
+ multiple: true,
577
+ },
578
+ "https-cert-reset": {
579
+ configs: [
580
+ {
581
+ description:
582
+ "Clear all items provided in 'https.cert' configuration. Path to an SSL certificate or content of an SSL certificate.",
491
583
  multiple: false,
492
- description: "Path to an SSL certificate.",
493
584
  path: "https.cert",
585
+ type: "reset",
586
+ },
587
+ ],
588
+ description:
589
+ "Clear all items provided in 'https.cert' configuration. Path to an SSL certificate or content of an SSL certificate.",
590
+ multiple: false,
591
+ simpleType: "boolean",
592
+ },
593
+ "https-crl": {
594
+ configs: [
595
+ {
596
+ description:
597
+ "Path to PEM formatted CRLs (Certificate Revocation Lists) or content of PEM formatted CRLs (Certificate Revocation Lists).",
598
+ multiple: true,
599
+ path: "https.crl[]",
600
+ type: "string",
494
601
  },
495
602
  ],
496
- description: "Path to an SSL certificate.",
603
+ description:
604
+ "Path to PEM formatted CRLs (Certificate Revocation Lists) or content of PEM formatted CRLs (Certificate Revocation Lists).",
605
+ multiple: true,
497
606
  simpleType: "string",
607
+ },
608
+ "https-crl-reset": {
609
+ configs: [
610
+ {
611
+ description:
612
+ "Clear all items provided in 'https.crl' configuration. Path to PEM formatted CRLs (Certificate Revocation Lists) or content of PEM formatted CRLs (Certificate Revocation Lists).",
613
+ multiple: false,
614
+ path: "https.crl",
615
+ type: "reset",
616
+ },
617
+ ],
618
+ description:
619
+ "Clear all items provided in 'https.crl' configuration. Path to PEM formatted CRLs (Certificate Revocation Lists) or content of PEM formatted CRLs (Certificate Revocation Lists).",
498
620
  multiple: false,
621
+ simpleType: "boolean",
499
622
  },
500
623
  ipc: {
501
624
  configs: [
package/client/index.js CHANGED
@@ -3,7 +3,7 @@ import webpackHotLog from "webpack/hot/log.js";
3
3
  import stripAnsi from "./modules/strip-ansi/index.js";
4
4
  import parseURL from "./utils/parseURL.js";
5
5
  import socket from "./socket.js";
6
- import { show, hide } from "./overlay.js";
6
+ import { formatProblem, show, hide } from "./overlay.js";
7
7
  import { log, setLogLevel } from "./utils/log.js";
8
8
  import sendMessage from "./utils/sendMessage.js";
9
9
  import reloadApp from "./utils/reloadApp.js";
@@ -77,6 +77,7 @@ var onSocketMessage = {
77
77
  sendMessage("Invalid");
78
78
  },
79
79
  hash: function hash(_hash) {
80
+ status.previousHash = status.currentHash;
80
81
  status.currentHash = _hash;
81
82
  },
82
83
  logging: setAllLogLevel,
@@ -127,20 +128,24 @@ var onSocketMessage = {
127
128
  warnings: function warnings(_warnings) {
128
129
  log.warn("Warnings while compiling.");
129
130
 
130
- var strippedWarnings = _warnings.map(function (warning) {
131
- return stripAnsi(warning.message ? warning.message : warning);
131
+ var printableWarnings = _warnings.map(function (error) {
132
+ var _formatProblem = formatProblem("warning", error),
133
+ header = _formatProblem.header,
134
+ body = _formatProblem.body;
135
+
136
+ return "".concat(header, "\n").concat(stripAnsi(body));
132
137
  });
133
138
 
134
- sendMessage("Warnings", strippedWarnings);
139
+ sendMessage("Warnings", printableWarnings);
135
140
 
136
- for (var i = 0; i < strippedWarnings.length; i++) {
137
- log.warn(strippedWarnings[i]);
141
+ for (var i = 0; i < printableWarnings.length; i++) {
142
+ log.warn(printableWarnings[i]);
138
143
  }
139
144
 
140
- var needShowOverlay = typeof options.overlay === "boolean" ? options.overlay : options.overlay && options.overlay.warnings;
145
+ var needShowOverlayForWarnings = typeof options.overlay === "boolean" ? options.overlay : options.overlay && options.overlay.warnings;
141
146
 
142
- if (needShowOverlay) {
143
- show(_warnings, "warnings");
147
+ if (needShowOverlayForWarnings) {
148
+ show("warning", _warnings);
144
149
  }
145
150
 
146
151
  reloadApp(options, status);
@@ -148,20 +153,24 @@ var onSocketMessage = {
148
153
  errors: function errors(_errors) {
149
154
  log.error("Errors while compiling. Reload prevented.");
150
155
 
151
- var strippedErrors = _errors.map(function (error) {
152
- return stripAnsi(error.message ? error.message : error);
156
+ var printableErrors = _errors.map(function (error) {
157
+ var _formatProblem2 = formatProblem("error", error),
158
+ header = _formatProblem2.header,
159
+ body = _formatProblem2.body;
160
+
161
+ return "".concat(header, "\n").concat(stripAnsi(body));
153
162
  });
154
163
 
155
- sendMessage("Errors", strippedErrors);
164
+ sendMessage("Errors", printableErrors);
156
165
 
157
- for (var i = 0; i < strippedErrors.length; i++) {
158
- log.error(strippedErrors[i]);
166
+ for (var i = 0; i < printableErrors.length; i++) {
167
+ log.error(printableErrors[i]);
159
168
  }
160
169
 
161
- var needShowOverlay = typeof options.overlay === "boolean" ? options.overlay : options.overlay && options.overlay.errors;
170
+ var needShowOverlayForErrors = typeof options.overlay === "boolean" ? options.overlay : options.overlay && options.overlay.errors;
162
171
 
163
- if (needShowOverlay) {
164
- show(_errors, "errors");
172
+ if (needShowOverlayForErrors) {
173
+ show("error", _errors);
165
174
  }
166
175
  },
167
176
  error: function error(_error) {
@@ -169,6 +178,11 @@ var onSocketMessage = {
169
178
  },
170
179
  close: function close() {
171
180
  log.info("Disconnected!");
181
+
182
+ if (options.overlay) {
183
+ hide();
184
+ }
185
+
172
186
  sendMessage("Close");
173
187
  }
174
188
  };
@@ -39,7 +39,7 @@ function ansiRegex() {
39
39
  _ref$onlyFirst = _ref.onlyFirst,
40
40
  onlyFirst = _ref$onlyFirst === void 0 ? false : _ref$onlyFirst;
41
41
 
42
- var pattern = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'].join('|');
42
+ var pattern = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'].join('|');
43
43
  return new RegExp(pattern, onlyFirst ? undefined : 'g');
44
44
  }
45
45
 
package/client/overlay.js CHANGED
@@ -108,19 +108,44 @@ function hide() {
108
108
  document.body.removeChild(iframeContainerElement);
109
109
  iframeContainerElement = null;
110
110
  containerElement = null;
111
+ }
112
+
113
+ function formatProblem(type, item) {
114
+ var header = type === "warning" ? "WARNING" : "ERROR";
115
+ var body = "";
116
+
117
+ if (typeof item === "string") {
118
+ body += item;
119
+ } else {
120
+ var file = item.file || ""; // eslint-disable-next-line no-nested-ternary
121
+
122
+ var moduleName = item.moduleName ? item.moduleName.indexOf("!") !== -1 ? "".concat(item.moduleName.replace(/^(\s|\S)*!/, ""), " (").concat(item.moduleName, ")") : "".concat(item.moduleName) : "";
123
+ var loc = item.loc;
124
+ header += "".concat(moduleName || file ? " in ".concat(moduleName ? "".concat(moduleName).concat(file ? " (".concat(file, ")") : "") : file).concat(loc ? " ".concat(loc) : "") : "");
125
+ body += item.message || "";
126
+ }
127
+
128
+ return {
129
+ header: header,
130
+ body: body
131
+ };
111
132
  } // Compilation with errors (e.g. syntax error or missing modules).
112
133
 
113
134
 
114
- function show(messages, type) {
135
+ function show(type, messages) {
115
136
  ensureOverlayExists(function () {
116
137
  messages.forEach(function (message) {
117
138
  var entryElement = document.createElement("div");
118
139
  var typeElement = document.createElement("span");
119
- typeElement.innerText = type === "warnings" ? "Warning:" : "Error:";
140
+
141
+ var _formatProblem = formatProblem(type, message),
142
+ header = _formatProblem.header,
143
+ body = _formatProblem.body;
144
+
145
+ typeElement.innerText = header;
120
146
  typeElement.style.color = "#".concat(colors.red); // Make it look similar to our terminal.
121
147
 
122
- var errorMessage = message.message || messages[0];
123
- var text = ansiHTML(encode(errorMessage));
148
+ var text = ansiHTML(encode(body));
124
149
  var messageTextNode = document.createElement("div");
125
150
  messageTextNode.innerHTML = text;
126
151
  entryElement.appendChild(typeElement);
@@ -134,4 +159,4 @@ function show(messages, type) {
134
159
  });
135
160
  }
136
161
 
137
- export { show, hide };
162
+ export { formatProblem, show, hide };
@@ -8,21 +8,13 @@ function reloadApp(_ref, status) {
8
8
 
9
9
  if (status.isUnloading) {
10
10
  return;
11
- } // TODO Workaround for webpack v4, `__webpack_hash__` is not replaced without HotModuleReplacement plugin
12
-
11
+ }
13
12
 
14
- var webpackHash = // eslint-disable-next-line camelcase
15
- typeof __webpack_hash__ !== "undefined" ? // eslint-disable-next-line camelcase
16
- __webpack_hash__ : status.previousHash || "";
17
- var isInitial = status.currentHash.indexOf(webpackHash) === 0;
13
+ var currentHash = status.currentHash,
14
+ previousHash = status.previousHash;
15
+ var isInitial = currentHash.indexOf(previousHash) >= 0;
18
16
 
19
17
  if (isInitial) {
20
- var isLegacyInitial = webpackHash === "" && hot === false && liveReload === true;
21
-
22
- if (isLegacyInitial) {
23
- status.previousHash = status.currentHash;
24
- }
25
-
26
18
  return;
27
19
  }
28
20
 
package/lib/Server.js CHANGED
@@ -36,13 +36,13 @@ class Server {
36
36
  this.webSocketProxies = [];
37
37
  this.sockets = [];
38
38
  this.compiler = compiler;
39
+ this.currentHash = null;
39
40
  }
40
41
 
41
42
  static get DEFAULT_STATS() {
42
43
  return {
43
44
  all: false,
44
45
  hash: true,
45
- assets: true,
46
46
  warnings: true,
47
47
  errors: true,
48
48
  errorDetails: false,
@@ -74,7 +74,7 @@ class Server {
74
74
  }
75
75
 
76
76
  static async getFreePort(port) {
77
- if (port && port !== "auto") {
77
+ if (typeof port !== "undefined" && port !== null && port !== "auto") {
78
78
  return port;
79
79
  }
80
80
 
@@ -517,24 +517,39 @@ class Server {
517
517
 
518
518
  // https option
519
519
  if (options.https) {
520
- for (const property of ["cacert", "pfx", "key", "cert"]) {
520
+ // TODO remove the `cacert` option in favor `ca` in the next major release
521
+ for (const property of ["cacert", "ca", "cert", "crl", "key", "pfx"]) {
522
+ if (typeof options.https[property] === "undefined") {
523
+ // eslint-disable-next-line no-continue
524
+ continue;
525
+ }
526
+
521
527
  const value = options.https[property];
522
- const isBuffer = value instanceof Buffer;
528
+ const readFile = (item) => {
529
+ if (
530
+ Buffer.isBuffer(item) ||
531
+ (typeof item === "object" && item !== null && !Array.isArray(item))
532
+ ) {
533
+ return item;
534
+ }
523
535
 
524
- if (value && !isBuffer) {
525
- let stats = null;
536
+ if (item) {
537
+ let stats = null;
526
538
 
527
- try {
528
- stats = fs.lstatSync(fs.realpathSync(value)).isFile();
529
- } catch (error) {
530
- // ignore error
539
+ try {
540
+ stats = fs.lstatSync(fs.realpathSync(item)).isFile();
541
+ } catch (error) {
542
+ // Ignore error
543
+ }
544
+
545
+ // It is file
546
+ return stats ? fs.readFileSync(item) : item;
531
547
  }
548
+ };
532
549
 
533
- // It is file
534
- options.https[property] = stats
535
- ? fs.readFileSync(path.resolve(value))
536
- : value;
537
- }
550
+ options.https[property] = Array.isArray(value)
551
+ ? value.map((item) => readFile(item))
552
+ : readFile(value);
538
553
  }
539
554
 
540
555
  let fakeCert;
@@ -654,6 +669,18 @@ class Server {
654
669
  this.logger.info(`SSL certificate: ${certificatePath}`);
655
670
  }
656
671
 
672
+ if (options.https.cacert) {
673
+ if (options.https.ca) {
674
+ this.logger.warn(
675
+ "Do not specify 'https.ca' and 'https.cacert' options together, the 'https.ca' option will be used."
676
+ );
677
+ } else {
678
+ options.https.ca = options.https.cacert;
679
+ }
680
+
681
+ delete options.https.cacert;
682
+ }
683
+
657
684
  options.https.key = options.https.key || fakeCert;
658
685
  options.https.cert = options.https.cert || fakeCert;
659
686
  }
@@ -1036,42 +1063,43 @@ class Server {
1036
1063
  }
1037
1064
 
1038
1065
  async initialize() {
1039
- const compilers = this.compiler.compilers || [this.compiler];
1066
+ if (this.options.webSocketServer) {
1067
+ const compilers = this.compiler.compilers || [this.compiler];
1040
1068
 
1041
- // eslint-disable-next-line no-shadow
1042
- compilers.forEach((compiler) => {
1043
- this.addAdditionalEntries(compiler);
1069
+ // eslint-disable-next-line no-shadow
1070
+ compilers.forEach((compiler) => {
1071
+ this.addAdditionalEntries(compiler);
1044
1072
 
1045
- const webpack = compiler.webpack || require("webpack");
1073
+ const webpack = compiler.webpack || require("webpack");
1046
1074
 
1047
- const providePlugin = new webpack.ProvidePlugin({
1048
- __webpack_dev_server_client__: this.getClientTransport(),
1049
- });
1075
+ new webpack.ProvidePlugin({
1076
+ __webpack_dev_server_client__: this.getClientTransport(),
1077
+ }).apply(compiler);
1050
1078
 
1051
- providePlugin.apply(compiler);
1079
+ // TODO remove after drop webpack v4 support
1080
+ compiler.options.plugins = compiler.options.plugins || [];
1052
1081
 
1053
- // TODO remove after drop webpack v4 support
1054
- compiler.options.plugins = compiler.options.plugins || [];
1082
+ if (this.options.hot) {
1083
+ const HMRPluginExists = compiler.options.plugins.find(
1084
+ (p) => p.constructor === webpack.HotModuleReplacementPlugin
1085
+ );
1055
1086
 
1056
- if (this.options.hot) {
1057
- const HMRPluginExists = compiler.options.plugins.find(
1058
- (p) => p.constructor === webpack.HotModuleReplacementPlugin
1059
- );
1087
+ if (HMRPluginExists) {
1088
+ this.logger.warn(
1089
+ `"hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.`
1090
+ );
1091
+ } else {
1092
+ // Apply the HMR plugin
1093
+ const plugin = new webpack.HotModuleReplacementPlugin();
1060
1094
 
1061
- if (HMRPluginExists) {
1062
- this.logger.warn(
1063
- `"hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.`
1064
- );
1065
- } else {
1066
- // apply the HMR plugin
1067
- const plugin = new webpack.HotModuleReplacementPlugin();
1068
- plugin.apply(compiler);
1095
+ plugin.apply(compiler);
1096
+ }
1069
1097
  }
1070
- }
1071
- });
1098
+ });
1072
1099
 
1073
- if (this.options.client && this.options.client.progress) {
1074
- this.setupProgressPlugin();
1100
+ if (this.options.client && this.options.client.progress) {
1101
+ this.setupProgressPlugin();
1102
+ }
1075
1103
  }
1076
1104
 
1077
1105
  this.setupHooks();
@@ -1087,11 +1115,31 @@ class Server {
1087
1115
  if (this.options.setupExitSignals) {
1088
1116
  const signals = ["SIGINT", "SIGTERM"];
1089
1117
 
1118
+ let needForceShutdown = false;
1119
+
1120
+ const exitProcess = () => {
1121
+ // eslint-disable-next-line no-process-exit
1122
+ process.exit();
1123
+ };
1124
+
1090
1125
  signals.forEach((signal) => {
1091
1126
  process.on(signal, () => {
1127
+ if (needForceShutdown) {
1128
+ exitProcess();
1129
+ }
1130
+
1131
+ this.logger.info(
1132
+ "Gracefully shutting down. To force exit, press ^C again. Please wait..."
1133
+ );
1134
+
1135
+ needForceShutdown = true;
1136
+
1092
1137
  this.stopCallback(() => {
1093
- // eslint-disable-next-line no-process-exit
1094
- process.exit();
1138
+ if (typeof this.compiler.close === "function") {
1139
+ this.compiler.close(exitProcess);
1140
+ } else {
1141
+ exitProcess();
1142
+ }
1095
1143
  });
1096
1144
  });
1097
1145
  });
@@ -1123,26 +1171,18 @@ class Server {
1123
1171
  }
1124
1172
 
1125
1173
  setupHooks() {
1126
- const addHooks = (compiler) => {
1127
- compiler.hooks.invalid.tap("webpack-dev-server", () => {
1128
- if (this.webSocketServer) {
1129
- this.sendMessage(this.webSocketServer.clients, "invalid");
1130
- }
1131
- });
1132
- compiler.hooks.done.tap("webpack-dev-server", (stats) => {
1133
- if (this.webSocketServer) {
1134
- this.sendStats(this.webSocketServer.clients, this.getStats(stats));
1135
- }
1136
-
1137
- this.stats = stats;
1138
- });
1139
- };
1174
+ this.compiler.hooks.invalid.tap("webpack-dev-server", () => {
1175
+ if (this.webSocketServer) {
1176
+ this.sendMessage(this.webSocketServer.clients, "invalid");
1177
+ }
1178
+ });
1179
+ this.compiler.hooks.done.tap("webpack-dev-server", (stats) => {
1180
+ if (this.webSocketServer) {
1181
+ this.sendStats(this.webSocketServer.clients, this.getStats(stats));
1182
+ }
1140
1183
 
1141
- if (this.compiler.compilers) {
1142
- this.compiler.compilers.forEach(addHooks);
1143
- } else {
1144
- addHooks(this.compiler);
1145
- }
1184
+ this.stats = stats;
1185
+ });
1146
1186
  }
1147
1187
 
1148
1188
  setupHostHeaderCheck() {
@@ -1653,7 +1693,7 @@ class Server {
1653
1693
  }
1654
1694
 
1655
1695
  logStatus() {
1656
- const colorette = require("colorette");
1696
+ const { isColorSupported, cyan, red } = require("colorette");
1657
1697
 
1658
1698
  const getColorsOption = (compilerOptions) => {
1659
1699
  let colorsEnabled;
@@ -1664,7 +1704,7 @@ class Server {
1664
1704
  ) {
1665
1705
  colorsEnabled = compilerOptions.stats;
1666
1706
  } else {
1667
- colorsEnabled = colorette.options.enabled;
1707
+ colorsEnabled = isColorSupported;
1668
1708
  }
1669
1709
 
1670
1710
  return colorsEnabled;
@@ -1673,14 +1713,14 @@ class Server {
1673
1713
  const colors = {
1674
1714
  info(useColor, msg) {
1675
1715
  if (useColor) {
1676
- return colorette.cyan(msg);
1716
+ return cyan(msg);
1677
1717
  }
1678
1718
 
1679
1719
  return msg;
1680
1720
  },
1681
1721
  error(useColor, msg) {
1682
1722
  if (useColor) {
1683
- return colorette.red(msg);
1723
+ return red(msg);
1684
1724
  }
1685
1725
 
1686
1726
  return msg;
@@ -1826,10 +1866,19 @@ class Server {
1826
1866
  headers = headers(req, res, this.middleware.context);
1827
1867
  }
1828
1868
 
1829
- // eslint-disable-next-line guard-for-in
1830
- for (const name in headers) {
1831
- res.setHeader(name, headers[name]);
1869
+ const allHeaders = [];
1870
+
1871
+ if (!Array.isArray(headers)) {
1872
+ // eslint-disable-next-line guard-for-in
1873
+ for (const name in headers) {
1874
+ allHeaders.push({ key: name, value: headers[name] });
1875
+ }
1876
+ headers = allHeaders;
1832
1877
  }
1878
+
1879
+ headers.forEach((header) => {
1880
+ res.setHeader(header.key, header.value);
1881
+ });
1833
1882
  }
1834
1883
 
1835
1884
  next();
@@ -1850,6 +1899,10 @@ class Server {
1850
1899
  return false;
1851
1900
  }
1852
1901
 
1902
+ if (/^(file|.+-extension):/i.test(hostHeader)) {
1903
+ return true;
1904
+ }
1905
+
1853
1906
  // use the node url-parser to retrieve the hostname from the host-header.
1854
1907
  const hostname = url.parse(
1855
1908
  // if hostHeader doesn't have scheme, add // for parsing.
@@ -1917,13 +1970,13 @@ class Server {
1917
1970
 
1918
1971
  // eslint-disable-next-line class-methods-use-this
1919
1972
  sendMessage(clients, type, data) {
1920
- clients.forEach((client) => {
1973
+ for (const client of clients) {
1921
1974
  // `sockjs` uses `1` to indicate client is ready to accept data
1922
1975
  // `ws` uses `WebSocket.OPEN`, but it is mean `1` too
1923
1976
  if (client.readyState === 1) {
1924
1977
  client.send(JSON.stringify({ type, data }));
1925
1978
  }
1926
- });
1979
+ }
1927
1980
  }
1928
1981
 
1929
1982
  serveMagicHtml(req, res, next) {
@@ -1958,8 +2011,7 @@ class Server {
1958
2011
  stats &&
1959
2012
  (!stats.errors || stats.errors.length === 0) &&
1960
2013
  (!stats.warnings || stats.warnings.length === 0) &&
1961
- stats.assets &&
1962
- stats.assets.every((asset) => !asset.emitted);
2014
+ this.currentHash === stats.hash;
1963
2015
 
1964
2016
  if (shouldEmit) {
1965
2017
  this.sendMessage(clients, "still-ok");
@@ -1967,6 +2019,7 @@ class Server {
1967
2019
  return;
1968
2020
  }
1969
2021
 
2022
+ this.currentHash = stats.hash;
1970
2023
  this.sendMessage(clients, "hash", stats.hash);
1971
2024
 
1972
2025
  if (stats.errors.length > 0 || stats.warnings.length > 0) {
@@ -2013,7 +2066,6 @@ class Server {
2013
2066
  };
2014
2067
 
2015
2068
  const chokidar = require("chokidar");
2016
-
2017
2069
  const watcher = chokidar.watch(watchPath, finalWatchOptions);
2018
2070
 
2019
2071
  // disabling refreshing on changing the content
package/lib/options.json CHANGED
@@ -201,7 +201,7 @@
201
201
  },
202
202
  {
203
203
  "type": "object",
204
- "additionalProperties": false,
204
+ "additionalProperties": true,
205
205
  "properties": {
206
206
  "passphrase": {
207
207
  "type": "string",
@@ -211,8 +211,45 @@
211
211
  "type": "boolean",
212
212
  "description": "Request for an SSL certificate."
213
213
  },
214
+ "ca": {
215
+ "anyOf": [
216
+ {
217
+ "type": "array",
218
+ "items": {
219
+ "anyOf": [
220
+ {
221
+ "type": "string"
222
+ },
223
+ {
224
+ "instanceof": "Buffer"
225
+ }
226
+ ]
227
+ }
228
+ },
229
+ {
230
+ "type": "string"
231
+ },
232
+ {
233
+ "instanceof": "Buffer"
234
+ }
235
+ ],
236
+ "description": "Path to an SSL CA certificate or content of an SSL CA certificate."
237
+ },
214
238
  "cacert": {
215
239
  "anyOf": [
240
+ {
241
+ "type": "array",
242
+ "items": {
243
+ "anyOf": [
244
+ {
245
+ "type": "string"
246
+ },
247
+ {
248
+ "instanceof": "Buffer"
249
+ }
250
+ ]
251
+ }
252
+ },
216
253
  {
217
254
  "type": "string"
218
255
  },
@@ -220,10 +257,23 @@
220
257
  "instanceof": "Buffer"
221
258
  }
222
259
  ],
223
- "description": "Path to an SSL CA certificate."
260
+ "description": "Path to an SSL CA certificate or content of an SSL CA certificate."
224
261
  },
225
- "key": {
262
+ "cert": {
226
263
  "anyOf": [
264
+ {
265
+ "type": "array",
266
+ "items": {
267
+ "anyOf": [
268
+ {
269
+ "type": "string"
270
+ },
271
+ {
272
+ "instanceof": "Buffer"
273
+ }
274
+ ]
275
+ }
276
+ },
227
277
  {
228
278
  "type": "string"
229
279
  },
@@ -231,10 +281,23 @@
231
281
  "instanceof": "Buffer"
232
282
  }
233
283
  ],
234
- "description": "Path to an SSL key."
284
+ "description": "Path to an SSL certificate or content of an SSL certificate."
235
285
  },
236
- "pfx": {
286
+ "crl": {
237
287
  "anyOf": [
288
+ {
289
+ "type": "array",
290
+ "items": {
291
+ "anyOf": [
292
+ {
293
+ "type": "string"
294
+ },
295
+ {
296
+ "instanceof": "Buffer"
297
+ }
298
+ ]
299
+ }
300
+ },
238
301
  {
239
302
  "type": "string"
240
303
  },
@@ -242,10 +305,27 @@
242
305
  "instanceof": "Buffer"
243
306
  }
244
307
  ],
245
- "description": "Path to an SSL pfx file."
308
+ "description": "Path to PEM formatted CRLs (Certificate Revocation Lists) or content of PEM formatted CRLs (Certificate Revocation Lists)."
246
309
  },
247
- "cert": {
310
+ "key": {
248
311
  "anyOf": [
312
+ {
313
+ "type": "array",
314
+ "items": {
315
+ "anyOf": [
316
+ {
317
+ "type": "string"
318
+ },
319
+ {
320
+ "instanceof": "Buffer"
321
+ },
322
+ {
323
+ "type": "object",
324
+ "additionalProperties": true
325
+ }
326
+ ]
327
+ }
328
+ },
249
329
  {
250
330
  "type": "string"
251
331
  },
@@ -253,7 +333,35 @@
253
333
  "instanceof": "Buffer"
254
334
  }
255
335
  ],
256
- "description": "Path to an SSL certificate."
336
+ "description": "Path to an SSL key or content of an SSL key."
337
+ },
338
+ "pfx": {
339
+ "anyOf": [
340
+ {
341
+ "type": "array",
342
+ "items": {
343
+ "anyOf": [
344
+ {
345
+ "type": "string"
346
+ },
347
+ {
348
+ "instanceof": "Buffer"
349
+ },
350
+ {
351
+ "type": "object",
352
+ "additionalProperties": true
353
+ }
354
+ ]
355
+ }
356
+ },
357
+ {
358
+ "type": "string"
359
+ },
360
+ {
361
+ "instanceof": "Buffer"
362
+ }
363
+ ],
364
+ "description": "Path to an SSL pfx file or content of an SSL pfx file."
257
365
  }
258
366
  }
259
367
  }
@@ -261,8 +369,32 @@
261
369
  "description": "Allows to configure the server's listening socket for TLS (by default, dev server will be served over HTTP).",
262
370
  "link": "https://webpack.js.org/configuration/dev-server/#devserverhttps"
263
371
  },
372
+ "HeaderObject": {
373
+ "type": "object",
374
+ "additionalProperties": false,
375
+ "properties": {
376
+ "key": {
377
+ "description": "key of header.",
378
+ "type": "string"
379
+ },
380
+ "value": {
381
+ "description": "value of header.",
382
+ "type": "string"
383
+ }
384
+ },
385
+ "cli": {
386
+ "exclude": true
387
+ }
388
+ },
264
389
  "Headers": {
265
390
  "anyOf": [
391
+ {
392
+ "type": "array",
393
+ "items": {
394
+ "$ref": "#/definitions/HeaderObject"
395
+ },
396
+ "minItems": 1
397
+ },
266
398
  {
267
399
  "type": "object"
268
400
  },
@@ -446,7 +578,9 @@
446
578
  "Port": {
447
579
  "anyOf": [
448
580
  {
449
- "type": "number"
581
+ "type": "number",
582
+ "minimum": 0,
583
+ "maximum": 65535
450
584
  },
451
585
  {
452
586
  "type": "string",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpack-dev-server",
3
- "version": "4.1.1",
3
+ "version": "4.3.1",
4
4
  "description": "Serves a webpack app. Updates the browser on changes.",
5
5
  "bin": "bin/webpack-dev-server.js",
6
6
  "main": "lib/Server.js",
@@ -35,7 +35,7 @@
35
35
  "ansi-html-community": "^0.0.8",
36
36
  "bonjour": "^3.5.0",
37
37
  "chokidar": "^3.5.1",
38
- "colorette": "^1.2.2",
38
+ "colorette": "^2.0.10",
39
39
  "compression": "^1.7.4",
40
40
  "connect-history-api-fallback": "^1.6.0",
41
41
  "del": "^6.0.0",
@@ -55,7 +55,7 @@
55
55
  "spdy": "^4.0.2",
56
56
  "strip-ansi": "^7.0.0",
57
57
  "url": "^0.11.0",
58
- "webpack-dev-middleware": "^5.0.0",
58
+ "webpack-dev-middleware": "^5.2.1",
59
59
  "ws": "^8.1.0"
60
60
  },
61
61
  "devDependencies": {
@@ -103,7 +103,7 @@
103
103
  "tcp-port-used": "^1.0.2",
104
104
  "typescript": "^4.2.4",
105
105
  "url-loader": "^4.1.1",
106
- "webpack": "^5.50.0",
106
+ "webpack": "^5.54.0",
107
107
  "webpack-cli": "^4.7.2",
108
108
  "webpack-merge": "^5.8.0"
109
109
  },