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/CHANGELOG.md +48 -0
- package/client/clients/BaseClient.js +27 -0
- package/client/clients/SockJSClient.js +69 -0
- package/client/clients/WebsocketClient.js +31 -0
- package/client/index.bundle.js +1 -1
- package/client/index.js +55 -216
- package/client/live.bundle.js +3 -3
- package/client/socket.js +15 -15
- package/client/utils/createSocketUrl.js +78 -0
- package/client/utils/getCurrentScriptSource.js +22 -0
- package/client/utils/log.js +49 -0
- package/client/utils/reloadApp.js +55 -0
- package/client/utils/sendMessage.js +14 -0
- package/lib/Server.js +38 -26
- package/lib/options.json +13 -2
- package/lib/utils/createConfig.js +4 -0
- package/lib/utils/createLogger.js +1 -1
- package/lib/utils/findPort.js +17 -6
- package/lib/utils/getSocketServerImplementation.js +41 -0
- package/lib/utils/processOptions.js +8 -6
- package/lib/utils/runOpen.js +21 -0
- package/lib/utils/status.js +2 -14
- package/lib/utils/tryParseInt.js +2 -0
- package/lib/utils/updateCompiler.js +8 -0
- package/package.json +16 -14
package/client/socket.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
/* global __webpack_dev_server_client__ */
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
/* eslint-disable
|
|
5
|
+
camelcase
|
|
6
|
+
*/
|
|
4
7
|
|
|
8
|
+
var Client = __webpack_dev_server_client__;
|
|
5
9
|
var retries = 0;
|
|
6
|
-
var
|
|
10
|
+
var client = null;
|
|
7
11
|
|
|
8
12
|
var socket = function initSocket(url, handlers) {
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
96
|
-
this.
|
|
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
|
-
|
|
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)",
|
package/lib/utils/findPort.js
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
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 (
|
|
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
|
|
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
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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;
|
package/lib/utils/status.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
package/lib/utils/tryParseInt.js
CHANGED
|
@@ -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.
|