My initial hunch is no. A server has to have everything ready for all users. As node is a single threaded process, it could reduce experience for other users (not just the current one). Besides, Meteor does not take that much memory so we can say that itās free server-side. Also, every time you update the server, you risk having to re-upload all the libs again.
Wow, that sounds great!
Regarding import(...) on the server: I think it would be useful to support this for code that is shared between client and server, e.g., for Meteor methods:
I would expect this to work everywhere. On the client, big-module.js would be loaded from a separate bundle and on the server, await import(...) would be similar to require.
Absolutely amazing work @klaussner. With all the work from @benjamnās, the TC39 discussions and so on, it looks like you guys are nearer to solve the puzzle than ever beforeā¦
But maybe I can give another perspective to code splitting:
I think we can all agree on that loading big modules asynchronously (in a browser env) is one of the biggest weaknesses of Meteorās build system compared to Webpack at the moment, right?
But for me, far more important than loading ./big-module.js would be loading complete packages like āmeteor/big-local-atmosphere-packageā or ābig-npm-packageā.
Doesnāt Package.js already provide us with all the needed information for code splitting like which module to rely strong/weak on and which deps just to use? If you look at rocket.chat or other big meteor projects, what is currently developed with the āumbrellaā package approach is basically a folder-based recipe on how to split the app into logical modules perfect for code splitting, or am I wrong?
Personally I think loading something from packages/ in an async way would be extremely valuable than just loading a file in the project dir. I know, MDG wants to move away from Atmosphere in the long term, but when it comes to splitting a webapp into big modules I think the whole npm link / eslint / babel compile horror is just not worth the time so people start to structure their app inside the imports/ directory just because they fear that local atmosphere packages get deprecated in the future
Oh, and thatās what I also found googling around / some literature:
@benjamn, are we waiting for tc39 proposal to firm up before we implement? I am super excited about this. Not only for our apps, but for Meteor as a whole. The build system is a key advantage.
Also, since we are in the process of adding it as a new feature, I would love if we could properly support service workers. What I mean: if a bundle has not changed, why change its name / hash and force a reload? Keep as-is so the client loads it from the cache. Only change names of bundles that indeed have a change.
This would be a game-changer for Meteor and the ecosystem. As it makes apps loading very smart, only loading what physically has changed.
Iām working on support for dynamic import(...) as we speak!
If all goes according to plan, the next 1.4.3 beta will include a working prototype. Thatās part of why there hasnāt been a 1.4.3 beta in a little while.
Because import(...) is asynchronous, it definitely seems amenable to service worker-based caching. However, thereās no necessary reason fetching modules has to happen via HTTP (Iām currently planning to do it over a web socket), so the service workers API might not be the only option for async module caching. There are multiple places we could intercept module fetching for caching purposes, even if we didnāt have service workers.
hey benjamin, thatās SO COOL! Iām just wondering if thereās a way to define how things get built with Meteor? I had to get off Meteor recently and go to Webpack unfortunately because creating a Chrome extension with Meteor was difficult. Code splitting in Meteor really excites me, would love to get back to Meteor in the future with this progress
I think it can be hard to find the client-side build output of a Meteor app since itās hidden away inside various directories, did you try loading that JS file into an extension?
I think using Meteor to build client-only JS bundles should be possible but probably harder than it could be since itās not the main focus.
Youāre getting at some interesting tradeoffs that Iām happy to discuss.
In short, the server-side logic for resolving dependencies of requested modules is more complex than a traditional CDN or proxy can understand. At best, the client could ask the module server for a set of module URLs to fetch, then fetch those modules via HTTP (with traditional caching). However, that would involve extra round trips, which is something Iām hoping to avoid.
The good news:
Previously fetched modules will be cached in IndexedDB (or local storage) on the client, so the module server can avoid sending back unchanged module code.
The module server will be stateless (clients tell the server what dynamic modules they already have), so you could (in principle) run multiple instances of the module server and load balance between them. In fact, scaling to additional containers on Galaxy will spread the load automatically.
The module server sends back exactly the modules the client needs, rather than sending back pre-built bundles. Bundles are easier to cache on a CDN, but you would need a combinatorial explosion of bundles to eliminate any duplication of modules between bundles.
In the future, HTTP/2 Server Push might be a good way to implement dynamic module delivery, but itās not required by the current implementation, and it seems unnecessarily complicated for what Iām trying to do.
Hope this is implemented in meteor as itās default behavior, right know meteor loads a massive js even if you donāt navigate to all the pages so a lot of js gets unused
Hey @benjamn, your work on support for dynamic import(...) is open source?
Iāll love to have a look on what youāre doing and perhaps help in some way.
Thank you.
Exception while invoking method 'dynamicRemove' TypeError: Collection.remove is not a function
I20170330-08:21:35.310(7)? at [object Object]._callee$ (imports/modules/dynamicRemove.js:24:27)
I20170330-08:21:35.310(7)? at tryCatch (/Users/theara/Desktop/meteor-app/react-material/node_modules/regenerator-runtime/runtime.js:64:40)
I20170330-08:21:35.311(7)? at GeneratorFunctionPrototype.invoke [as _invoke] (/Users/theara/Desktop/meteor-app/react-material/node_modules/regenerator-runtime/runtime.js:299:22)
I20170330-08:21:35.313(7)? at GeneratorFunctionPrototype.prototype.(anonymous function) [as next] (/Users/theara/Desktop/meteor-app/react-material/node_modules/regenerator-runtime/runtime.js:116:21)
I20170330-08:21:35.313(7)? at tryCatch (/Users/theara/Desktop/meteor-app/react-material/node_modules/regenerator-runtime/runtime.js:64:40)
I20170330-08:21:35.314(7)? at invoke (/Users/theara/Desktop/meteor-app/react-material/node_modules/regenerator-runtime/runtime.js:154:20)
I20170330-08:21:35.315(7)? at /Users/theara/Desktop/meteor-app/react-material/node_modules/regenerator-runtime/runtime.js:164:13
I20170330-08:21:35.315(7)? at /Users/theara/.meteor/packages/promise/.0.8.8.1mes7d8++os+web.browser+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:32:39