React has just announced the release of React Fiber!
Is Fiber ready yet?— React (@reactjs) July 26, 2017
We'd say yes. 😀 Just released a beta of React 16! https://t.co/4DZ5DD9mcF 🎉
Just today Brian Vaughn has published an official note on GitHub giving all installation instructions, requirement descriptions, and an overview on what React 16 mean for developers. Unfortunately, it does not support async rendering yet. According to Brian:
"This initial React 16.0 release is mostly focused on compatibility with existing apps. It does not enable asynchronous rendering yet. We will introduce an opt-in to the async mode later during React 16.x. We don't expect React 16.0 to make your apps significantly faster or slower, but we'd love to know if you see improvements or regressions."
Fiber is a complete rewrite of React’s core, aimed at improving UI responsiveness and perceived performance for end-users. Even though React is a convenient framework for developers, it is the users and their experience from using the app that counts the most - and sometimes, especially on lower-end devices, React apps can simply seem slow for them. React Fiber aims to improve this situation by rethinking how and when the user interface should be updated, ultimately making your apps seem much faster and more responsive to users.
Before we jump into details on how this is done, here are some key facts about React Fiber:
- Research on React Fiber began in 2015, with the first experimental version released in 2016.
- Fiber introduces ground-up support for scheduling, along with several other new features.
- The stable version of Fiber will be introduced in React 16.0, which should be out this summer.
- React Fiber will be backwards-compatible with existing React apps.
- Public APIs won’t change.
- Fiber is already being used in production on Facebook.
“(React Fiber) improves perceived performance and responsiveness for complex react applications” - Lin Clark during React Conf 2017
Smarter, not faster
First and foremost - with Fiber, the React team did not aim to make the framework faster but to improve what makes the user interface feel smooth and responsive. Depending on the way the user interacts with an app, there is a certain threshold to UI response time above which the app seems slow:
- For things like gestures and animations, the feedback should be the fastest - around 16 ms to provide a smooth 60 FPS experience.
- Clicks or taps have a bigger margin of perceived responsiveness - around 80 to 150 ms.
- For interaction involving network activity, the UI updates can take even longer to still seem responsive - for example, search boxes with server-side autocomplete can wait with rendering the results until the user stops typing.
- For elements which are not visible to the user at a certain time - for example, below the fold on a scrollable list or in another tab within the app - the updates can be deferred until the user actually needs to see those elements.
The main performance-related issue that the React team set out to tackle with Fiber is scheduling - that is, determining when computations should be performed. In client-side frameworks like React, recursive calls to component lifecycle methods can block the browser’s main thread, leading to laggy UI performance. To solve this problem, two things can be done:
- The work done by the framework needs to be split into smaller chunks to let the browser’s main thread do its work in between them, making the framework more responsive to browser events.
- UI updates need to be prioritized, so that those affecting perceived performance the most (such as animations) happen before less important ones (e.g. updates to off-screen elements).
So, how does Fiber achieve this?
You may already know that depending on the underlying platform, React uses different renderers to display UI elements, such as the DOM renderer for browsers, or the Native renderer for mobile apps. However, there is some platform-independent logic shared between all renderers that takes care of computing which parts of a UI tree need to be changed (also known as “diffing”) - this common part is called the reconciler. React Fiber reimplements the reconciler using data structures called fibers to keep track of where it is in the tree.
In React Fiber, the rendering process has been split into two phases:
- Reconcile - building up the work-in-progress tree and figuring out the list of changes, but not actually performing them changes yet
- Commit - performing the changes in the DOM (or native UI)
The reconciliation phase can be interrupted to let the browser’s main thread do its work with the help of a relatively new browser API called requestIdleCallback. This allows the main thread to notify React when it has spare processing time. For older browsers, React includes a polyfill of the requestIdleCallback API, so compatibility shouldn’t be an issue. This API is also implemented in React Native, so native mobile apps can benefit from Fiber’s scheduling improvements as well.
New priorities - “fast” things first
In addition to breaking up work into smaller pieces, which makes React more responsive to browser events, Fiber assigns different priorities to different types of UI updates - those more critical to the perceived performance. UI updates such as animations are assigned higher priority and can pause other in-progress updates. The higher-priority update is then reconciled and committed, after which the lower-priority ones continue, reusing previously completed work if possible.
Apart from built-in scheduling, React Fiber brings smaller bundle sizes, better codebase approachability thanks to Flow typing, better error boundaries, more descriptive errors, and the ability to return arrays and strings from render functions.
Fiber, which will be introduced in React 16.0, will be backwards-compatible with existing React apps. Despite the fact it is a complete rewrite, public APIs will stay the same. You can check React Fiber’s status on http://isfiberreadyyet.com/ - event though it is still not 100% ready, it is already being used by Facebook on their main page.