Skip to content

Commit 7632956

Browse files
refactor: transportMode and client URL options (#3260)
1 parent 8283a97 commit 7632956

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1796
-1489
lines changed

lib/Server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ class Server {
580580

581581
if (!headers) {
582582
this.logger.warn(
583-
'transportMode.server implementation must pass headers to the callback of onConnection(f) ' +
583+
'webSocketServer implementation must pass headers to the callback of onConnection(f) ' +
584584
'via f(connection, headers) in order for clients to pass a headers security check'
585585
);
586586
}

lib/options.json

Lines changed: 69 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,46 @@
139139
}
140140
},
141141
"additionalProperties": false
142+
},
143+
"WebSocketServerEnum": {
144+
"enum": ["sockjs", "ws"]
145+
},
146+
"WebSocketServerString": {
147+
"type": "string",
148+
"minLength": 1
149+
},
150+
"WebSocketServerFunction": {
151+
"instanceof": "Function"
152+
},
153+
"WebSocketServerObject": {
154+
"type": "object",
155+
"properties": {
156+
"type": {
157+
"anyOf": [
158+
{
159+
"$ref": "#/definitions/WebSocketServerEnum"
160+
},
161+
{
162+
"$ref": "#/definitions/WebSocketServerString"
163+
},
164+
{
165+
"$ref": "#/definitions/WebSocketServerFunction"
166+
}
167+
]
168+
},
169+
"options": {
170+
"type": "object",
171+
"additionalProperties": true
172+
}
173+
},
174+
"additionalProperties": false
175+
},
176+
"ClientTransportEnum": {
177+
"enum": ["sockjs", "ws"]
178+
},
179+
"ClientTransportString": {
180+
"type": "string",
181+
"minLength": 1
142182
}
143183
},
144184
"properties": {
@@ -157,6 +197,17 @@
157197
"client": {
158198
"type": "object",
159199
"properties": {
200+
"transport": {
201+
"anyOf": [
202+
{
203+
"$ref": "#/definitions/ClientTransportEnum"
204+
},
205+
{
206+
"$ref": "#/definitions/ClientTransportString"
207+
}
208+
],
209+
"description": "Allows to set custom transport to communicate with server."
210+
},
160211
"host": {
161212
"type": "string",
162213
"description": "Tells clients connected to devServer to use the provided host."
@@ -177,7 +228,7 @@
177228
"enum": ["auto"]
178229
}
179230
],
180-
"description": "Tells clients connected to devServer to use the provided port."
231+
"description": "Tells clients connected to devServer to use the provided path to connect."
181232
},
182233
"logging": {
183234
"enum": ["none", "error", "warn", "info", "log", "verbose"],
@@ -234,6 +285,23 @@
234285
"description": "Specifies client properties. https://webpack.js.org/configuration/dev-server/#devserverclient",
235286
"additionalProperties": false
236287
},
288+
"webSocketServer": {
289+
"anyOf": [
290+
{
291+
"$ref": "#/definitions/WebSocketServerEnum"
292+
},
293+
{
294+
"$ref": "#/definitions/WebSocketServerString"
295+
},
296+
{
297+
"$ref": "#/definitions/WebSocketServerFunction"
298+
},
299+
{
300+
"$ref": "#/definitions/WebSocketServerObject"
301+
}
302+
],
303+
"description": "Allows to set web socket server and options."
304+
},
237305
"compress": {
238306
"type": "boolean",
239307
"description": "Enable gzip compression for everything served. https://webpack.js.org/configuration/dev-server/#devservercompress"
@@ -487,33 +555,6 @@
487555
],
488556
"description": "It is possible to configure advanced options for serving static files from directory. See the Express documentation for the possible options. https://webpack.js.org/configuration/dev-server/#devserverstatic"
489557
},
490-
"transportMode": {
491-
"anyOf": [
492-
{
493-
"type": "object",
494-
"properties": {
495-
"client": {
496-
"type": "string"
497-
},
498-
"server": {
499-
"anyOf": [
500-
{
501-
"type": "string"
502-
},
503-
{
504-
"instanceof": "Function"
505-
}
506-
]
507-
}
508-
},
509-
"additionalProperties": false
510-
},
511-
{
512-
"enum": ["sockjs", "ws"]
513-
}
514-
],
515-
"description": "This option allows us either to choose the current devServer transport mode for client/server individually or to provide custom client/server implementation. https://webpack.js.org/configuration/dev-server/#devservertransportmode"
516-
},
517558
"watchFiles": {
518559
"anyOf": [
519560
{

lib/servers/SockJSServer.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,17 @@ module.exports = class SockJSServer extends BaseServer {
4949
},
5050
});
5151

52+
const getPrefix = (options) => {
53+
if (typeof options.prefix !== 'undefined') {
54+
return options.prefix;
55+
}
56+
57+
return options.path;
58+
};
59+
5260
this.socket.installHandlers(this.server.server, {
53-
prefix: this.server.options.client.path,
61+
...this.server.options.webSocketServer.options,
62+
prefix: getPrefix(this.server.options.webSocketServer.options),
5463
});
5564
}
5665

lib/servers/WebsocketServer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ module.exports = class WebsocketServer extends BaseServer {
1111
super(server);
1212

1313
this.webSocketServer = new ws.Server({
14+
...this.server.options.webSocketServer.options,
1415
noServer: true,
15-
path: this.server.options.client.path,
1616
});
1717

1818
this.server.server.on('upgrade', (req, sock, head) => {

lib/utils/DevServerPlugin.js

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,40 @@ class DevServerPlugin {
3030

3131
/** @type {string} */
3232
const domain = createDomain(options);
33+
34+
// SockJS is not supported server mode, so `host` and `port` can't specified, let's ignore them
35+
// TODO show warning about this
36+
const isSockJSType = options.webSocketServer.type === 'sockjs';
37+
3338
/** @type {string} */
34-
const host =
35-
options.client && options.client.host
36-
? `&host=${options.client.host}`
37-
: '';
39+
let host = '';
40+
41+
if (options.client && options.client.host) {
42+
host = `&host=${options.client.host}`;
43+
} else if (options.webSocketServer.options.host && !isSockJSType) {
44+
host = `&host=${options.webSocketServer.options.host}`;
45+
}
46+
3847
/** @type {string} */
39-
let path = '';
48+
let port = '';
4049

41-
// only add the path if it is not default
42-
if (
43-
options.client &&
44-
options.client.path &&
45-
options.client.path !== '/ws'
46-
) {
47-
path = `&path=${options.client.path}`;
50+
if (options.client && options.client.port) {
51+
port = `&port=${options.client.port}`;
52+
} else if (options.webSocketServer.options.port && !isSockJSType) {
53+
port = `&port=${options.webSocketServer.options.port}`;
54+
} else {
55+
port = `&port=${options.port}`;
4856
}
4957

5058
/** @type {string} */
51-
const port =
52-
(options.client && options.client.port) || options.port
53-
? `&port=${options.client.port || options.port}`
54-
: '';
59+
let path = '';
60+
61+
// Only add the path if it is not default
62+
if (options.client && options.client.path && options.client.path) {
63+
path = `&path=${options.client.path}`;
64+
} else if (options.webSocketServer.options.path) {
65+
path = `&path=${options.webSocketServer.options.path}`;
66+
}
5567

5668
/** @type {string} */
5769
const logging =
@@ -61,7 +73,7 @@ class DevServerPlugin {
6173

6274
/** @type {string} */
6375
const clientEntry = `${require.resolve(
64-
'../../client/'
76+
'../../client/index.js'
6577
)}?${domain}${host}${path}${port}${logging}`;
6678

6779
/** @type {(string[] | string)} */

lib/utils/getSocketClientPath.js

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,48 @@
22

33
function getSocketClientPath(options) {
44
let ClientImplementation;
5-
let clientImplFound = true;
5+
let clientImplementationFound = true;
66

7-
switch (typeof options.transportMode.client) {
7+
const isKnownWebSocketServerImplementation =
8+
typeof options.webSocketServer.type === 'string' &&
9+
(options.webSocketServer.type === 'ws' ||
10+
options.webSocketServer.type === 'sockjs');
11+
12+
let clientTransport;
13+
14+
if (typeof options.client.transport !== 'undefined') {
15+
clientTransport = options.client.transport;
16+
} else if (isKnownWebSocketServerImplementation) {
17+
clientTransport = options.webSocketServer.type;
18+
}
19+
20+
switch (typeof clientTransport) {
821
case 'string':
922
// could be 'sockjs', 'ws', or a path that should be required
10-
if (options.transportMode.client === 'sockjs') {
23+
if (clientTransport === 'sockjs') {
1124
ClientImplementation = require('../../client/clients/SockJSClient');
12-
} else if (options.transportMode.client === 'ws') {
25+
} else if (clientTransport === 'ws') {
1326
ClientImplementation = require('../../client/clients/WebsocketClient');
1427
} else {
1528
try {
1629
// eslint-disable-next-line import/no-dynamic-require
17-
ClientImplementation = require(options.transportMode.client);
30+
ClientImplementation = require(clientTransport);
1831
} catch (e) {
19-
clientImplFound = false;
32+
clientImplementationFound = false;
2033
}
2134
}
2235
break;
2336
default:
24-
clientImplFound = false;
37+
clientImplementationFound = false;
2538
}
2639

27-
if (!clientImplFound) {
40+
if (!clientImplementationFound) {
2841
throw new Error(
29-
"transportMode.client must be a string denoting a default implementation (e.g. 'sockjs', 'ws') or a full path to " +
30-
'a JS file which exports a class extending BaseClient (webpack-dev-server/client-src/clients/BaseClient) ' +
31-
'via require.resolve(...)'
42+
`${
43+
!isKnownWebSocketServerImplementation
44+
? 'When you use custom web socket implementation you must explicitly specify client.transport. '
45+
: ''
46+
}client.transport must be a string denoting a default implementation (e.g. 'sockjs', 'ws') or a full path to a JS file which exports a class extending BaseClient (webpack-dev-server/client-src/clients/BaseClient.js) via require.resolve(...)`
3247
);
3348
}
3449

lib/utils/getSocketServerImplementation.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,36 @@
22

33
function getSocketServerImplementation(options) {
44
let ServerImplementation;
5-
let serverImplFound = true;
6-
switch (typeof options.transportMode.server) {
5+
let ServerImplementationFound = true;
6+
7+
switch (typeof options.webSocketServer.type) {
78
case 'string':
89
// could be 'sockjs', in the future 'ws', or a path that should be required
9-
if (options.transportMode.server === 'sockjs') {
10+
if (options.webSocketServer.type === 'sockjs') {
1011
ServerImplementation = require('../servers/SockJSServer');
11-
} else if (options.transportMode.server === 'ws') {
12+
} else if (options.webSocketServer.type === 'ws') {
1213
ServerImplementation = require('../servers/WebsocketServer');
1314
} else {
1415
try {
1516
// eslint-disable-next-line import/no-dynamic-require
16-
ServerImplementation = require(options.transportMode.server);
17+
ServerImplementation = require(options.webSocketServer.type);
1718
} catch (e) {
18-
serverImplFound = false;
19+
ServerImplementationFound = false;
1920
}
2021
}
2122
break;
2223
case 'function':
23-
// potentially do more checks here to confirm that the user implemented this properlly
24-
// since errors could be difficult to understand
25-
ServerImplementation = options.transportMode.server;
24+
// Potentially do more checks here to confirm that the user implemented this properly since errors could be difficult to understand
25+
ServerImplementation = options.webSocketServer.type;
2626
break;
2727
default:
28-
serverImplFound = false;
28+
ServerImplementationFound = false;
2929
}
3030

31-
if (!serverImplFound) {
31+
if (!ServerImplementationFound) {
3232
throw new Error(
33-
"transportMode.server must be a string denoting a default implementation (e.g. 'ws', 'sockjs'), a full path to " +
34-
'a JS file which exports a class extending BaseServer (webpack-dev-server/lib/servers/BaseServer) ' +
33+
"webSocketServer (webSocketServer.type) must be a string denoting a default implementation (e.g. 'ws', 'sockjs'), a full path to " +
34+
'a JS file which exports a class extending BaseServer (webpack-dev-server/lib/servers/BaseServer.js) ' +
3535
'via require.resolve(...), or the class itself which extends BaseServer'
3636
);
3737
}

0 commit comments

Comments
 (0)