From 9424bf08c3c4fcaa6ac847c8a0deec68d2d5f007 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Sun, 3 Dec 2017 11:12:20 -0500 Subject: [PATCH] Try loading SockJS dynamically after native WebSocket errors. To save size in modern browsers, JavaScript bundles built for the web.browser architecture no longer statically include the SockJS library. That's safe as long as native WebSockets actually work, but what if there's a problem with the network that necessitates falling back to long-polling or some other SockJS strategy? In those cases, we can load SockJS using a dynamic import(), which is a little slower than including it in the bundle, but that's OK because the module will be permanently cached in IndexedDB in production, and falling back to SockJS should be rare in modern browsers anyway. Note that this trick would not be possible if the implementation of dynamic import() still required a socket connection! (#9384) --- packages/modern-browsers/TODO.md | 2 +- packages/socket-stream-client/browser.js | 13 +++++++++---- packages/socket-stream-client/package.js | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/modern-browsers/TODO.md b/packages/modern-browsers/TODO.md index 4f51149f8d..cf25a4b75a 100644 --- a/packages/modern-browsers/TODO.md +++ b/packages/modern-browsers/TODO.md @@ -25,7 +25,7 @@ - [x] Use `web.browser.legacy` to handle SockJS instead. -- [ ] Load `SockJS` using dynamic `import()` if necessary in modern +- [x] Load `SockJS` using dynamic `import()` if necessary in modern `web.browser` clients. - [ ] Use different plugins in babel-compiler for `web.browser.legacy`. diff --git a/packages/socket-stream-client/browser.js b/packages/socket-stream-client/browser.js index 237a928804..93210be961 100644 --- a/packages/socket-stream-client/browser.js +++ b/packages/socket-stream-client/browser.js @@ -184,11 +184,16 @@ export class ClientStream extends StreamClientCommon { }; this.socket.onclose = () => { - if (this.lastError) { - this._lostConnection(this.lastError); - } else { + Promise.resolve( + // If the socket is closing because there was an error, and we + // didn't load SockJS before, try loading it dynamically before + // retrying the connection. + this.lastError && + ! hasSockJS && + import("./sockjs-0.3.4.js") + ).done(() => { this._lostConnection(); - } + }); }; this.socket.onerror = error => { diff --git a/packages/socket-stream-client/package.js b/packages/socket-stream-client/package.js index fb16c92066..b06f4a81b6 100644 --- a/packages/socket-stream-client/package.js +++ b/packages/socket-stream-client/package.js @@ -14,6 +14,7 @@ Package.onUse(function(api) { api.use("ecmascript"); api.use("modern-browsers"); api.use("retry"); // TODO Try to remove this. + api.use("dynamic-import"); api.addFiles("sockjs-0.3.4.js", "web.browser.legacy"); api.mainModule("browser.js", "client", { lazy: true });