Not including SockJS in the modern JS bundle was a nice bundle size
savings (28KB before gzip), but SockJS works better than a native
WebSocket for clients that are stuck in unusual networking situations, and
the fallback of using dynamic import() to load SockJS when the native
WebSocket failed was much slower than simply including SockJS in the
bundle and using it from the start.
Moreover, the new `meteor create --minimal` starter app does not use
socket-stream-client (nor DDP), so going back to including SockJS in both
the modern and the legacy bundles should have no impact on the minimal
modern bundle size.
If you want to continue using a native WebSocket instead of SockJS, you
can always pin the older version of the socket-stream-client package:
meteor add socket-stream-client@0.2.1
Thanks to bug reports from @jamesmillerburgess, in Meteor 1.6.1-rc.4 we
reverted a change that unsuccessfully attempted to remove SockJS from the
JS bundle (and instead injected a <script> tag to load SockJS in older
browsers): 365804218f
With this commit, we are once again attempting to exclude SockJS from the
JS bundle for modern browsers, this time taking advantage of the
web.browser.legacy system to control which browsers receive which bundle.
The definition of a "modern" browser is stricter now (essentially, any
browser with native async/await support), so I'm hopeful that browsers
with incomplete WebSocket support will get the legacy bundle, which
includes SockJS.
However, if there are still bugs in modern browsers due to faulty
WebSocket message compression (for example), we should be able to address
those problems directly, rather than reverting this change yet again.
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)
Although it was tempting to avoid including the SockJS library in the
bundle for modern browsers, Meteor 1.6.2 will have a much better way of
managing this kind of differential bundling for modern/legacy browsers
(see PR #9439), and removing SockJS seems to lead to a worse experience
when native WebSockets end up failing, as @jamesmillerburgess discovered:
https://github.com/meteor/meteor/pull/9274#issuecomment-356214405
https://github.com/meteor/meteor/pull/9274#issuecomment-355241004
The `Error in connection establishment: net::ERR_CONNECTION_REFUSED`
message will still repeat every few seconds, but devtools should coalesce
it into a single line with an incrementing counter, as before.
This is a back-port of a similar change on the web.browser.legacy branch:
b8601d3ce7
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)