Top Banner
The Case for React.js and ClojureScript Murilo Pereira @mpereira May 2, 2014
90

The Case for React.js and ClojureScript

Aug 28, 2014

Download

Software

Murilo Pereira

Sonian Tech Talk presentation given on may 2, 2014.

http://murilopereira.com/the-case-for-reactjs-and-clojurescript/
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: The Case for React.js and ClojureScript

The Case for

React.js andClojureScript

Murilo Pereira

@mpereira

May 2, 2014

Page 2: The Case for React.js and ClojureScript

Problem

Page 3: The Case for React.js and ClojureScript

Building UIs isdifficult.

Page 4: The Case for React.js and ClojureScript

Modern Web UIsvisual representations of data changing over timerespond to asynchronous user eventstransition both the underlying data and itself to new states

Page 5: The Case for React.js and ClojureScript

"Data changing over time is theroot of all evil."

Page 6: The Case for React.js and ClojureScript

Incidental ComplexityJavaScript isn't DOM is stateful

reactive

Page 7: The Case for React.js and ClojureScript

What if the JavaScript DOMAPI was reactive?

Page 8: The Case for React.js and ClojureScript

function tweetScore(tweet) { return(tweet.favorites_count + tweet.retweets_count);}

function compareTweetsByScore(a, b) { return(tweetScore(b) - tweetScore(a));}

function renderApplication(tweets) { return(document.dom.ul( { class: 'tweets' }, tweets .sort(compareTweetsByScore) .slice(0, 5) .map(function(tweet) { return(document.dom.li({ class: 'tweet' }, tweet.text); }) ));}

var tweets = fetchTweets({ username: 'mpereira' }, { limit: 20 });document.dom.render(renderApplication(tweets), document.body);

Page 9: The Case for React.js and ClojureScript

Possible solution: Data binding

Page 10: The Case for React.js and ClojureScript

Data BindingObservablesComputed properties

Backbone, Ember, Meteor, et al.

Page 11: The Case for React.js and ClojureScript

Contemporary data binding isnot simple.

Page 12: The Case for React.js and ClojureScript

SimpleNot to be mistaken for "easy"

Easiness = Familiarity (subjective)

Simplicity = "Does/is one thing" (objective)

Page 13: The Case for React.js and ClojureScript

Data BindingApplication logic entangled with observablesForces us to compose our programs with frameworkconstructs instead of language constructs (functions and datastructures)

Page 14: The Case for React.js and ClojureScript

"How often are you fighting theframework?"

Page 15: The Case for React.js and ClojureScript

Dirty-checking (Angular)Also susceptible to the problems of data binding.

Page 16: The Case for React.js and ClojureScript

https://docs.angularjs.org/guide/concepts

Page 17: The Case for React.js and ClojureScript

Complex

Page 18: The Case for React.js and ClojureScript

Even with shortcomings it'sstill possible to build complex,

modern UIs usingcontemporary MVC

frameworks.

Page 19: The Case for React.js and ClojureScript

"We can create precisely thesame programs we're creating

right now with drasticallysimpler tools."

Rich Hickey

Page 20: The Case for React.js and ClojureScript

A different solution to the sameproblem.

Page 21: The Case for React.js and ClojureScript

React.js

Page 22: The Case for React.js and ClojureScript

React.jsLibrary for creating UIsRenders the DOM and responds to user eventsCan be thought of as the V in MVC

Page 23: The Case for React.js and ClojureScript

Remember our utopic examplea few slides back?

Page 24: The Case for React.js and ClojureScript

function tweetScore(tweet) { return(tweet.favorites_count + tweet.retweets_count);}

function compareTweetsByScore(a, b) { return(tweetScore(b) - tweetScore(a));}

function renderApplication(tweets) { return(document.dom.ul( { class: 'tweets' }, tweets .sort(compareTweetsByScore) .slice(0, 5) .map(function(tweet) { return(document.dom.li({ class: 'tweet' }, tweet.text); }) ));}

var tweets = fetchTweets({ username: 'mpereira' }, { limit: 20 });document.dom.render(renderApplication(tweets), document.body);

Page 25: The Case for React.js and ClojureScript

It's actually valid React.js code

Page 26: The Case for React.js and ClojureScript

function tweetScore(tweet) { return(tweet.favorites_count + tweet.retweets_count);}

function compareTweetsByScore(a, b) { return(tweetScore(b) - tweetScore(a));}

function renderApplication(tweets) { return(React.DOM.ul( { className: 'tweets' }, tweets .sort(compareTweetsByScore) .slice(0, 5) .map(function(tweet) { return(React.DOM.li({ className: 'tweet' }, tweet.text); }) ));}

var tweets = fetchTweets({ username: 'mpereira' }, { limit: 20 });React.renderComponent(renderApplication(tweets), document.body);

Page 27: The Case for React.js and ClojureScript

React gives us a minimallyleaky abstraction for a reactiveJavaScript/DOM environment.

Page 28: The Case for React.js and ClojureScript

Data

Component

DOM

Page 29: The Case for React.js and ClojureScript

Model

View

DOM

Page 30: The Case for React.js and ClojureScript

M3

V2

DOM

M2 M4 M5M1

V1 V3

Page 31: The Case for React.js and ClojureScript

Data

C3

DOM

C4C2 C5C1

Page 32: The Case for React.js and ClojureScript

Components

Page 33: The Case for React.js and ClojureScript

ComponentsIdempotent functions that describe your

UI at any point in time.

Page 34: The Case for React.js and ClojureScript

component(data) = VDOM

Page 35: The Case for React.js and ClojureScript

component(data_1) = VDOM_1

*user input changes data from data_1 to data_2*

component(data_2) = VDOM_2diffVDOMs(VDOM_1, VDOM_2) = diffDOMOperations(diff) = operations

applyDOMOperations(operations, document.body)

Page 36: The Case for React.js and ClojureScript

Best part? You don't even haveto worry about this. Just build

components.

Page 37: The Case for React.js and ClojureScript

Every place data is displayed isguaranteed to be up-to-date. 

No need for KVO or markingHTML templates withframework directives.

Page 38: The Case for React.js and ClojureScript

Frees the programmer fromdoing manual, explicit DOM

operations.

Page 39: The Case for React.js and ClojureScript

But what about theperformance?

Isn't diffing VDOMs slow?

Why have VDOMs if thebrowser already has a DOM?

Page 40: The Case for React.js and ClojureScript

The DOM is slow.

Page 41: The Case for React.js and ClojureScript

The DOM is slowQuerying may require tree traversalMutations trigger viewport reflows, relayouts, repaints (CSSengine, etc.)Can also invalidate caches, requiring the entire DOM to bereconstructed on the viewport

Page 42: The Case for React.js and ClojureScript

Having in-memoryrepresentations of the DOM

allows React to have extremelyfast UIs.

Page 43: The Case for React.js and ClojureScript

Virtual DOM (VDOM)Allows for components to have a declarative APIPerforms the minimum amount of actual DOM operationsthrough computing diffsHandles DOM operations for you

Page 44: The Case for React.js and ClojureScript

"Performance isn't the [main]goal of the VDOM, but if you'reworried with performance,

most workloads are as fast orfaster [than the MVC

alternatives] out of the box."Pete Hunt

Page 45: The Case for React.js and ClojureScript

Components

Page 46: The Case for React.js and ClojureScript

Components allow you toexpress your program in thelanguage of your problem

domain.

Rather than on the language ofa particular framework.

Page 47: The Case for React.js and ClojureScript

Bill O'Reilly

Tide comes in, tide goes out.You can't explain that!

Top Tweets

Just had #breakfast.

@troll yes, definitely plan onthat.

pic.twitter.com/asd23 #selfie#instagram

Good# morning.

Page 48: The Case for React.js and ClojureScript

Bill O'Reilly

Top Tweets

Tide comes in, tide goes out.You can't explain that! #tides

Just had #breakfast.

@troll yes, definitely plan onthat.

pic.twitter.com/asd23 #selfie#instagram

Good# morning.

Header

Profile

Tweets

Top Tweets

Page 49: The Case for React.js and ClojureScript

var Profile = React.createClass({ render: function() { return(React.DOM.div(null, [ React.DOM.img(null, this.props.user.image), React.DOM.p(null, this.props.user.name) ]); }});

var Tweets = React.createClass({ render: function() { return(React.DOM.ul(null, this.props.tweets.map(function(tweet) { return(React.DOM.li(null, tweet.text)); }); }});

var TopTweets = React.createClass({ render: function() { return(React.DOM.div(null, [ React.DOM.h1(null, 'Top Tweets'), Profile({ user: this.props.user }), Tweets({ tweets: this.props.user.tweets }) ]); }});

React.renderComponent(TopTweets({ user: user }), document.body);

Page 50: The Case for React.js and ClojureScript

var Profile = React.createClass({ render: function() { return( <div> <img href={this.props.user.image} /> <p>{this.props.user.name}</p> </div> ); }});

var Tweets = React.createClass({ render: function() { return( <ul> {this.props.tweets.map(function(tweet) { return(<li>tweet.text</li>); })}; </ul> ); }});

var TopTweets = React.createClass({ render: function() { return( <div> <h1>Top Tweets</h1> <Profile user={this.props.user} /> <Tweets tweets={this.props.user.tweets} /> </div> ); }

Page 51: The Case for React.js and ClojureScript

TopTweets(data) = Header() + Profile(data_1) + Tweets(data_2)

Page 52: The Case for React.js and ClojureScript

Components are reusable andcomposable declarative

representations of your UI.

Page 53: The Case for React.js and ClojureScript

CollateralBenefits

Page 54: The Case for React.js and ClojureScript

Collateral BenefitsRender the application on the server (node.js, Java 8'sNashhorn, etc.)UI testability for freeNo templates!

Page 55: The Case for React.js and ClojureScript

React.js takeawaysDeclarative, fast UIsExpress your programs in the language of your problemdomain

Page 56: The Case for React.js and ClojureScript

ClojureScript

Page 57: The Case for React.js and ClojureScript

ProblemJavaScript sucks

We need JavaScript

Page 58: The Case for React.js and ClojureScript

JavaScript sucksNo integersNo module systemVerbose syntaxConfusing, inconsistent equality operatorsConfusing, inconsistent automatic operator conversionsLack of block scopeNon-uniform iteratorsGlobal variables by defaultNaNthisNo macros (yet...)etc.

Page 59: The Case for React.js and ClojureScript

We Need JavaScriptRuntime is everywhereRuntime is improving (Web Sockets, geo-location, FS API, RAF,push notifications, WebRTC, WebGL, SVG, Canvas, WebWorkers, IndexedDB, etc.)

Page 60: The Case for React.js and ClojureScript

Build better languages on topof JavaScript.

Page 61: The Case for React.js and ClojureScript

Compilers!Lots of them already existOnly a few bring significant improvements

Popular ones

CoffeeScript: mostly syntax sugarTypeScript: typed superset of JavaScript. Brings type checking,compile time errors

Page 62: The Case for React.js and ClojureScript

ClojureScript

Page 63: The Case for React.js and ClojureScript

ClojureScript is a Clojurecompiler that targets

JavaScript.

Page 64: The Case for React.js and ClojureScript

Why ClojureScript?Why Clojure?Why LISP?

Page 65: The Case for React.js and ClojureScript

Clojure is just a betterlanguage.

Page 66: The Case for React.js and ClojureScript

Number of daysspent designingthe language v1

JavaScript Clojure

Page 67: The Case for React.js and ClojureScript

ClojureScriptLISPSTMRuntime polymorphismThe REPLFunctional programmingImmutable data structuresUniform API over immutable data structuresMacrosLazy sequencesDestructuringState VS Identityetc.

Page 68: The Case for React.js and ClojureScript

core.async(go (try (let [tweets (<? (get-tweets-for "swannodette")) first-url (<? (expand-url (first (parse-urls tweets)))) response (<? (http-get first-url))] (. js/console (log "Most recent link text:" response))) (catch js/Error e (. js/console (error "Error with the twitterverse:" e)))))

Asynchronous Error Handling

Page 69: The Case for React.js and ClojureScript

The possibility of havingaccess to the power of Clojurein the browser is immensely

valuable.

Page 70: The Case for React.js and ClojureScript

ValueTo programmers, who will be able to build better programs, with

less bugs, faster.

To the people and companies who will benefit from thoseprograms.

Page 71: The Case for React.js and ClojureScript

The developer experience hasimproved significantly.

Page 72: The Case for React.js and ClojureScript

Developer ExperienceSource mapsEasily reproducible tutorialsBrowser-connected in-editor REPLsFast compilation cyclesCompatible libraries

Page 73: The Case for React.js and ClojureScript

Recommend you to check itout

(but you probably have, already)

Page 74: The Case for React.js and ClojureScript
Page 75: The Case for React.js and ClojureScript

Om

Page 76: The Case for React.js and ClojureScript

ClojureScript interface to React.

Page 77: The Case for React.js and ClojureScript

"Because of immutable dataOm can deliver even better

performance than React out ofthe box."

David Nolen

Page 78: The Case for React.js and ClojureScript

30-40X faster than JS MVCs nothing to do with ClojureScript. Ditch stateful objects, ditch events. Be declarative. Immutability. That's it.5:39 AM - 15 Dec 2013

David Nolen @swannodette

Follow

41 RETWEETS 39 FAVORITES

Page 79: The Case for React.js and ClojureScript

???

Page 80: The Case for React.js and ClojureScript

ClojureScriptCompiled, slower than hand-written JavaScriptUses immutable data structures, slower than JavaScript datastructures

And yet

Om's performance beats thatof most JavaScript MVC

frameworks

Page 81: The Case for React.js and ClojureScript

"Ideas have fundamentalperformance properties."

Pete Hunt

Page 82: The Case for React.js and ClojureScript

Immutable data structuresmake React's diffing algorithm

really smart.

Page 84: The Case for React.js and ClojureScript

Takeaways

Page 85: The Case for React.js and ClojureScript

"Ideas have fundamentalperformance properties."

Page 86: The Case for React.js and ClojureScript

"Don't trade simplicity forfamiliarity."

Page 87: The Case for React.js and ClojureScript

And  .give it five minutes

Page 88: The Case for React.js and ClojureScript

Thanks! @mpereira