$30 off During Our Annual Pro Sale. View Details »

Why does React scale? - JSConf 2014

vjeux
May 29, 2014
2M

Why does React scale? - JSConf 2014

vjeux

May 29, 2014
Tweet

Transcript

  1. Why does React scale?
    Christopher “vjeux” Chedeau

    View Slide

  2. min(Time To Find Root Cause)
    We want to reduce the number of bugs in the system but it’s not really actionable

    Instead, we found that focusing on minimizing the time to find the root cause of bugs

    was a better proxy to meet our goal

    View Slide

  3. Everytime you start the process of fixing a bug is by reproducing it

    For example, in this case there’s only one todo item but the count says 2

    View Slide

  4. Once you have a repro case, you want to know what code was being used to generate this value

    To do that, you are going to right-click/inspect element and look at it in the browser

    Then, you’re going to find something as unique as possible and grep it on your entire codebase

    It’s a bit of an hit & miss process, sometimes “todo-count” will give you the right code, sometimes not

    View Slide

  5. To make it easier and faster, we introduced React dev tools. This gives you the React component

    that was used to generate it. Since at Facebook, all the React components are uniquely named,

    you can directly open the file and be set. Dev tools are also really nice as you can live update

    props on state on the right panel

    View Slide

  6. Once you found the variable, you need to understand why it doesn’t have the value you’d expect.

    When I ask people what their workflow is, they usually tell me that they use a debugger, and when

    I watch over their shoulder I cry deep inside

    View Slide

  7. Debugger
    • Forward in time
    • Execute every lines
    Developer
    • Backward in time
    • Jump to updates
    The issue with debuggers is that they are not really useful for this use case. We are at the end of the

    execution and we want to know what happened to that variable in the past so that it got assigned this value

    Also, the debugger is executing every single line, but you want to jump directly to the place the variable got modified

    View Slide

  8. Local Variable
    Current Function

    !
    < 100 lines
    There are few different types of variables in a React application. If you are dealing with a local variable,

    then it is easy, you can just scroll up and see how it is being modified

    View Slide

  9. State
    Entire Codebase

    !
    (a lot of lines)
    If it is a state variable and you are not taking special care, then your search space is basically the entire

    code base. This was the source of soooo many issues at Facebook that in React we decided to treat it

    in a special way.

    View Slide

  10. State
    Entire Codebase

    !
    (a lot of lines)
    Owned by the Component

    !
    1 file

    < 1000 lines
    We imposed one constraint on state variables is that they belong to a component, and only the

    component can modify them. This greatly reduce the search space to just one file

    View Slide

  11. State
    Entire Codebase

    !
    (a lot of lines)
    Owned by the Component

    !
    1 file

    < 1000 lines
    getInitialState()

    setState()

    !
    < 10 lines
    Still, one file is pretty big. We restricted state updates further so that you can only modify them

    via two functions: getInitialState() and setState(). Since there are only a couple of call sites in

    a file, it’s now very tractable for a developer

    View Slide

  12. Immutable

    !
    0 lines
    Props
    The other special variable in React is props. This is a value being passed by your parent.

    One fundamental concept is that it is immutable, therefore you just have to look for its call site

    View Slide

  13. Immutable

    !
    0 lines
    Props
    Call sites

    !
    1-100 files
    If you are into a normal component, you shouldn’t have more than a couple of call sites,

    but if you are looking at a core component, then it can get in the dozens or hundreds and become

    hard to identify which one it is

    View Slide

  14. Immutable

    !
    0 lines
    Props
    Call sites

    !
    1-100 files
    Automatically inherit props


    Call sites

    and their call sites

    and … .
    If you have to pass a props from a grand parent to a child, then it starts adding a bit of boilerplate.

    Many people ask us why we don’t implement props that are automatically inherited like scope in Angular.

    The reason is that you now have to check all the possible ancestors of your component which can be a —lot— of files

    And as a corollary, when you want to update one of the top level files, it’s really hard to know all the components

    that depends on it, and therefore test them all to make sure your fix worked

    View Slide

  15. Immutable

    !
    0 lines
    Props
    Call sites

    !
    1-100 files
    Dev Tools

    !
    1 file
    Luckily for us, we don’t need to track down all the call sites, we can use again the dev tools

    in order to find the call site, we just have to press `up` :)

    View Slide

  16. Prop Types
    We introduced typing annotations which is something really uncommon in a JS library

    View Slide

  17. Prop Types
    C++ – auto keyword
    Static Languages Dynamic Languages
    JavaScript – TypeScript
    PHP – Hack
    Write More Types
    Write Less Types
    If we take a minute to look at programming languages in general, it starts to make sense

    Static languages are trying to make you write less types whereas dynamic languages want

    you to write more types

    View Slide

  18. Prop Types
    Sweet Spot

    !
    Type only function arguments

    !
    component props
    It turns out that they both converge into a place where we are typing function arguments.

    If you think about it, a React component can be seen as a function and its props as arguments.

    So it actually makes sense to type props

    View Slide

  19. Prop Types
    Exceptions do not propagate

    !
    1 hop
    The first use case of adding type annotations is for documentation. You can just read that file and

    know what it is expected to take as arguments. The second one is that it prevents errors for propagating.

    JavaScript doesn’t throw very often and your value is going to be able to go many levels deep before throwing

    an exception. The farther you are from the original error the more hops you’re going to have to do and

    the harder it’s going for you to trace back the error as the code is going to be unrelated

    View Slide

  20. jQuery?
    jQuery
    React
    JSX
    Someone asked me on twitter if we could support jQuery way of building virtual DOM nodes.

    We support two DSLs natively and CoffeeScript & ClojureScript communities came up with several others.

    However, jQuery has a very different property, it doesn’t come with a way to say that the node is completed

    View Slide

  21. Mutable
    call(element)

    !
    the entire call tree
    Because anybody can modify the element after it was created, then whenever you pass it to a function

    you have no idea if that function is going to modify it or not. Meaning that you’ve got to check the entire

    call tree. This was a major source of bug at Facebook

    View Slide

  22. Immutable
    Yet, it’s still valuable to be able to modify an element after it’s been created. So we introduced the API

    cloneWithProps. The important detail is that it returns a new object instead of modifying the existing one

    View Slide

  23. Immutable
    var modified = call(element)

    !
    only this pattern
    Which means that if you call a function with an element, if it modifies it, then it needs to return it.

    Since 99% of the time it doesn’t modify it, then you can skip a large numbers of calls when troubleshooting.

    This is also a good example of using immutability in JS and not some very different language such as lisp or haskell

    View Slide

  24. • Move Fast & Break Things
    • But fix it before it goes to prod!
    Conclusion
    We’ve got a moto at Facebook which is Move fast & break thing. The other side of that sentence is that

    we invest a lot in detection and once known, we need to be able to fix it fast, and hopefully before the users

    can see it. Again, we don’t know how to make it faster but we can make it more predictable.

    View Slide

  25. • Unpredictability #1: Finding the root cause
    • Unpredictability #2: Not introducing another bug with your fix
    Conclusion
    The first source of unpredictability is finding the root cause of the bug, but we covered this in the talk.

    Then, you need to come up with a fix, in practice as engineers this is what we do best.

    Finally, the worst thing you can do is to come up with a fix that causes another bug. It turns out that all the

    steps we did to improve tracing back when a variable was modified also helps when making a change to make

    sure that it doesn’t introduce unintended side effects

    View Slide

  26. Questions?
    Christopher “vjeux” Chedeau

    View Slide