FRONTEND AT SCALE Designing abstractions for big teams @joshduck - - PowerPoint PPT Presentation
FRONTEND AT SCALE Designing abstractions for big teams @joshduck - - PowerPoint PPT Presentation
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
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
Hardware Data storage Web framework UI rendering Business logic Runtimes
Common infrastructure
Product UI
Product code
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
Simplify Specialize Replace
Turn data into markup Strings and concatenation Goal: Medium:
Server rendering
String escaping Cross-site scripting HTML syntax HTML tags
echo "<div class=\"dashboard-box\"> Hello, $name. </div>";
$welcome = new UIDashboard(); $welcome->setTitle('Hello, ' . $name); $welcome->setIcon('event'); $welcome->setContent($body); echo $welcome->render();
Object composition is better than string concatenation
$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>;
XHP is a DSL for components
class :dashboard { function render() { return <card> <icon type={$this->icon} /> <div>{$this->:title}</div> </card>; } }
It's XHP all the way down 🐣
Components are a massive win for code quality
They encourage engineers to create decoupled, reusable units of code
The pit of success
class :dashboard implements AsyncXHP { async function render() { $text = await getDashboard($this->:id); return <card>{$data->text}</card>; } }
Retrofitting async rendering
A declarative interface leaves the door open for future changes
Synchronizing state with a UI DOM nodes and APIs Goal: Medium:
Client rendering
{liked: } false
{liked: } true
{liked: } false
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'; });
DOM APIs Browser compatibility Bookkeeping
$('.like-button').click(function() { $(container).find('.like').toggle(); $(container).find('.unlike').toggle(); });
jQuery simplifies the DOM APIs
class LikeButton extends React.Component { render() { return this.state.liked ? <Button label="Like" onClick={...} /> <Button label="Unlike" onClick={...} /> } }
Initial render and updates share an API
Good infra doesn't come from building in isolation
Work directly with product teams to understand their needs
Minimize public interfaces Update call sites alongside infra changes Use tooling to automate changes Deprecate, log, and monitor
Iterating on a core library is really, really hard
React has gone places we never expected
Handling application state changes in a predictable way Object mutation and events Goal: Medium:
State management
Stores Views Dispatcher
Flummox Alt Fluxxor McFly Lux Delorean Reflux Material Flux MartyJS Fluxible Flux This OmniscientJS Fluxy
Flux and Redux are still imperative
Simplified mutations and events, but didn't replace them We couldn't iterate on implementation
function Product(props) { return <li>{props.name} (AUD {props.price}) </li>; } Relay.createContainer(Product, { product: ` fragment { name, price, } `, });
Relay is a new approach to data management
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
One way data flow Declarative interfaces Immutability Functional programming Static analysis
Steal ideas that work
Thank you
@joshduck