Make Downloading JavaScript Cool Again
@liamzebedee | liamz.co
v2 - evolved from presenting at TBD Hackathon + Web3 Summit Berlin
Distributing apps on the web is like sending the bible for every single church reading
Bundles > 2MB
Recent innovations:
Webpack
Yarn / NPM united packages
React
Styled-components
PWA’s
The future
Edge computing
Bundle identifiers (2abd79e7d9fg.js) and c-hash-ing
SplitChunks
Static analysis of dependencies into a graph
Split out into many <script src=> and load async
Minimization (FooBar -> a.b)
Prefetch/preload
HTTP2 Push
Problems:
Small changes => more download => less battery life (mobile)
Download a whole lot more than I need to
We don’t really cache code on webpages, so reloads are always slow
Oppportunity:
XKCD (web is instant apps) - AR etc.
WebAssembly structured stack machine
P2P CDN’s?
Deliver code for execution
What if we downloaded only what changed?
How?
Naive approach: delta
Knowledge of \( C_t \) for \( 0..t \)
Problem: How can we synchronise state without high bandwidth usage?
We already compare the hashes of assets, but this is for the entire file. Can we do it on a more granular scale
Merkle tree (popularised in blockchain world)
A tree data structure
Where every non-leaf node is hash of its children
Compilers turn code into lower-level code. Example:
// Compile JSX (React syntax) to JS (vanilla JavaScript)
//
source = fs.readFile('something.jsx')
// export default const blah = () => {
// return <div>Hello world</div>;
// }
compiled = runLoaders(src)
// module.exports = function blah() {
// return React.createElement('div', { children: "Hello world" })
// }
Compilation:
What does that look like?
function shout() {
console.log("BLOCKCHAIN!");
}
// AST
Function [name=shout]
Call [name=console.log]
Literal ["BLOCKCHAIN!"]
// Merkle AST
42
123
543
function shout() {
console.log("BLOCKCHAIN!");
}
// AST
Function [name=shout]
Call [name=console.log]
Literal ["BLOCKCHAIN!"]
// Merkle AST
42
123
543
function shout() {
console.log("BLOCKCHAIN!", "IOT!");
}
// AST
Function [name=shout]
Call [name=console.log]
Literal ["BLOCKCHAIN!"]
Literal ["IOT!"]
// Merkle AST
86
99
543
264
*changed
Send client tree to server, compare the Merkle AST's
86*
99*
543
264*
Client
42
123
543
Server
86
99
543
264
What's changed?
Send client to server, compare the Merkle AST's
86*
99*
543
264*
Client
42
123
543
Server
86
99
543
264
What's changed?
We send only the diffs to the client
We send only the diffs to the client
They patch their source
And run the bundle
Wishlist: deliver binary AST's
Let's cache things inversely proportional to how often they're required
e.g. React is loaded almost every day by FB/Netflix, so it never escapes the cache
Why? Web is the biggest distributed consensus-driven open platform we have.
Let's make mobile web apps INSTANT to load.
feature-complete MVP, for client/server in TypeScript. E2E testing/stats with Puppeteer.
Let's make dApps better and the web a competitive pressure on mobile
TODO:
Need to start tracking bundles over time to collect stats