Putting the "P"
in Preact
Background
Who is this guy
@_developit on Twitter
@developit on GitHub
Who is this guy
Background
- Building mobile web apps since iOS 1
- Actually earlier, Windows Mobile 5
- Written a bunch of UI frameworks
Background
Look familiar?
This code was
written in 2008.
Background
- "HTML5 OS"
- Carbyn
- custom DOM atop the real DOM
... in IE 8, iOS 4 🤡
(artistic liberty)
- Web Components
- Shadow DOM
- <style scoped>
- CSS animations
Background
Unnecessary Terminal
Unnecessary IDE
Unnecessary Email Client
Lessons
Invention and reinvention
can appear dangerously similar
Maintenance requires large
scope of understanding
When you over-abstract,
you get nothing for free
What if...
Instead of fighting the web,
we embraced it?
Idea
Preact
Summer 2015
Origins
- remembered: hyperscript
Accidentally wrote another template engine
Sad me
Hyperscript
<div id="one">
Hello
</div>
<Foo hello />
h('div', { id:'one' },
'Hello'
);
h(Foo, { hello: true })
Remember hyperscript?
It's behind everything now
JSX
From blog post "WTF is JSX"
// a "partial" that does a filtered loop
function foo(items) {
return items.map( p => <li>{p}</li> );
}
let vdom = (
<div id="foo">
<p>Look, a simple JSX DOM renderer!</p>
<ul>{ foo(ITEMS) }</ul>
</div>
)
document.body.appendChild( render(vdom) );
I created Preact
to teach myself
how React worked
Preact
- started out as a CodePen
- animating hundreds of elements
- obsessively profiled & tracked FPS
- rapidly tested out ideas
- recycling for memory usage?
- cache props on DOM elements?
- cache normalized nodeName?
- cost of attributes vs properties
Paul Lewis (@aerotwist)
Pot Stirrer
"React + Performance = ?"
I wonder...
Results
Decent
Surprisingly Decent
Debounced rendering
Preact
Turns out,
Preact works a lot like Paul's Vanilla JS baseline.
Preact
- hey, that's a tiny, simplified React!
- added support for "transient" components
- started adding React-isms:
- stateful components (classes)
- lifecycle methods
- compositional components
- refs
- context
this was super
annoying to do
Paul Lewis
...again!
"The Cost of Frameworks"
It seems to me that developer ergonomics should be less important than our users’ needs.
Preact
- Small modules / publish all the things
- Needed a catchy name
- All the good ones taken
Performance
Just keep profiling
Performance
- Chrome Dev Tools Timeline, so good
Something to obsess over.
Performance
- IRHydra2
- @mraleph
- see how/why
- shows deopts
git.io/hydraosx
making changes
based on actual data
YOU
Lessons from IRHydra
- monomophism
- guard property access
- inline helpers
- short-circuit / fast path
- when in doubt: benchmark!
Monomorphism
monomorphic
fn({ a: 1 })
fn({ a: 2 })
megamorphic
fn({ a: 1, b: 2 })
fn({ b: 2, a: 1 })
fn('a', 1)
fn(div)
fn(span)
polymorphic
fn({ a: 1 })
fn({ b: 2 })
fn({ a: 1 })
fn({ a: 1 }, 1)
best
worst
better
fn = o => o.a
Guard Property Access
Help your friendly engine out a bit:
let value = typeof dom.key!=='undefined' && dom.key
// don't write this:
if (obj.props)
// if you mean this:
if (typeof obj.props!=='undefined')
could be 0, '', null...
Inline Helpers
Functions can know too much.
function hook(obj, name, a, b) {
return obj[name] && obj[name](a, b);
}
hook(obj, 'foo', 1, 2);
obj.foo(1, 2);
deopt after a few different values
has its own inline cache
Short-Circuitting
The cheapest function call
is the one you never make
- unknown
Benchmark!
Monomorphic
Guarded property access
*here be dragons
Quick DOM Tips
- 💯 Text.nodeValue
- 🍲 Batch writes
- 📚 Avoid reads
- 🎤 Avoid Live NodeLists
requestAnimationFrame
setTimeout
MutationObserver
Promise.then()
Today
Today
- a growing community
- expanding focus to Developer Experience
- lots of discussion & contribution
- in use at many companies
Use-Cases
- Self-contained web widgets / embeds
- Progressive Web Apps
- Pieces of an existing application
- Component-by-component migration
- Web Components
Non-Use-Cases
- React Native
- Alternative Renderers
- Certain 3rd-party libs
- Uncomfortable with the DOM
New Use-Cases
Fin
Putting the "P" in Preact
By developit
Putting the "P" in Preact
- 4,015