webpack-dev-server 3.4.1 → 3.7.0
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 +56 -0
- package/bin/webpack-dev-server.js +21 -77
- 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 +54 -65
- package/lib/options.json +17 -2
- package/lib/servers/BaseServer.js +9 -0
- package/lib/servers/SockJSServer.js +64 -0
- package/lib/servers/WebsocketServer.js +8 -0
- package/lib/utils/addEntries.js +2 -0
- package/lib/utils/createConfig.js +4 -0
- package/lib/utils/defaultPort.js +3 -0
- package/lib/utils/findPort.js +22 -29
- package/lib/utils/getSocketServerImplementation.js +41 -0
- package/lib/utils/processOptions.js +29 -0
- package/lib/utils/runOpen.js +21 -0
- package/lib/utils/setupExitSignals.js +21 -0
- package/lib/utils/status.js +2 -14
- package/lib/utils/updateCompiler.js +8 -0
- package/package.json +19 -18
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
|
@@ -12,7 +12,6 @@ const url = require('url');
|
|
|
12
12
|
const http = require('http');
|
|
13
13
|
const https = require('https');
|
|
14
14
|
const ip = require('ip');
|
|
15
|
-
const sockjs = require('sockjs');
|
|
16
15
|
const semver = require('semver');
|
|
17
16
|
const killable = require('killable');
|
|
18
17
|
const chokidar = require('chokidar');
|
|
@@ -31,28 +30,9 @@ const status = require('./utils/status');
|
|
|
31
30
|
const createDomain = require('./utils/createDomain');
|
|
32
31
|
const runBonjour = require('./utils/runBonjour');
|
|
33
32
|
const routes = require('./utils/routes');
|
|
33
|
+
const getSocketServerImplementation = require('./utils/getSocketServerImplementation');
|
|
34
34
|
const schema = require('./options.json');
|
|
35
35
|
|
|
36
|
-
// Workaround for sockjs@~0.3.19
|
|
37
|
-
// sockjs will remove Origin header, however Origin header is required for checking host.
|
|
38
|
-
// See https://github.com/webpack/webpack-dev-server/issues/1604 for more information
|
|
39
|
-
{
|
|
40
|
-
// eslint-disable-next-line global-require
|
|
41
|
-
const SockjsSession = require('sockjs/lib/transport').Session;
|
|
42
|
-
const decorateConnection = SockjsSession.prototype.decorateConnection;
|
|
43
|
-
SockjsSession.prototype.decorateConnection = function(req) {
|
|
44
|
-
decorateConnection.call(this, req);
|
|
45
|
-
const connection = this.connection;
|
|
46
|
-
if (
|
|
47
|
-
connection.headers &&
|
|
48
|
-
!('origin' in connection.headers) &&
|
|
49
|
-
'origin' in req.headers
|
|
50
|
-
) {
|
|
51
|
-
connection.headers.origin = req.headers.origin;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
36
|
// Workaround for node ^8.6.0, ^9.0.0
|
|
57
37
|
// DEFAULT_ECDH_CURVE is default to prime256v1 in these version
|
|
58
38
|
// breaking connection when certificate is not signed with prime256v1
|
|
@@ -62,6 +42,10 @@ if (semver.satisfies(process.version, '8.6.0 - 9')) {
|
|
|
62
42
|
tls.DEFAULT_ECDH_CURVE = 'auto';
|
|
63
43
|
}
|
|
64
44
|
|
|
45
|
+
if (!process.env.WEBPACK_DEV_SERVER) {
|
|
46
|
+
process.env.WEBPACK_DEV_SERVER = true;
|
|
47
|
+
}
|
|
48
|
+
|
|
65
49
|
class Server {
|
|
66
50
|
constructor(compiler, options = {}, _log) {
|
|
67
51
|
if (options.lazy && !options.filename) {
|
|
@@ -83,6 +67,19 @@ class Server {
|
|
|
83
67
|
|
|
84
68
|
this.log = _log || createLogger(options);
|
|
85
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
|
+
|
|
86
83
|
this.originalStats =
|
|
87
84
|
this.options.stats && Object.keys(this.options.stats).length
|
|
88
85
|
? this.options.stats
|
|
@@ -108,11 +105,8 @@ class Server {
|
|
|
108
105
|
if (!this.options.watchOptions) {
|
|
109
106
|
this.options.watchOptions = {};
|
|
110
107
|
}
|
|
111
|
-
|
|
112
|
-
this.
|
|
113
|
-
/node_modules/,
|
|
114
|
-
];
|
|
115
|
-
this.watchOptions = this.options.watchOptions;
|
|
108
|
+
|
|
109
|
+
this.watchOptions = options.watchOptions || {};
|
|
116
110
|
|
|
117
111
|
// Replace leading and trailing slashes to normalize path
|
|
118
112
|
this.sockPath = `/${
|
|
@@ -430,6 +424,8 @@ class Server {
|
|
|
430
424
|
}
|
|
431
425
|
|
|
432
426
|
setupBeforeFeature() {
|
|
427
|
+
// Todo rename onBeforeSetupMiddleware in next major release
|
|
428
|
+
// Todo pass only `this` argument
|
|
433
429
|
this.options.before(this.app, this, this.compiler);
|
|
434
430
|
}
|
|
435
431
|
|
|
@@ -438,6 +434,8 @@ class Server {
|
|
|
438
434
|
}
|
|
439
435
|
|
|
440
436
|
setupAfterFeature() {
|
|
437
|
+
// Todo rename onAfterSetupMiddleware in next major release
|
|
438
|
+
// Todo pass only `this` argument
|
|
441
439
|
this.options.after(this.app, this, this.compiler);
|
|
442
440
|
}
|
|
443
441
|
|
|
@@ -667,20 +665,10 @@ class Server {
|
|
|
667
665
|
}
|
|
668
666
|
|
|
669
667
|
createSocketServer() {
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
sockjs_url: '/__webpack_dev_server__/sockjs.bundle.js',
|
|
673
|
-
// Limit useless logs
|
|
674
|
-
log: (severity, line) => {
|
|
675
|
-
if (severity === 'error') {
|
|
676
|
-
this.log.error(line);
|
|
677
|
-
} else {
|
|
678
|
-
this.log.debug(line);
|
|
679
|
-
}
|
|
680
|
-
},
|
|
681
|
-
});
|
|
668
|
+
const SocketServerImplementation = this.socketServerImplementation;
|
|
669
|
+
this.socketServer = new SocketServerImplementation(this);
|
|
682
670
|
|
|
683
|
-
|
|
671
|
+
this.socketServer.onConnection((connection) => {
|
|
684
672
|
if (!connection) {
|
|
685
673
|
return;
|
|
686
674
|
}
|
|
@@ -706,10 +694,15 @@ class Server {
|
|
|
706
694
|
}
|
|
707
695
|
});
|
|
708
696
|
|
|
697
|
+
if (this.clientLogLevel) {
|
|
698
|
+
this.sockWrite([connection], 'log-level', this.clientLogLevel);
|
|
699
|
+
}
|
|
700
|
+
|
|
709
701
|
if (this.hot) {
|
|
710
702
|
this.sockWrite([connection], 'hot');
|
|
711
703
|
}
|
|
712
704
|
|
|
705
|
+
// TODO: change condition at major version
|
|
713
706
|
if (this.options.liveReload !== false) {
|
|
714
707
|
this.sockWrite([connection], 'liveReload', this.options.liveReload);
|
|
715
708
|
}
|
|
@@ -722,20 +715,27 @@ class Server {
|
|
|
722
715
|
this.sockWrite([connection], 'overlay', this.clientOverlay);
|
|
723
716
|
}
|
|
724
717
|
|
|
725
|
-
if (this.clientLogLevel) {
|
|
726
|
-
this.sockWrite([connection], 'log-level', this.clientLogLevel);
|
|
727
|
-
}
|
|
728
|
-
|
|
729
718
|
if (!this._stats) {
|
|
730
719
|
return;
|
|
731
720
|
}
|
|
732
721
|
|
|
733
722
|
this._sendStats([connection], this.getStats(this._stats), true);
|
|
734
723
|
});
|
|
724
|
+
}
|
|
735
725
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
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
739
|
}
|
|
740
740
|
|
|
741
741
|
listen(port, hostname, fn) {
|
|
@@ -753,12 +753,16 @@ class Server {
|
|
|
753
753
|
if (fn) {
|
|
754
754
|
fn.call(this.listeningApp, err);
|
|
755
755
|
}
|
|
756
|
+
|
|
757
|
+
if (typeof this.options.onListening === 'function') {
|
|
758
|
+
this.options.onListening(this);
|
|
759
|
+
}
|
|
756
760
|
});
|
|
757
761
|
}
|
|
758
762
|
|
|
759
763
|
close(cb) {
|
|
760
764
|
this.sockets.forEach((socket) => {
|
|
761
|
-
|
|
765
|
+
this.socketServer.close(socket);
|
|
762
766
|
});
|
|
763
767
|
|
|
764
768
|
this.sockets = [];
|
|
@@ -901,25 +905,10 @@ class Server {
|
|
|
901
905
|
return false;
|
|
902
906
|
}
|
|
903
907
|
|
|
904
|
-
showStatus() {
|
|
905
|
-
const suffix =
|
|
906
|
-
this.options.inline !== false || this.options.lazy === true
|
|
907
|
-
? '/'
|
|
908
|
-
: '/webpack-dev-server/';
|
|
909
|
-
const uri = `${createDomain(this.options, this.listeningApp)}${suffix}`;
|
|
910
|
-
|
|
911
|
-
status(
|
|
912
|
-
uri,
|
|
913
|
-
this.options,
|
|
914
|
-
this.log,
|
|
915
|
-
this.options.stats && this.options.stats.colors
|
|
916
|
-
);
|
|
917
|
-
}
|
|
918
|
-
|
|
919
908
|
// eslint-disable-next-line
|
|
920
909
|
sockWrite(sockets, type, data) {
|
|
921
910
|
sockets.forEach((socket) => {
|
|
922
|
-
|
|
911
|
+
this.socketServer.send(socket, JSON.stringify({ type, data }));
|
|
923
912
|
});
|
|
924
913
|
}
|
|
925
914
|
|
|
@@ -1003,9 +992,9 @@ class Server {
|
|
|
1003
992
|
this.contentBaseWatchers.push(watcher);
|
|
1004
993
|
}
|
|
1005
994
|
|
|
1006
|
-
invalidate() {
|
|
995
|
+
invalidate(callback) {
|
|
1007
996
|
if (this.middleware) {
|
|
1008
|
-
this.middleware.invalidate();
|
|
997
|
+
this.middleware.invalidate(callback);
|
|
1009
998
|
}
|
|
1010
999
|
}
|
|
1011
1000
|
}
|
package/lib/options.json
CHANGED
|
@@ -195,6 +195,9 @@
|
|
|
195
195
|
"noInfo": {
|
|
196
196
|
"type": "boolean"
|
|
197
197
|
},
|
|
198
|
+
"onListening": {
|
|
199
|
+
"instanceof": "Function"
|
|
200
|
+
},
|
|
198
201
|
"open": {
|
|
199
202
|
"anyOf": [
|
|
200
203
|
{
|
|
@@ -294,6 +297,16 @@
|
|
|
294
297
|
"serveIndex": {
|
|
295
298
|
"type": "boolean"
|
|
296
299
|
},
|
|
300
|
+
"serverMode": {
|
|
301
|
+
"anyOf": [
|
|
302
|
+
{
|
|
303
|
+
"type": "string"
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"instanceof": "Function"
|
|
307
|
+
}
|
|
308
|
+
]
|
|
309
|
+
},
|
|
297
310
|
"serverSideRender": {
|
|
298
311
|
"type": "boolean"
|
|
299
312
|
},
|
|
@@ -391,8 +404,8 @@
|
|
|
391
404
|
"http2": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverhttp2)",
|
|
392
405
|
"https": "should be {Object|Boolean} (https://webpack.js.org/configuration/dev-server/#devserverhttps)",
|
|
393
406
|
"index": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserverindex)",
|
|
394
|
-
"injectClient": "should be {Boolean|Function}",
|
|
395
|
-
"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)",
|
|
396
409
|
"inline": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverinline)",
|
|
397
410
|
"key": "should be {String|Buffer}",
|
|
398
411
|
"lazy": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserverlazy-)",
|
|
@@ -402,6 +415,7 @@
|
|
|
402
415
|
"logTime": "should be {Boolean} (https://github.com/webpack/webpack-dev-middleware#logtime)",
|
|
403
416
|
"mimeTypes": "should be {Object} (https://webpack.js.org/configuration/dev-server/#devservermimetypes-)",
|
|
404
417
|
"noInfo": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devservernoinfo-)",
|
|
418
|
+
"onListening": "should be {Function} (https://webpack.js.org/configuration/dev-server/#onlistening)",
|
|
405
419
|
"open": "should be {String|Boolean} (https://webpack.js.org/configuration/dev-server/#devserveropen)",
|
|
406
420
|
"openPage": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserveropenpage)",
|
|
407
421
|
"overlay": "should be {Boolean|Object} (https://webpack.js.org/configuration/dev-server/#devserveroverlay)",
|
|
@@ -416,6 +430,7 @@
|
|
|
416
430
|
"reporter": "should be {Function} (https://github.com/webpack/webpack-dev-middleware#reporter)",
|
|
417
431
|
"requestCert": "should be {Boolean}",
|
|
418
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-)",
|
|
419
434
|
"serverSideRender": "should be {Boolean} (https://github.com/webpack/webpack-dev-middleware#serversiderender)",
|
|
420
435
|
"setup": "should be {Function} (https://webpack.js.org/configuration/dev-server/#devserversetup)",
|
|
421
436
|
"sockHost": "should be {String|Null} (https://webpack.js.org/configuration/dev-server/#devserversockhost)",
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/* eslint-disable
|
|
4
|
+
class-methods-use-this,
|
|
5
|
+
func-names
|
|
6
|
+
*/
|
|
7
|
+
const sockjs = require('sockjs');
|
|
8
|
+
const BaseServer = require('./BaseServer');
|
|
9
|
+
|
|
10
|
+
// Workaround for sockjs@~0.3.19
|
|
11
|
+
// sockjs will remove Origin header, however Origin header is required for checking host.
|
|
12
|
+
// See https://github.com/webpack/webpack-dev-server/issues/1604 for more information
|
|
13
|
+
{
|
|
14
|
+
// eslint-disable-next-line global-require
|
|
15
|
+
const SockjsSession = require('sockjs/lib/transport').Session;
|
|
16
|
+
const decorateConnection = SockjsSession.prototype.decorateConnection;
|
|
17
|
+
SockjsSession.prototype.decorateConnection = function(req) {
|
|
18
|
+
decorateConnection.call(this, req);
|
|
19
|
+
const connection = this.connection;
|
|
20
|
+
if (
|
|
21
|
+
connection.headers &&
|
|
22
|
+
!('origin' in connection.headers) &&
|
|
23
|
+
'origin' in req.headers
|
|
24
|
+
) {
|
|
25
|
+
connection.headers.origin = req.headers.origin;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = class SockJSServer extends BaseServer {
|
|
31
|
+
// options has: error (function), debug (function), server (http/s server), path (string)
|
|
32
|
+
constructor(server) {
|
|
33
|
+
super(server);
|
|
34
|
+
this.socket = sockjs.createServer({
|
|
35
|
+
// Use provided up-to-date sockjs-client
|
|
36
|
+
sockjs_url: '/__webpack_dev_server__/sockjs.bundle.js',
|
|
37
|
+
// Limit useless logs
|
|
38
|
+
log: (severity, line) => {
|
|
39
|
+
if (severity === 'error') {
|
|
40
|
+
this.server.log.error(line);
|
|
41
|
+
} else {
|
|
42
|
+
this.server.log.debug(line);
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
this.socket.installHandlers(this.server.listeningApp, {
|
|
48
|
+
prefix: this.server.sockPath,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
send(connection, message) {
|
|
53
|
+
connection.write(message);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
close(connection) {
|
|
57
|
+
connection.close();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// f should return the resulting connection
|
|
61
|
+
onConnection(f) {
|
|
62
|
+
this.socket.on('connection', f);
|
|
63
|
+
}
|
|
64
|
+
};
|
package/lib/utils/addEntries.js
CHANGED
|
@@ -72,6 +72,8 @@ function addEntries(config, options, server) {
|
|
|
72
72
|
const webTarget =
|
|
73
73
|
config.target === 'web' ||
|
|
74
74
|
config.target === 'webworker' ||
|
|
75
|
+
config.target === 'electron-renderer' ||
|
|
76
|
+
config.target === 'node-webkit' ||
|
|
75
77
|
config.target == null;
|
|
76
78
|
const additionalEntries = checkInject(
|
|
77
79
|
options.injectClient,
|