Skip to content

v0.9.1

Latest
Compare
Choose a tag to compare
@pemrouz pemrouz released this 26 Mar 03:31
· 2 commits to master since this release

Notable Changes

Automatic Push (Basic React Example)

In an ideal world, a developer could just start writing and running code like:

import foo from './foo.js'

However, the browser would fetch ./foo.js, parse it, before it realises it needs ./bar.js to evaluate, and then make another round-trip to the server to get ./bar.js (repeating for each dependency). This is why ES Modules as the runtime format is not suitable in production, without a co-operating server.

In terms of user experience, the current practice of bundling is too coarse-grained, not dedupeable and results in over-fetching as too much code is loaded before use. In terms of developer experience, it's purely an unnecessary cognitive and resource overhead, especially if they try to split the bundles themselves.

In v9, Ripple will now automatically push dependencies for a resource.

In terms of user experience, this results in the theoretical upper bound for performance. If you request a resource with dependencies, only a single round-trip will be made. Since we are just dealing with finer-grained units (modules), this means we can dedupe, get more cache hits, and only pull deltas for what we don't already have. As a user interacts with your site, the module map starts to get populated. It may be for example they visited some pages that already loaded moment and lodash, and by the time they go to the next page that needs those, there will be zero network interactions, resulting in a much more app-like experience - i.e. dynamically streaming and populating the module cache as needed achieves a performance profile static bundles fundamentally cannot (for both start and continued interaction with your site). It allows naturally enables interleaving and progressive rendering without having to think about it.

In terms of developer experience, this completely eliminates the need for a product developer to think about the entire issue or spend any time on it. They don't have to create bundles ever again, think about how best to split them, and not only do they not have to worry about performance, they can rest assured users will get the best performance that is theoretically possible. This approach also scales with size: you can start hacking together a few modules and just fire up a server, or you can have an enterprise application that spans many teams and a million modules, and also just fire up the same server. Since there is no build step between authoring modules and seeing the results, it means much faster iterations too. There is no dependency hell issues as JavaScript developers have come to expect, and deduping is already handled by how npm installs dependencies.

Check out the minimal example here

  • In the future:
    • This is currently working for CommonJS, since that's what the world is using right now. Support for ESM will also be added. This is fairly trivial to do now but the plan was to wait for an unflagged version of node that natively supports ESM first. Since it now seems that will take some time, support for ES modules will be added sooner.
    • The primary concern is still getting things right, before fine-tuning for absolute performance. After ESM, performance screws will be tightened and an updated version of the loading 10k modules challenge will be published.
    • Reinvestigate HTTP/2 + Push as the underlying transport mechanism: However every time I have looked at this it doesn't seem quite right. Given more recent discussions around HTTP/2 Push, it seems like more people are realising that is not a panacea that will just fix everything.
    • The offline module caches resources and boots from those before any network interaction even happens, greatly improving the perceived startup time for repeat loads. This has been removed for now and will be refactored to use the new Cache API instead (also revisiting Service Workers).
    • Server-side rendering would also improve perceived startup time.