Making Generated JavaScript Inline-Caching Friendly in ReScript
In this post, I want to explain how ReScript (formerly BuckleScript) improves JavaScript performance by using type information to generate predictable runtime representations.
Modern JavaScript engines like V8 heavily optimize based on object shapes. When those shapes stay consistent, engines can apply inline caching, which leads to significant performance gains.
ReScript leans into this by ensuring the JavaScript it generates is both idiomatic and engine-friendly.
Why Encoding Matters
JavaScript engines optimize property access based on how objects look at runtime.
If object shapes change often:
- Inline caches break
- Property access slows down
- Debugging becomes harder
ReScript avoids this by guaranteeing:
- Similar data always has the same shape
- Variant representations are predictable
- Generated JavaScript remains readable
Record Encoding (Stable Objects)
Records in ReScript compile directly to JavaScript objects.
Example ReScript record:
1type int64 = { loBits: int [@bs.as "lo"], hiBits: int [@bs.as "hi"] }
2let value = { hiBits: 33, loBits: 32 }
3let sum = ({ loBits, hiBits }) => loBits + hiBitsGenerated JavaScript looks like:
1var value = { lo: 32, hi: 33 }
2function sum(param) { return param.lo + param.hi }Why this works well:
- Object shapes are consistent
- Property names are stable
- Debuggers show meaningful structures
Variant Encoding (Tagged Unions)
Variants are encoded using different strategies depending on whether they carry data.
Variants Without Payload
These compile to simple numbers.
Rescript:
1type color = | Red | Blue | GreenGenerated JavaScript:
1Red = 0, Blue = 1, Green = 2This representation is compact and fast.
Variants With Payload
Variants that carry data compile to objects with a stable layout.
ReScript:
1type tree = | Empty | Node(tree, int, tree)
2let t = Node(Empty, 3, Empty)Generated JavaScript:
1var t = { TAG: 0, _0: 0, _1: 3, _2: 0 }Each object:
- Uses the same fields
- Preserves stable shapes
- Works well with inline caching
Optimized Variant Encoding (Single Payload)
When only one variant carries data, ReScript skips the TAG field entirely.
ReScript:
1type list = | Nil | Cons(int, list)
2let xs = Cons(1, Nil)Generated JavaScript:
1var xs = { _0: 1, _1: 0 }This reduces object size while keeping pattern matching predictable.
List Encoding for Debugging
Lists can also be encoded using clearer field names:
1{ hd: 1, tl: { hd: 2, tl: { hd: 3, tl: 0 } } }This improves debuggability while remaining efficient for JavaScript engines.
Polymorphic Variants
Polymorphic variants also generate stable shapes.
ReScript:
1let v = `hello(3)Generated JavaScript:
1var v = { HASH: someNumber, VAL: 3 }These shapes remain consistent and engine-optimizable.
Final Thoughts
ReScript’s approach to encoding data is about more than performance. It also improves:
- Debugging experience
- Predictability
- Confidence in refactors
By combining strong typing with JavaScript-friendly output, ReScript produces code that runs fast and stays understandable.
This balance is what makes ReScript especially appealing for long-lived, production frontend systems.