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)
This commit is contained in:
Ben Newman
2017-12-03 11:12:20 -05:00
parent bfbb8baf5f
commit 9424bf08c3
3 changed files with 11 additions and 5 deletions

View File

@@ -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`.

View File

@@ -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 => {

View File

@@ -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 });