Skip to content

Commit eecc1e4

Browse files
knagaitsevevilebottnawi
authored andcommitted
refactor: insert client implementation from within Dev Server API (#1933)
1 parent 6973e4c commit eecc1e4

File tree

9 files changed

+226
-12
lines changed

9 files changed

+226
-12
lines changed

client-src/default/socket.js

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
'use strict';
22

3-
const SockJS = require('sockjs-client/dist/sockjs');
3+
/* global __webpack_dev_server_client__ */
4+
/* eslint-disable
5+
camelcase
6+
*/
7+
const Client = __webpack_dev_server_client__;
48

59
let retries = 0;
6-
let sock = null;
10+
let client = null;
711

812
const socket = function initSocket(url, handlers) {
9-
sock = new SockJS(url);
13+
client = new Client(url);
1014

11-
sock.onopen = function onopen() {
15+
client.onOpen(() => {
1216
retries = 0;
13-
};
17+
});
1418

15-
sock.onclose = function onclose() {
19+
client.onClose(() => {
1620
if (retries === 0) {
1721
handlers.close();
1822
}
1923

2024
// Try to reconnect.
21-
sock = null;
25+
client = null;
2226

2327
// After 10 retries stop trying, to prevent logspam.
2428
if (retries <= 10) {
@@ -32,15 +36,14 @@ const socket = function initSocket(url, handlers) {
3236
socket(url, handlers);
3337
}, retryInMs);
3438
}
35-
};
39+
});
3640

37-
sock.onmessage = function onmessage(e) {
38-
// This assumes that all data sent via the websocket is JSON.
39-
const msg = JSON.parse(e.data);
41+
client.onMessage((data) => {
42+
const msg = JSON.parse(data);
4043
if (handlers[msg.type]) {
4144
handlers[msg.type](msg.data);
4245
}
43-
};
46+
});
4447
};
4548

4649
module.exports = socket;

lib/clients/BaseClient.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
/* eslint-disable
4+
no-unused-vars
5+
*/
6+
module.exports = class BaseClient {
7+
static getClientPath(options) {
8+
throw new Error('Client needs implementation');
9+
}
10+
};

lib/clients/SockJSClient.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
/* eslint-disable
4+
no-unused-vars
5+
*/
6+
const SockJS = require('sockjs-client/dist/sockjs');
7+
const BaseClient = require('./BaseClient');
8+
9+
module.exports = class SockJSClient extends BaseClient {
10+
constructor(url) {
11+
super();
12+
this.sock = new SockJS(url);
13+
}
14+
15+
static getClientPath(options) {
16+
return require.resolve('./SockJSClient');
17+
}
18+
19+
onOpen(f) {
20+
this.sock.onopen = f;
21+
}
22+
23+
onClose(f) {
24+
this.sock.onclose = f;
25+
}
26+
27+
// call f with the message string as the first argument
28+
onMessage(f) {
29+
this.sock.onmessage = (e) => {
30+
f(e.data);
31+
};
32+
}
33+
};

lib/clients/WebsocketClient.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
const BaseClient = require('./BaseClient');
4+
5+
module.exports = class WebsocketClient extends BaseClient {};

lib/utils/updateCompiler.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
const webpack = require('webpack');
88
const addEntries = require('./addEntries');
9+
const SockJSClient = require('./../clients/SockJSClient');
910

1011
function updateCompiler(compiler, options) {
1112
if (options.inline !== false) {
@@ -48,6 +49,11 @@ function updateCompiler(compiler, options) {
4849
compilers.forEach((compiler) => {
4950
const config = compiler.options;
5051
compiler.hooks.entryOption.call(config.context, config.entry);
52+
53+
const providePlugin = new webpack.ProvidePlugin({
54+
__webpack_dev_server_client__: SockJSClient.getClientPath(options),
55+
});
56+
providePlugin.apply(compiler);
5157
});
5258

5359
// do not apply the plugin unless it didn't exist before.

test/SockJSClient.test.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
'use strict';
2+
3+
const http = require('http');
4+
const express = require('express');
5+
const sockjs = require('sockjs');
6+
const SockJSClient = require('../lib/clients/SockJSClient');
7+
8+
describe('SockJSClient', () => {
9+
let socketServer;
10+
let listeningApp;
11+
12+
beforeAll((done) => {
13+
// eslint-disable-next-line new-cap
14+
const app = new express();
15+
listeningApp = http.createServer(app);
16+
listeningApp.listen(8080, 'localhost', () => {
17+
socketServer = sockjs.createServer();
18+
socketServer.installHandlers(listeningApp, {
19+
prefix: '/sockjs-node',
20+
});
21+
done();
22+
});
23+
});
24+
25+
describe('client', () => {
26+
it('should open, recieve message, and close', (done) => {
27+
socketServer.on('connection', (connection) => {
28+
connection.write('hello world');
29+
setTimeout(() => {
30+
connection.close();
31+
}, 1000);
32+
});
33+
const client = new SockJSClient('http://localhost:8080/sockjs-node');
34+
const data = [];
35+
client.onOpen(() => {
36+
data.push('open');
37+
});
38+
client.onClose(() => {
39+
data.push('close');
40+
});
41+
client.onMessage((msg) => {
42+
data.push(msg);
43+
});
44+
setTimeout(() => {
45+
expect(data.length).toEqual(3);
46+
expect(data[0]).toEqual('open');
47+
expect(data[1]).toEqual('hello world');
48+
expect(data[2]).toEqual('close');
49+
done();
50+
}, 3000);
51+
});
52+
});
53+
54+
afterAll((done) => {
55+
listeningApp.close(() => {
56+
done();
57+
});
58+
});
59+
});

test/e2e/ProvidePlugin.test.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
'use strict';
2+
3+
const testServer = require('../helpers/test-server');
4+
const config = require('../fixtures/provide-plugin-config/webpack.config');
5+
const runBrowser = require('../helpers/run-browser');
6+
7+
describe('ProvidePlugin', () => {
8+
describe('inline', () => {
9+
beforeAll((done) => {
10+
const options = {
11+
port: 9000,
12+
host: '0.0.0.0',
13+
inline: true,
14+
watchOptions: {
15+
poll: true,
16+
},
17+
};
18+
testServer.startAwaitingCompilation(config, options, done);
19+
});
20+
21+
afterAll(testServer.close);
22+
23+
describe('on browser client', () => {
24+
jest.setTimeout(30000);
25+
26+
it('should inject SockJS client implementation', (done) => {
27+
runBrowser().then(({ page, browser }) => {
28+
page.waitForNavigation({ waitUntil: 'load' }).then(() => {
29+
page
30+
.evaluate(() => {
31+
return window.injectedClient === window.expectedClient;
32+
})
33+
.then((isCorrectClient) => {
34+
expect(isCorrectClient).toBeTruthy();
35+
browser.close().then(done);
36+
});
37+
});
38+
page.goto('http://localhost:9000/main');
39+
});
40+
});
41+
});
42+
});
43+
44+
describe('not inline', () => {
45+
beforeAll((done) => {
46+
const options = {
47+
port: 9000,
48+
host: '0.0.0.0',
49+
inline: false,
50+
watchOptions: {
51+
poll: true,
52+
},
53+
};
54+
testServer.startAwaitingCompilation(config, options, done);
55+
});
56+
57+
afterAll(testServer.close);
58+
59+
describe('on browser client', () => {
60+
jest.setTimeout(30000);
61+
62+
it('should not inject client implementation', (done) => {
63+
runBrowser().then(({ page, browser }) => {
64+
page.waitForNavigation({ waitUntil: 'load' }).then(() => {
65+
page
66+
.evaluate(() => {
67+
// eslint-disable-next-line no-undefined
68+
return window.injectedClient === undefined;
69+
})
70+
.then((isCorrectClient) => {
71+
expect(isCorrectClient).toBeTruthy();
72+
browser.close().then(done);
73+
});
74+
});
75+
page.goto('http://localhost:9000/main');
76+
});
77+
});
78+
});
79+
});
80+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict';
2+
3+
const SockJSClient = require('../../../lib/clients/SockJSClient');
4+
5+
window.expectedClient = SockJSClient;
6+
// eslint-disable-next-line camelcase, no-undef
7+
window.injectedClient = __webpack_dev_server_client__;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
module.exports = {
4+
mode: 'development',
5+
context: __dirname,
6+
entry: './foo.js',
7+
output: {
8+
path: '/',
9+
},
10+
node: false,
11+
};

0 commit comments

Comments
 (0)