webpack-dev-server 3.5.0 → 3.7.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/client/socket.js CHANGED
@@ -1,24 +1,26 @@
1
1
  'use strict';
2
+ /* global __webpack_dev_server_client__ */
2
3
 
3
- var SockJS = require('sockjs-client/dist/sockjs');
4
+ /* eslint-disable
5
+ camelcase
6
+ */
4
7
 
8
+ var Client = __webpack_dev_server_client__;
5
9
  var retries = 0;
6
- var sock = null;
10
+ var client = null;
7
11
 
8
12
  var socket = function initSocket(url, handlers) {
9
- sock = new SockJS(url);
10
-
11
- sock.onopen = function onopen() {
13
+ client = new Client(url);
14
+ client.onOpen(function () {
12
15
  retries = 0;
13
- };
14
-
15
- sock.onclose = function onclose() {
16
+ });
17
+ client.onClose(function () {
16
18
  if (retries === 0) {
17
19
  handlers.close();
18
20
  } // Try to reconnect.
19
21
 
20
22
 
21
- sock = null; // After 10 retries stop trying, to prevent logspam.
23
+ client = null; // After 10 retries stop trying, to prevent logspam.
22
24
 
23
25
  if (retries <= 10) {
24
26
  // Exponentially increase timeout to reconnect.
@@ -30,16 +32,14 @@ var socket = function initSocket(url, handlers) {
30
32
  socket(url, handlers);
31
33
  }, retryInMs);
32
34
  }
33
- };
34
-
35
- sock.onmessage = function onmessage(e) {
36
- // This assumes that all data sent via the websocket is JSON.
37
- var msg = JSON.parse(e.data);
35
+ });
36
+ client.onMessage(function (data) {
37
+ var msg = JSON.parse(data);
38
38
 
39
39
  if (handlers[msg.type]) {
40
40
  handlers[msg.type](msg.data);
41
41
  }
42
- };
42
+ });
43
43
  };
44
44
 
45
45
  module.exports = socket;
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+ /* global self */
3
+
4
+ var url = require('url');
5
+
6
+ var querystring = require('querystring');
7
+
8
+ var getCurrentScriptSource = require('./getCurrentScriptSource');
9
+
10
+ function createSocketUrl(resourceQuery) {
11
+ var urlParts;
12
+
13
+ if (typeof resourceQuery === 'string' && resourceQuery !== '') {
14
+ // If this bundle is inlined, use the resource query to get the correct url.
15
+ urlParts = url.parse(resourceQuery.substr(1));
16
+ } else {
17
+ // Else, get the url from the <script> this file was called with.
18
+ var scriptHost = getCurrentScriptSource(); // eslint-disable-next-line no-useless-escape
19
+
20
+ scriptHost = scriptHost.replace(/\/[^\/]+$/, '');
21
+ urlParts = url.parse(scriptHost || '/', false, true);
22
+ }
23
+
24
+ if (!urlParts.port || urlParts.port === '0') {
25
+ urlParts.port = self.location.port;
26
+ }
27
+
28
+ var _urlParts = urlParts,
29
+ auth = _urlParts.auth,
30
+ path = _urlParts.path;
31
+ var _urlParts2 = urlParts,
32
+ hostname = _urlParts2.hostname,
33
+ protocol = _urlParts2.protocol; // check ipv4 and ipv6 `all hostname`
34
+ // why do we need this check?
35
+ // hostname n/a for file protocol (example, when using electron, ionic)
36
+ // see: https://github.com/webpack/webpack-dev-server/pull/384
37
+
38
+ if ((hostname === '0.0.0.0' || hostname === '::') && self.location.hostname && // eslint-disable-next-line no-bitwise
39
+ !!~self.location.protocol.indexOf('http')) {
40
+ hostname = self.location.hostname;
41
+ } // `hostname` can be empty when the script path is relative. In that case, specifying
42
+ // a protocol would result in an invalid URL.
43
+ // When https is used in the app, secure websockets are always necessary
44
+ // because the browser doesn't accept non-secure websockets.
45
+
46
+
47
+ if (hostname && (self.location.protocol === 'https:' || urlParts.hostname === '0.0.0.0')) {
48
+ protocol = self.location.protocol;
49
+ } // default values of the sock url if they are not provided
50
+
51
+
52
+ var sockHost = hostname;
53
+ var sockPath = '/sockjs-node';
54
+ var sockPort = urlParts.port; // eslint-disable-next-line no-undefined
55
+
56
+ if (path !== null && path !== undefined && path !== '/') {
57
+ var parsedQuery = querystring.parse(path); // all of these sock url params are optionally passed in through
58
+ // resourceQuery, so we need to fall back to the default if
59
+ // they are not provided
60
+
61
+ sockHost = parsedQuery.sockHost || sockHost;
62
+ sockPath = parsedQuery.sockPath || sockPath;
63
+ sockPort = parsedQuery.sockPort || sockPort;
64
+ }
65
+
66
+ return url.format({
67
+ protocol: protocol,
68
+ auth: auth,
69
+ hostname: sockHost,
70
+ port: sockPort,
71
+ // If sockPath is provided it'll be passed in via the resourceQuery as a
72
+ // query param so it has to be parsed out of the querystring in order for the
73
+ // client to open the socket to the correct location.
74
+ pathname: sockPath
75
+ });
76
+ }
77
+
78
+ module.exports = createSocketUrl;
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ function getCurrentScriptSource() {
4
+ // `document.currentScript` is the most accurate way to find the current script,
5
+ // but is not supported in all browsers.
6
+ if (document.currentScript) {
7
+ return document.currentScript.getAttribute('src');
8
+ } // Fall back to getting all scripts in the document.
9
+
10
+
11
+ var scriptElements = document.scripts || [];
12
+ var currentScript = scriptElements[scriptElements.length - 1];
13
+
14
+ if (currentScript) {
15
+ return currentScript.getAttribute('src');
16
+ } // Fail as there was no script to use.
17
+
18
+
19
+ throw new Error('[WDS] Failed to get current script source.');
20
+ }
21
+
22
+ module.exports = getCurrentScriptSource;
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+
3
+ var log = require('loglevel').getLogger('webpack-dev-server');
4
+
5
+ var INFO = 'info';
6
+ var WARN = 'warn';
7
+ var ERROR = 'error';
8
+ var DEBUG = 'debug';
9
+ var TRACE = 'trace';
10
+ var SILENT = 'silent'; // deprecated
11
+ // TODO: remove these at major released
12
+ // https://github.com/webpack/webpack-dev-server/pull/1825
13
+
14
+ var WARNING = 'warning';
15
+ var NONE = 'none'; // Set the default log level
16
+
17
+ log.setDefaultLevel(INFO);
18
+
19
+ function setLogLevel(level) {
20
+ switch (level) {
21
+ case INFO:
22
+ case WARN:
23
+ case ERROR:
24
+ case DEBUG:
25
+ case TRACE:
26
+ log.setLevel(level);
27
+ break;
28
+ // deprecated
29
+
30
+ case WARNING:
31
+ // loglevel's warning name is different from webpack's
32
+ log.setLevel('warn');
33
+ break;
34
+ // deprecated
35
+
36
+ case NONE:
37
+ case SILENT:
38
+ log.disableAll();
39
+ break;
40
+
41
+ default:
42
+ log.error("[WDS] Unknown clientLogLevel '".concat(level, "'"));
43
+ }
44
+ }
45
+
46
+ module.exports = {
47
+ log: log,
48
+ setLogLevel: setLogLevel
49
+ };
@@ -0,0 +1,55 @@
1
+ 'use strict';
2
+ /* global WorkerGlobalScope self */
3
+
4
+ var _require = require('./log'),
5
+ log = _require.log;
6
+
7
+ function reloadApp(_ref, _ref2) {
8
+ var hotReload = _ref.hotReload,
9
+ hot = _ref.hot,
10
+ liveReload = _ref.liveReload;
11
+ var isUnloading = _ref2.isUnloading,
12
+ currentHash = _ref2.currentHash;
13
+
14
+ if (isUnloading || !hotReload) {
15
+ return;
16
+ }
17
+
18
+ if (hot) {
19
+ log.info('[WDS] App hot update...'); // eslint-disable-next-line global-require
20
+
21
+ var hotEmitter = require('webpack/hot/emitter');
22
+
23
+ hotEmitter.emit('webpackHotUpdate', currentHash);
24
+
25
+ if (typeof self !== 'undefined' && self.window) {
26
+ // broadcast update to window
27
+ self.postMessage("webpackHotUpdate".concat(currentHash), '*');
28
+ }
29
+ } // allow refreshing the page only if liveReload isn't disabled
30
+ else if (liveReload) {
31
+ var rootWindow = self; // use parent window for reload (in case we're in an iframe with no valid src)
32
+
33
+ var intervalId = self.setInterval(function () {
34
+ if (rootWindow.location.protocol !== 'about:') {
35
+ // reload immediately if protocol is valid
36
+ applyReload(rootWindow, intervalId);
37
+ } else {
38
+ rootWindow = rootWindow.parent;
39
+
40
+ if (rootWindow.parent === rootWindow) {
41
+ // if parent equals current window we've reached the root which would continue forever, so trigger a reload anyways
42
+ applyReload(rootWindow, intervalId);
43
+ }
44
+ }
45
+ });
46
+ }
47
+
48
+ function applyReload(rootWindow, intervalId) {
49
+ clearInterval(intervalId);
50
+ log.info('[WDS] App updated. Reloading...');
51
+ rootWindow.location.reload();
52
+ }
53
+ }
54
+
55
+ module.exports = reloadApp;
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+ /* global __resourceQuery WorkerGlobalScope self */
3
+ // Send messages to the outside, so plugins can consume it.
4
+
5
+ function sendMsg(type, data) {
6
+ if (typeof self !== 'undefined' && (typeof WorkerGlobalScope === 'undefined' || !(self instanceof WorkerGlobalScope))) {
7
+ self.postMessage({
8
+ type: "webpack".concat(type),
9
+ data: data
10
+ }, '*');
11
+ }
12
+ }
13
+
14
+ module.exports = sendMsg;
package/lib/Server.js CHANGED
@@ -30,8 +30,8 @@ const status = require('./utils/status');
30
30
  const createDomain = require('./utils/createDomain');
31
31
  const runBonjour = require('./utils/runBonjour');
32
32
  const routes = require('./utils/routes');
33
+ const getSocketServerImplementation = require('./utils/getSocketServerImplementation');
33
34
  const schema = require('./options.json');
34
- const SockJSServer = require('./servers/SockJSServer');
35
35
 
36
36
  // Workaround for node ^8.6.0, ^9.0.0
37
37
  // DEFAULT_ECDH_CURVE is default to prime256v1 in these version
@@ -67,6 +67,19 @@ class Server {
67
67
 
68
68
  this.log = _log || createLogger(options);
69
69
 
70
+ if (this.options.serverMode === undefined) {
71
+ this.options.serverMode = 'sockjs';
72
+ } else {
73
+ this.log.warn(
74
+ 'serverMode is an experimental option, meaning its usage could potentially change without warning'
75
+ );
76
+ }
77
+
78
+ // this.SocketServerImplementation is a class, so it must be instantiated before use
79
+ this.socketServerImplementation = getSocketServerImplementation(
80
+ this.options
81
+ );
82
+
70
83
  this.originalStats =
71
84
  this.options.stats && Object.keys(this.options.stats).length
72
85
  ? this.options.stats
@@ -92,11 +105,8 @@ class Server {
92
105
  if (!this.options.watchOptions) {
93
106
  this.options.watchOptions = {};
94
107
  }
95
- // Ignoring node_modules folder by default
96
- this.options.watchOptions.ignored = this.options.watchOptions.ignored || [
97
- /node_modules/,
98
- ];
99
- this.watchOptions = this.options.watchOptions;
108
+
109
+ this.watchOptions = options.watchOptions || {};
100
110
 
101
111
  // Replace leading and trailing slashes to normalize path
102
112
  this.sockPath = `/${
@@ -655,7 +665,8 @@ class Server {
655
665
  }
656
666
 
657
667
  createSocketServer() {
658
- this.socketServer = new SockJSServer(this);
668
+ const SocketServerImplementation = this.socketServerImplementation;
669
+ this.socketServer = new SocketServerImplementation(this);
659
670
 
660
671
  this.socketServer.onConnection((connection) => {
661
672
  if (!connection) {
@@ -683,10 +694,15 @@ class Server {
683
694
  }
684
695
  });
685
696
 
697
+ if (this.clientLogLevel) {
698
+ this.sockWrite([connection], 'log-level', this.clientLogLevel);
699
+ }
700
+
686
701
  if (this.hot) {
687
702
  this.sockWrite([connection], 'hot');
688
703
  }
689
704
 
705
+ // TODO: change condition at major version
690
706
  if (this.options.liveReload !== false) {
691
707
  this.sockWrite([connection], 'liveReload', this.options.liveReload);
692
708
  }
@@ -699,10 +715,6 @@ class Server {
699
715
  this.sockWrite([connection], 'overlay', this.clientOverlay);
700
716
  }
701
717
 
702
- if (this.clientLogLevel) {
703
- this.sockWrite([connection], 'log-level', this.clientLogLevel);
704
- }
705
-
706
718
  if (!this._stats) {
707
719
  return;
708
720
  }
@@ -711,6 +723,21 @@ class Server {
711
723
  });
712
724
  }
713
725
 
726
+ showStatus() {
727
+ const suffix =
728
+ this.options.inline !== false || this.options.lazy === true
729
+ ? '/'
730
+ : '/webpack-dev-server/';
731
+ const uri = `${createDomain(this.options, this.listeningApp)}${suffix}`;
732
+
733
+ status(
734
+ uri,
735
+ this.options,
736
+ this.log,
737
+ this.options.stats && this.options.stats.colors
738
+ );
739
+ }
740
+
714
741
  listen(port, hostname, fn) {
715
742
  this.hostname = hostname;
716
743
 
@@ -878,21 +905,6 @@ class Server {
878
905
  return false;
879
906
  }
880
907
 
881
- showStatus() {
882
- const suffix =
883
- this.options.inline !== false || this.options.lazy === true
884
- ? '/'
885
- : '/webpack-dev-server/';
886
- const uri = `${createDomain(this.options, this.listeningApp)}${suffix}`;
887
-
888
- status(
889
- uri,
890
- this.options,
891
- this.log,
892
- this.options.stats && this.options.stats.colors
893
- );
894
- }
895
-
896
908
  // eslint-disable-next-line
897
909
  sockWrite(sockets, type, data) {
898
910
  sockets.forEach((socket) => {
package/lib/options.json CHANGED
@@ -297,6 +297,16 @@
297
297
  "serveIndex": {
298
298
  "type": "boolean"
299
299
  },
300
+ "serverMode": {
301
+ "anyOf": [
302
+ {
303
+ "type": "string"
304
+ },
305
+ {
306
+ "instanceof": "Function"
307
+ }
308
+ ]
309
+ },
300
310
  "serverSideRender": {
301
311
  "type": "boolean"
302
312
  },
@@ -394,8 +404,8 @@
394
404
  "http2": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverhttp2)",
395
405
  "https": "should be {Object|Boolean} (https://webpack.js.org/configuration/dev-server/#devserverhttps)",
396
406
  "index": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserverindex)",
397
- "injectClient": "should be {Boolean|Function}",
398
- "injectHot": "should be {Boolean|Function}",
407
+ "injectClient": "should be {Boolean|Function} (https://webpack.js.org/configuration/dev-server/#devserverinjectclient)",
408
+ "injectHot": "should be {Boolean|Function} (https://webpack.js.org/configuration/dev-server/#devserverinjecthot)",
399
409
  "inline": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverinline)",
400
410
  "key": "should be {String|Buffer}",
401
411
  "lazy": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverlazy-)",
@@ -420,6 +430,7 @@
420
430
  "reporter": "should be {Function} (https://github.com/webpack/webpack-dev-middleware#reporter)",
421
431
  "requestCert": "should be {Boolean}",
422
432
  "serveIndex": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverserveindex)",
433
+ "serverMode": "should be {String|Function} (https://webpack.js.org/configuration/dev-server/#devserverservermode-)",
423
434
  "serverSideRender": "should be {Boolean} (https://github.com/webpack/webpack-dev-middleware#serversiderender)",
424
435
  "setup": "should be {Function} (https://webpack.js.org/configuration/dev-server/#devserversetup)",
425
436
  "sockHost": "should be {String|Null} (https://webpack.js.org/configuration/dev-server/#devserversockhost)",
@@ -50,6 +50,10 @@ function createConfig(config, argv, { port }) {
50
50
  options.progress = argv.progress;
51
51
  }
52
52
 
53
+ if (argv.overlay) {
54
+ options.overlay = argv.overlay;
55
+ }
56
+
53
57
  if (!options.publicPath) {
54
58
  // eslint-disable-next-line
55
59
  options.publicPath =
@@ -2,7 +2,7 @@
2
2
 
3
3
  const log = require('webpack-log');
4
4
 
5
- function createLogger(options) {
5
+ function createLogger(options = {}) {
6
6
  let level = options.logLevel || 'info';
7
7
 
8
8
  if (options.noInfo === true) {
@@ -1,12 +1,26 @@
1
1
  'use strict';
2
2
 
3
- const { getPortPromise } = require('portfinder');
3
+ const pRetry = require('p-retry');
4
+ const portfinder = require('portfinder');
4
5
  const defaultPort = require('./defaultPort');
5
6
  const defaultTo = require('./defaultTo');
6
7
  const tryParseInt = require('./tryParseInt');
7
8
 
9
+ function runPortFinder() {
10
+ return new Promise((resolve, reject) => {
11
+ portfinder.basePort = defaultPort;
12
+ portfinder.getPort((error, port) => {
13
+ if (error) {
14
+ return reject(error);
15
+ }
16
+
17
+ return resolve(port);
18
+ });
19
+ });
20
+ }
21
+
8
22
  function findPort(port) {
9
- if (typeof port !== 'undefined') {
23
+ if (port) {
10
24
  return Promise.resolve(port);
11
25
  }
12
26
 
@@ -19,10 +33,7 @@ function findPort(port) {
19
33
  3
20
34
  );
21
35
 
22
- return getPortPromise({
23
- port: defaultPort,
24
- stopPort: defaultPort + defaultPortRetry,
25
- });
36
+ return pRetry(runPortFinder, { retries: defaultPortRetry });
26
37
  }
27
38
 
28
39
  module.exports = findPort;
@@ -0,0 +1,41 @@
1
+ 'use strict';
2
+
3
+ function getSocketServerImplementation(options) {
4
+ let ServerImplementation;
5
+ let serverImplFound = true;
6
+ switch (typeof options.serverMode) {
7
+ case 'string':
8
+ // could be 'sockjs', in the future 'ws', or a path that should be required
9
+ if (options.serverMode === 'sockjs') {
10
+ // eslint-disable-next-line global-require
11
+ ServerImplementation = require('../servers/SockJSServer');
12
+ } else {
13
+ try {
14
+ // eslint-disable-next-line global-require, import/no-dynamic-require
15
+ ServerImplementation = require(options.serverMode);
16
+ } catch (e) {
17
+ serverImplFound = false;
18
+ }
19
+ }
20
+ break;
21
+ case 'function':
22
+ // potentially do more checks here to confirm that the user implemented this properlly
23
+ // since errors could be difficult to understand
24
+ ServerImplementation = options.serverMode;
25
+ break;
26
+ default:
27
+ serverImplFound = false;
28
+ }
29
+
30
+ if (!serverImplFound) {
31
+ throw new Error(
32
+ "serverMode must be a string denoting a default implementation (e.g. 'sockjs'), a full path to " +
33
+ 'a JS file which exports a class extending BaseServer (webpack-dev-server/lib/servers/BaseServer) ' +
34
+ 'via require.resolve(...), or the class itself which extends BaseServer'
35
+ );
36
+ }
37
+
38
+ return ServerImplementation;
39
+ }
40
+
41
+ module.exports = getSocketServerImplementation;
@@ -6,12 +6,14 @@ const defaultPort = require('./defaultPort');
6
6
  function processOptions(config, argv, callback) {
7
7
  // processOptions {Promise}
8
8
  if (typeof config.then === 'function') {
9
- config.then(processOptions).catch((err) => {
10
- // eslint-disable-next-line no-console
11
- console.error(err.stack || err);
12
- // eslint-disable-next-line no-process-exit
13
- process.exit();
14
- });
9
+ config
10
+ .then((conf) => processOptions(conf, argv, callback))
11
+ .catch((err) => {
12
+ // eslint-disable-next-line no-console
13
+ console.error(err.stack || err);
14
+ // eslint-disable-next-line no-process-exit
15
+ process.exit(1);
16
+ });
15
17
 
16
18
  return;
17
19
  }
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ const open = require('opn');
4
+
5
+ function runOpen(uri, options, log) {
6
+ let openOptions = {};
7
+ let openMessage = 'Unable to open browser';
8
+
9
+ if (typeof options.open === 'string') {
10
+ openOptions = { app: options.open };
11
+ openMessage += `: ${options.open}`;
12
+ }
13
+
14
+ return open(`${uri}${options.openPage || ''}`, openOptions).catch(() => {
15
+ log.warn(
16
+ `${openMessage}. If you are running in a headless environment, please do not use the --open flag`
17
+ );
18
+ });
19
+ }
20
+
21
+ module.exports = runOpen;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const open = require('opn');
4
3
  const colors = require('./colors');
4
+ const runOpen = require('./runOpen');
5
5
 
6
6
  // TODO: don't emit logs when webpack-dev-server is used via Node.js API
7
7
  function status(uri, options, log, useColor) {
@@ -44,19 +44,7 @@ function status(uri, options, log, useColor) {
44
44
  }
45
45
 
46
46
  if (options.open) {
47
- let openOptions = {};
48
- let openMessage = 'Unable to open browser';
49
-
50
- if (typeof options.open === 'string') {
51
- openOptions = { app: options.open };
52
- openMessage += `: ${options.open}`;
53
- }
54
-
55
- open(`${uri}${options.openPage || ''}`, openOptions).catch(() => {
56
- log.warn(
57
- `${openMessage}. If you are running in a headless environment, please do not use the --open flag`
58
- );
59
- });
47
+ runOpen(uri, options, log);
60
48
  }
61
49
  }
62
50
 
@@ -2,9 +2,11 @@
2
2
 
3
3
  function tryParseInt(input) {
4
4
  const output = parseInt(input, 10);
5
+
5
6
  if (Number.isNaN(output)) {
6
7
  return null;
7
8
  }
9
+
8
10
  return output;
9
11
  }
10
12
 
@@ -48,6 +48,14 @@ function updateCompiler(compiler, options) {
48
48
  compilers.forEach((compiler) => {
49
49
  const config = compiler.options;
50
50
  compiler.hooks.entryOption.call(config.context, config.entry);
51
+
52
+ const providePlugin = new webpack.ProvidePlugin({
53
+ // SockJSClient.getClientPath(options)
54
+ __webpack_dev_server_client__: require.resolve(
55
+ '../../client/clients/SockJSClient.js'
56
+ ),
57
+ });
58
+ providePlugin.apply(compiler);
51
59
  });
52
60
 
53
61
  // do not apply the plugin unless it didn't exist before.