FRONTEND AT SCALE Designing abstractions for big teams @joshduck
What front-end abstractions have we built? And how did we do it?
Server rendered desktop site
Less memory, bandwidth, and latency
Device constraints × More products × Multiple platforms × Product depth Lots of complexity
Product UI Product code Business logic UI rendering Web framework Common Runtimes infrastructure Data storage Hardware
Common infrastructure Products teams can focus on products We can chase long tail of optimizations Knowledge is transferable Shared tooling and processes
The right solution changes over time
Specialize
Specialize Simplify
Specialize Simplify Replace
Server rendering Goal: Turn data into markup Medium: Strings and concatenation
String escaping HTML syntax echo "<div class=\"dashboard-box\"> Hello, $name. </div>"; Cross-site scripting HTML tags
Object composition is better than string concatenation $welcome = new UIDashboard(); $welcome->setTitle('Hello, ' . $name); $welcome->setIcon('event'); $welcome->setContent($body); echo $welcome->render();
XHP is a DSL for components $welcome = <dashboard title={"Hello, $name"}> {$body} <button use="primary" /> </dashboard>;
XHP is a DSL for components $welcome = <dashboard title={"Hello, $name"}> {$body} <button use="primary" /> </dashboard>;
It's XHP all the way down 🐣 class :dashboard { function render() { return <card> <icon type={$this->icon} /> <div>{$this->:title}</div> </card>; } }
Components are a massive win for code quality They encourage engineers to create decoupled, reusable units of code
The pit of success
Retrofitting async rendering class :dashboard implements AsyncXHP { async function render() { $text = await getDashboard($this->:id); return <card>{$data->text}</card>; } }
A declarative interface leaves the door open for future changes
Client rendering Goal: Synchronizing state with a UI Medium: DOM nodes and APIs
{liked: } false
{liked: } true
{liked: } false
Bookkeeping DOM APIs var liked = false; var like = container.children[0]; var unlike = container.children[1]; container.addEventListener('click', (e) => { liked = !liked; like.style.display = liked ? 'none' : 'block'; unlike.style.display = liked ? 'block' : 'none'; }); Browser compatibility
jQuery simplifies the DOM APIs $('.like-button').click(function() { $(container).find('.like').toggle(); $(container).find('.unlike').toggle(); });
Initial render and updates share an API class LikeButton extends React.Component { render() { return this.state.liked ? <Button label ="Like" onClick ={...} /> <Button label ="Unlike" onClick ={...} /> } }
Good infra doesn't come from building in isolation
Work directly with product teams to understand their needs
Iterating on a core library is really, really hard Minimize public interfaces Update call sites alongside infra changes Use tooling to automate changes Deprecate, log, and monitor
React has gone places we never expected
State management Goal: Handling application state changes in a predictable way Medium: Object mutation and events
Stores Views Dispatcher
Alt Delorean Fluxy Material Flux Flummox Reflux Fluxible McFly OmniscientJS MartyJS Lux Flux This Fluxxor
Flux and Redux are still imperative Simplified mutations and events, but didn't replace them We couldn't iterate on implementation
Relay is a new approach to data management function Product(props) { return <li>{props.name} (AUD {props.price}) </li>; } Relay.createContainer(Product, { product: ` fragment { name, price, } `, });
Declarative Immutable Automated data fetching No manual object mutations Static analysis
Declarative code and static analysis play well together Extract data requirements as a build step Fetch data without running JavaScript Not possible with imperative code
Strings XHP DOM APIs jQuery React Ad hoc Flux Relay
Clearly define the problem space
Understand products' needs Start by working directly with a team You should be writing product code
Plan to iterate Build an escape hatch Support incremental adoption Iterate on the abstraction
Steal ideas that work One way data flow Declarative interfaces Immutability Functional programming Static analysis
Thank you @joshduck
Recommend
More recommend