React.js Conf 2016 Quick Summaries — Day 2, Part 2

Feb 25, 2016 · 10 min read

I was lucky enough to attend React.js Conf 2016, and as presentation happened I jotted a few notes about each talk. These aren’t complete summaries and there will be errors in the notes, but hopefully they’ll point you in the right direction when deciding which talks to watch.

You can see the complete schedule here.

Thanks to inFlow Inventory for sponsoring my attendance.

Performance Without Compromise

Steve McGuire (Netflix)

Performance and declarative, functional programming are at odds in the minds of many developers. At Netflix, we have an especially challenging performance target to hit. This talk will explore how we managed to take an unflinching stand on a completely declarative React based architecture while maintaining 100ms key-input and 60fps on the 600mhz single-core devices in your living room.

We’ll talk about how and why we adhered to principles like no refs, no observation, no mixins or inheritance, immutable hierarchical state, declarative data via Falcor, and top-down-rendering. While some of these principles can actually help performance, we’ll share how we mitigated others in order to hit our tough performance targets without compromising.

  • How to deliver a performant UI without compromising on Netflix ideals
  • Netflix runs on wide array of devices, PS4, smart TVs, streaming sticks
  • $30 streaming device, 600mz, single core, JS core w/ no JIT, 465x slower than v8 on a laptop
  • Built Gibbon, no HTML or CSS, 60fps render loop
  • react-gibbon replaced gibbon specific with react fork, but base react-gibbon on react-native, could use for focus, animation, layout
  • Architecture principles: Unidirectional flow, composition over inheritance, always declarative APIs
  • Unidirectional Data Flow
  • Problem with observation: no flow of information, as async actions resolve there are race conditions that sometimes aren’t caught until production
  • Built a lightweight state component, immutable unified state that only re-render trees that change
  • No mixins, use higher order components
  • Mixins: application state and data management bring clashes, also no idea where methods come from
  • Higher order components flow from the outside in, much more clear ownership of data and methods
  • Refs vs declarative
  • Focus with refs don’t work if you add higher order components
  • Declarative focus, setting props instead means they can be passed down
  • No Refs, Ever
  • Performance: all the above is ambitious for a device that’s 465x slower than a laptop
  • Don’t get bogged down with optimizing, but measure a lot
  • Higher Order Components were expensive: a complete life cycle was 1.2ms per render, a plain no operation pass through, 6 HoC per list, 8 lists + ancestors = 60 ms of mandatory overhead
  • HoC, most of the time are doing reduce, map… giving context, componentWillReceiveProps is just a reduce
  • Transducers replace HoC
  • Transducers mitigate overhead, but not perfect No ‘this’ “merges” still cost time Maybe should have written a new component instead
  • performance wins were 50s
  • More gains: separate styles into dynamic and static styles, which skips the render if nothing changes
  • Custom Babel transform outputs static diff, only keys that change are compared
  • JSX is a very useful compiler hint, let you know that a diff is about to happen
  • Future work: static child diffing, flow gives info about the call graph of modules so possible fold this into Babel.js, maybe use JSX for fast merging
  • After above, 110ms
  • Babel element inline helped with performance, create element is very expensive, constructors are slow vs object literals because of prop copy
  • After inlining: 90ms
  • Succeeded in being pure and fast

A GraphQL Framework in Non-JS Servers

Syrus Akbary (Graphene)

Syrus asking us to cheer for his mom who was watching the live stream from Spain
  • dive into backend — frontend needs backend for data
  • Love story with GraphQL: the next big thing
  • How can manage backend code in Python for SEO rendering in React
  • Embed V8 engine inside their backend
  • Django application would pass props and use V8 engine to render
  • But this tied data to the component in the backend, especially if different components were rendered at the same route (mobile vs web layout)
  • Let client decide the data it needs: ie REST API
  • REST Limitations: different endpoints per types, HTTP latency, and pagination only works for top level resource
  • When a page is rendered, a page involves a bunch of different types, lot of networking effort, a FLUX store for each type is needed
  • Solution: Solve the HTTP problem, glue everything together in one API endpoint, but again sever needs to know the data the client needs
  • Falcor.js by Netflix vs GraphQL by Facebook
  • Falcor has an array of references
  • GraphQL requests using an empty object and server fills with data
  • GraphQL is a query language / Falcor is a library
  • Falcor response data is modeled as a graph, GraphQL is more like a tree
  • GraphQL allows introspection
  • GraphQL fields accept arguments
  • Chose GraphQL! But implementation was in JS and backend was in Python
  • ported GraphQL implementation into Python
  • Features: simple concise powerful, built in Relay support, well tested, 95% coverage
  • Community loves automatic mapping from Django Models, will work without rewriting
  • Most proud of Graphene playground
Graphene playground
  • Real world example: Star Wars API implementation in Graphene = 150 lines of code vs 2000 in JS
  • No Python? GraphQL is implemented in Ruby and others
  • GraphQL is much easier to maintain than REST APIs
  • 1 click documentation and UI by default (GraphiQL)
  • Quick integration with frontend thanks to Relay
  • Dev process is faster, leaner, just query from frontend, backend provides it
  • Resolver is a backend as a server as a service built on GraphQL
  • Parse+Firebase+GraphQL

Speeding up Startup for Large React Apps

Bhuwan Khattar (Facebook)

Applications inevitably get new features over time. While number of features might grow linearly, the increase in coupling across parts of the application is usually exponential and slows down app initialization and degrades performance. We obviously want richer applications, but not necessarily at the cost of performance.

Instead of compromising by choosing one over the other, we’ve been building abstractions and infrastructure to improve performance, even in the face of increasing complexity. By incrementally loading parts of our application and reducing work required for application initialization, we can significantly simplify and speed up startup. This talk explores some of Facebook’s efforts to make initialization faster for large and growing React applications.

  • JS apps in the browser are unique: have to Download, Parse and Execute an app every time a user tries to use an application
  • Not all JS modules are used for initial render
  • Use Route specific modules to split up app, but more routes, code sharing, branching dependencies means users download more than needed
  • Startup performance is important, but want features to increase. How to do this?
  • At Facebook have been building infrastructure to deal with this increasing complexity
  • First bottleneck is the downloading of JS, first goal is to minimize this
  • No one size solution, many factors contribute download (byte size, caching, number of files, http requests)
  • Reduce total byte size by breaking down modules into subsets which are non-overlapping, called a package
  • Each package is analyzed
  • Use Machine Learning to predict download: Historical data of which modules are used together
  • Designed for site-wide efficiency, so more used modules will have better download times
  • Which Modules are Used Together?
  • Static analysis, dependency graph isn’t helpful (testing features where users get one dep or another for instance)
  • Instead move the branching code of client side to server side, on server only one module is downloaded
  • Servers are used to improve client side perf
  • Instead of using JS modules to determine entry points, server determines javascript dependencies, but also allows streaming of data
  • Reduces module and data fetching, add this into one step on the server
  • Server rendering is not the answer to client side perf problems
  • Server rendering doesn’t solve the problem: request, server generates data by executing JS in the server, renders the markup, but the client also needs the JS to reconcile the state with the server
  • Server rendering is less efficient because of redundant work. Downloading more bytes, JS and markup are downloaded, worse time to start interaction
  • Minimize JS bytes to init the app by remove extraneous code that will never be needed by the client instead
  • Dependencies can be downloaded by intent instead. When a user shows that they want to perform an action, download JS then
  • Don’t require a dependency, require a loader that can fetch the dependency
  • <BootloadedComponent> abstracts away showing a spinner until component is downloaded

Route based branching

  • Static analysis can’t understand rendering only 1 component based on routes
  • Instead dependencies should be of the route, not of the branching component logic using a MatchRoute function which never includes route components as dependencies
  • Instead of requiring modules at the top of files, only require modules as they are called “inline requires”
  • Inline requires and lazy execution using module factories, ~10% reduction in initial JS execute and 2x faster tests
  • Lazy Execution trade-off: can’t rely on side effects, can defer execution until later and bottleneck then
  • Idle chunks between execution, take advantage of these gaps to eagerly require modules during this downtime

Rethinking All Practices: Building Applications in Elm

Jamison Dance (Kuali)

React re-thought best practices for web and native development, but it is limited by the strengths and weaknesses of JavaScript.

Elm takes rethinking best practices even further by asking what a modern language designed for productive development should look like.

Signals and the Elm Architecture help you compose large complex applications out of small, understandable pieces. Elm’s powerful type system and emphasis on pure functions and immutable data make refactoring and maintaining large applications faster and easier.

Elm and React share common ideas, and creating a new language helps Elm leverage those ideas in to a better development experience. Learn how Elm can make you a better React developer, and maybe, just maybe, take the plunge in to trying Elm yourself.

  • Isomorphic shouldn’t be used for server render javascript. Use Universal!
  • Elm is a functional programming language that transpiles to JS

undefined is not a function is the most JavaScript phrase

  • Type checkers are better than error catchers, but gradual type systems can be turned off
  • Code that is hard to type check is code that you will not type check and that code is the tricky part that needs it
  • Elm has no runtime errors, type system by default
  • There’s no such thing as `null` in Elm
  • `Maybe` type can be empty or have a value, so compiler knows when you are checking all code paths
  • Want the computer to the things it does well so you can do the things that you can do well.
  • There are patterns in JS, but nothing forces you to use them
  • Elm Architecture is similar to React, unidirectional data flow
  • Stateless functions are easier to test because same input always produces same output, but nothing forces you in JS to use stateless functions
  • Elm only has stateless functions
  • Elm type system will enforce this, side-effects throw errors
  • Constraints are better than guidelines — focus on your own application domain that are specific to your problems
  • But… early days for Elm: smaller community, no server side rendering
  • Browser apps are growing, JS is evolving, Elm is what JS community is evolving toward

Optimising React Native: Tools and Tips

Tadeu Zagallo (Facebook)

React Native has seen an impressive adoption since its open-sourcing. Our goal is to make it easier for developers to write awesome native apps and we believe that performance is a prerequisite for a great user experience. We’ll go over some of the tools that we use to find and fix performance issues in React Native code, and share some tips and optimisations that you can use to make your own apps faster.