Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Native Fabric (UI-Layer Re-architecture) #4

Open
kelset opened this issue Jul 31, 2018 · 138 comments
Open

React Native Fabric (UI-Layer Re-architecture) #4

kelset opened this issue Jul 31, 2018 · 138 comments

Comments

@kelset
Copy link
Member

@kelset kelset commented Jul 31, 2018

Intro

With this issue I'd like to try and create a "one stop" for all the information available around the future re-architecture of the UI-Layer of React Native, codenamed "Fabric".

Terminology

  • JSI: JavaScript Interface, it's a unified lightweight general purpose API for (theoretically) any JavaScript virtual machine. It enables every other piece of the rearchitecture. (dedicated issue)
  • TurboModules: re-architecture of NativeModules, also using JSI. (dedicated issue)
  • CodeGen: a tool to "automate" the compatibility between JS and native side. (dedicated issue)

TL;DR

From @axe-fb's blogpost, here's a temporary description of Fabric (please consider that this is not yet finalized, it may change in the future)

In the current architecture, all UI operations (like creating native views, managing children, etc). are handled by a native module called UIManagerModule. The React Reconciller sends UI commands over the bridge, which are eventually handled by this module and delegated to UIImplementation. This in turn creates shadow nodes that represent the layout tree and are passed to Yoga to determine the relative co-ordinates based on the Flex box styles that are passed in from JS.
In the new system, the UI operations are directly exposed to JavaScript as functions using the JSI interface described above. The new UI manager can then create ComponentDescriptors and the Shadow Nodes for specific view types (like Text, View or Images), and then communicate with Java/ObjC to draw platform specific UI.

Available Materials

It was first announced in the "State of React Native 2018" blogpost by @sophiebits.

In July, @hramos linked a broadcast of a tech talk that happened in FB, which covered the ongoing work on the new React Native architecture codenamed "Fabric": facebook.com/hramos/videos/10101317533036249 (go to 8:18 for the presentation start - audio is a bit bad)

Further down the line, it was presented at ChainReact Conf 2018 by @axe-fb in the talk "The State of React Native".

At ReactConf 2018 @axe-fb did a talk about React Native's New Architecture, which also explains the 3 concepts above: JSI, Fabric, TurboModule.

On twitter, @shergin shared a presentation about View Flattening -> https://twitter.com/shergin/status/1058393187079704576?s=09

On twitter, @kmagiera shown a early stage implementation of Fabric working on the RNTester app -> https://twitter.com/kzzzf/status/1064891715457294337

IN Q1 2019, @kelset published a high-level/beginner friendly blogpost about it: https://formidable.com/blog/2019/fabric-turbomodules-part-3/ and did a talk about the whole rearchitecture in April 2019 at React Edinburgh.

@kelset also did a more in-depth talk at React Advanced London in Oct 2019: youtube recording & slides.

Q&A

This is also a place for questions related to this effort and its direction.

@axe-fb
Copy link
Collaborator

@axe-fb axe-fb commented Aug 2, 2018

Kevin's talk about Fabric internals

React Wednesday (July 25 2018)

Recording - https://www.facebook.com/hramos/videos/10101317533036249/

Video - https://www.slideshare.net/axemclion/react-native-fabric-review20180725

@shergin
Copy link

@shergin shergin commented Aug 16, 2018

We can start a Q&A here where anyone involved can share knowledge and ideas. 😄

I see Fabric as an effort aimed to modernize the rendering layer of React Native. Fabric relies on some new strategies, such as:

  • Using C++ for cross-platform "shadow" layer;
  • Immutable data structures (Shadow Trees, Props, Events);
  • Shared memory ownership (between JS and native);
  • JSI as an interop layer between JavaScript and native;
  • Type-safe data structures;
  • Opt-in synchronous execution where it benefits performance, the UI responsiveness and simplifying inherently-synchronous interop APIs.

Fabric is all about modern, easy-to-interop and performant UI.

@aleclarson
Copy link

@aleclarson aleclarson commented Aug 22, 2018

This sounds really cool. :)

  1. What's the timeline for Fabric's first stable release? Is there an issue tracking the progress of development? Will there be an in-depth blog post on the internals?

    edit: I see the overview stream covers the timeline and internal concepts, but a text version would be great, too! Also, could you improve the audio quality of streams like this one by using an external microphone in the future?

  2. What does Fabric mean for developers of native modules?

  3. What problems are solved by shared memory ownership between JS and native?

  4. How does the "JSI" differ from the React Native bridge?

  5. Can you provide more details on the removal of ViewManager modules?

  6. Will the reconciler eventually be in C++?

Thanks!

@shergin
Copy link

@shergin shergin commented Aug 25, 2018

@aleclarson Thank you for your question!

What's the timeline for Fabric's first stable release?

We don't have any public deadline or timeline. It's also hard to define what stable actually means for Facebook and for external users. We have quite ambitious (but realistic) plan to enable Fabric for some of the most popular RN screens in the main app.
To me, the most important mark will be when we enable Fabric for all screens in all Facebook apps. It's unclear when we will hit this point, but I am pretty optimistic about that.

What does Fabric mean for developers of native modules?

Fabric doesn't affect native modules API directly (this is a separate effort), except special kind of NativeModules called ViewManagers. Fabric does not use this approach anymore, any component-specific View Managers have to be rewritten. See also below.

What problems are solved by shared memory ownership between JS and native?

Technically, this problem does not exist in the current architecture, because the shadow tree is not shared between JS and native, each side maintains own copy of the same tree.
In Fabric, we have to be able to support multiple versions of (partially) immutable shadow trees, which can be created by both sides. To make this performant we have to "share ownership" of every node in those trees. So, if some particular node is not needed by both sides, it can be automatically deallocated; there is no need to maintain hash tables and send the information between worlds. JSI makes it possible exposing API that allows to call finalizes when GC collects objects.

How does the "JSI" differ from the React Native bridge?

They are similar but... totally different. They both connect JS machine with the native world.

Bridge is part of React Native.
Bridge includes:

  • Serializing/Deserializing pipeline;
  • Queueing;
  • Native Module API;
  • Asynchronous calling API;
  • (kinda special) Synchronous calling API;
  • Something else; Bridge is huge.

JSI is not a part of React Native, it's a unified lightweight general purpose API for (theoretically) any JavaScript virtual machine. Now there is only one implementation of that - for JavaScriptCore VM.
JSI has/allows:

  • Expose some native objects as JS objects and vice-versa;
  • Expose API for synchronous calling on this object in both directions.
    Everything else should be built on top of that.

Can you provide more details on the removal of ViewManager modules?

In the current architecture, ViewModules almost always contain only props mapping; in Fabric this information is described as *Prop classes in C++. So, there is no need for ViewManager.

Will the reconciler eventually be in C++?

Probably. Probably not. We are thinking that something like this might be valuable and feasible in a couple of years. But, personally, I think if we are thinking about this now, we can figure out something even smarter than that. :)

@kay-is
Copy link

@kay-is kay-is commented Aug 27, 2018

Thanks for the Q&A 😃

Will the JNI work like NativeScript does it?

I read they don't need bridges written in ObjC/Java.

@shergin
Copy link

@shergin shergin commented Aug 27, 2018

@kay-is

Will the JNI work like NativeScript does it?

Do you mean JSI? I don't know how NativeScript works, so I cannot say.

@kay-is
Copy link

@kay-is kay-is commented Aug 27, 2018

Yes, JSI, sorry.

AFAIK NativeScript exposes all native APIs in JS, so you don't need to write native code to interact with them.

@axe-fb
Copy link
Collaborator

@axe-fb axe-fb commented Aug 27, 2018

@kay-is It is similar, but there are differences. Unlike NativeScript, we would not have a binary file that registers ALL methods on the outset. It is more like HostObjects, which can have getters/setters.

@AlicanC
Copy link

@AlicanC AlicanC commented Aug 27, 2018

What side effects can we expect? Decreased build times? Decreased binary sizes?

How much of Java/ObjC code will become C++ in the end?

@aljs
Copy link

@aljs aljs commented Aug 28, 2018

  1. Can you share any benchmark results? I know, it's still a WIP - but it's interesting how Fabric compares to an old realisation in terms of performance.

  2. Does this affect native Obj-C modules that aren't running on the main thread?

@shergin
Copy link

@shergin shergin commented Aug 28, 2018

@AlicanC

What side effects can we expect? Decreased build times? Decreased binary sizes?

Probably, but that's not our goal. The main goal is to make the code more modern, flexible and maintainable.

How much of Java/ObjC code will become C++ in the end?

The goal is to have as small amount of platform-specific code as possible. It's hard to estimate exact amount though.

@aljs

Can you share any benchmark results? I know, it's still a WIP - but it's interesting how Fabric compares to an old realisation in terms of performance.

At this point, we don't have numbers in which we are confident enough to share. I expect to have them relatively soon though.

Does this affect native Obj-C modules that aren't running on the main thread?

(At least on iOS) All native modules which are view managers should be rewritten/adopted to Fabric, eventing else is covered by separated effort called TurboModules.

@msand
Copy link

@msand msand commented Sep 1, 2018

  1. How will the removal of ViewManagers affect Animated and useNativeDriver?
  2. What differences are there between iOS and Android? (previous message suggests only iOS needs rewriting of view managers)
    Seems the removal might simplify native animation of e.g. react-native-svg. I've had to introduce property setters in the ViewManagers and Views/ViewGroups (just to contain a reference to the shadow node, in order to be able to set the properties) in addition to the shadow nodes, for all Svg elements on Android, to allow animation using the native driver.
    https://github.com/react-native-community/react-native-svg/pull/757/files#diff-4514e2800c86c3d034626a608dce25b2
    facebook/react-native#18187
    react-native-svg/react-native-svg#757
  3. Will there be improved support for writing native modules in C++?
@axe-fb
Copy link
Collaborator

@axe-fb axe-fb commented Sep 1, 2018

@msand For native modules (3) - note that you can already write native modules in C++.
We are also working on a parallel proposal for a new architecture for native modules - #11

@msand
Copy link

@msand msand commented Sep 1, 2018

@axe-fb Do you have any good examples? I've seen expo-gl and just now found
https://github.com/sulewicz/djinni-react-native
https://github.com/sulewicz/djinni-react-native/tree/master/example-react-native/ExampleProject
which seems to simplify things.

@msand
Copy link

@msand msand commented Sep 1, 2018

I'm thinking for react-native-svg the text layout algorithm from the SVG 2.0 spec might make sense to attempt implementing in c++ instead of both obj-c and java. Would be easier to maintain a single implementation.

@shergin
Copy link

@shergin shergin commented Sep 5, 2018

@msand

How will the removal of ViewManagers affect Animated and useNativeDriver?

Native Animation Driver has to be rewritten, we plan to invest in it this year. Classic Animated implementation will work out of the box because it relies on setNativeProps which will fully support by Fabric soon. This is true for iOS and Android implementations.

I'm thinking for react-native-svg the text layout algorithm from the SVG 2.0 spec might make sense to attempt implementing in c++ instead of both obj-c and java. Would be easier to maintain a single implementation.

Yes, totally. I think the all non-drawing code should be unified and rewritten in C++. We plan to do this for ART soon.

@sibelius
Copy link
Member

@sibelius sibelius commented Sep 5, 2018

I've made an overview talk of how React Native bridge architecture works

I've made a talk that presents the current React Native Bridge architecture, explaining its characteristics, how it works and its drawbacks.
I've also talked about how the new future bridge architecture will look like

https://speakerdeck.com/sibelius/react-native-bridges-architectures

I think this could be a good intro for the bridge topic

@aljs
Copy link

@aljs aljs commented Sep 7, 2018

Are some parts of it already in use without a flag? (on master branch)
Get a crash related to custom view manager on [self.subviews objectAtIndex:]. Only on iOS 9-10, which is weird.

@mattgperry
Copy link

@mattgperry mattgperry commented Sep 16, 2018

@shergin I’m currently trying to implement the FLIP animation technique in React Native.

If you haven’t seen this in browsers, the short version: When the layout of a component changes, we can invert its positional delta via a transform, and then animate it into its new position by animating x and y back to 0

To do this seamlessly, without seeing the component in its new position for a frame, we need to guarantee onLayout is fired before the new position is drawn to the screen.

The docs say “the new layout may not yet be reflected on the screen at the time the event is received”, and indeed now and then there is a perceivable “snap”. Will Fabric allow us to guarantee execution of onLayout before the layout is reflected on the screen or am I barking up the wrong tree?

Thanks in advance for your input

@fkgozali
Copy link

@fkgozali fkgozali commented Sep 16, 2018

Will Fabric allow us to guarantee execution of onLayout before the layout is reflected on the screen or am I barking up the wrong tree?

A few things:

  • onLayout() is an async event from native to JS, so unless native guarantees that the event is dispatched synchronously after native layout, there’s no guarantee that the content is final.
  • One of use cases that Fabric can enable is “synchronous initial rendering”, where UI layout happens synchronously until content is ready to be displayed - we’ll tackle this a bit later after the core of Fabric and its parity with existing impl are stable.
  • Now, it is in theory possible to update the behavior of onLayout() to be more synchronous in nature, or to avoid the need of initial onLayout() if native can provide layout info synchronously on mount. We are thinking about this, but it won’t be immediately changed via Fabric project. It’s more of improvements we can do on top of Fabric.

Hope that helps.

@kyashrathore
Copy link

@kyashrathore kyashrathore commented Oct 8, 2018

will this re architecture of react native yield performance as good as flutter or flutter's performance is just hyped about?I have learned react recently and I love it ,will it prove to be a good decision to learn react-native for native mobile apps or in core of your heart you feel flutter is better?

@shergin
Copy link

@shergin shergin commented Oct 8, 2018

@contactyash

  1. Fabric is designed to be (incredibly) responsive and interopable.
  2. Real performance Flutter vs. Fabric is incomparable unless we have big production apps written in both of them.
  3. All apps that I have seen in Flutter don't demonstrate impressive performance unfortunately (totally bias opinion).
@joonhocho
Copy link

@joonhocho joonhocho commented Oct 8, 2018

The two main reasons that I stopped using on React Native were Navigation and ListView.
For navigation, I think I've tried 5 different libraries including React Navigation and all felt sluggish. I think wix/react-native-navigation v2 can finally address the problem. I have my hopes up.
For ListView, I've tried every library and every optimization solution out there and it all failed miserably for large lists with pictures and few dynamic components. In the end, I had to bridge native tableview and native cells in order to make it useable.
App startup kept getting slower as app grew large as well. I really hope this re-architecture finally fixes these issues.
ListView and Navigation are the most commonly used components in any apps, and they are still the main problems after 5 years for React Native.
With sync communication between native and js, will it be possible to use native native tableview with cells being rendered in js?

@shergin
Copy link

@shergin shergin commented Oct 9, 2018

@joonhocho Yes, Fabric is a foundation that meant to help improve things including navigation (sync external interop) and lists (better/sync measuring API, build-in view recycling and flattening). Fabric itself will not solve that, but it will enable actual solutions.

@joonhocho
Copy link

@joonhocho joonhocho commented Oct 9, 2018

@shergin I am wondering, in new react native architecture, whether even the rendering can be synchronized. I believe IOS UITableView requires synchronized rendering of cells. That means React should render and return native cell view to the tableview in synchronized way. Will this kind of behavior supported by the new architecture or rendering will be always asynchronous?

@michbil
Copy link

@michbil michbil commented Jan 6, 2020

Here is a way to build fabric for non-patient: Fix
After pod install run ./fixpods script in the RNTester directory, to run few hacks. Repository constantly changing, so there is no sense making proper fix for it ATM.
Much have changed since last time I built fabric, had to figure out few missing changes to AppDelegate.mm.
Here is sample video:
Fabric demo

@pvinis
Copy link
Member

@pvinis pvinis commented Jan 15, 2020

Is "Paper" the codename of the current architect, to be replaced by "Fabric"?

@TheSavior
Copy link

@TheSavior TheSavior commented Jan 15, 2020

Is "Paper" the codename of the current architect, to be replaced by "Fabric"?

Yep, the thinking was that paper is kinda like a crunchy, bad fabric material. :-)

@mauriciopf
Copy link

@mauriciopf mauriciopf commented Feb 26, 2020

Will this new architecture will be able to support multithreading?

@peterasorensen
Copy link

@peterasorensen peterasorensen commented May 12, 2020

We're getting pretty close to the middle of 2020, any word on a more specific roll out date, or has the ship date been pushed back?

@kelset
Copy link
Member Author

@kelset kelset commented May 12, 2020

@peterasorensen I think that the current focus is around TurboModules so until they are fully rolled out for the OSS side I'm assuming there won't be any update on Fabric rollout schedule :)

@LifeIsStrange

This comment was marked as spam.

@affannology

This comment was marked as spam.

@ravirajn22
Copy link

@ravirajn22 ravirajn22 commented Sep 23, 2020

I always had this doubt so wanted to post here so that some one can clarify and enlighten more on this topic.

Sorry if I get this wrong, I feel this whole re-architecture feels like what browsers do internally. Fo example,

  1. Using C++ as common layer to communicate between platform functions and JS. Browsers do it.
  2. Synchronously calling platform native functions via JS. Browsers do it.

So, if we consider the browser engine internally uses platform library(I know they don't use NSView or TextInput, they must use some native Drawing API) to draw views and inputs. Than how will this re-architecture will bring more performance than wrapping HTML and JS inside a Web view?

I am new to benchmarks and performance, but still if you guys have anything to share it will be help full.

BTW, all innovations happen over incremental changes on existing, so I hope the best for this re-architecture.

@Kudo
Copy link
Member

@Kudo Kudo commented Sep 23, 2020

@ravirajn22 Share my comment from a browser developer point of view.

Before answering, please let me ask a question first.
Flutter is more like a browser than React Native, why did people said Flutter's performance is better than React Native?

IMO, there are other reasons for browsers to be slow, not just platform functions <-> C++ <-> JS.
In a nutshell,
Browsers have HTML: Need to parse HTML and generate DOM tree.
Browsers have CSS: Need to parse CSS and generate CSSOM tree.
When HTML + CSS + JavaScript mixed together, the whole system will be complicated.
React Native / Flutter are faster than browsers because they use JavaScript / Dart to control native stuffs directly.
That is my two cents, from the beauty of simplicity.

@ravirajn22
Copy link

@ravirajn22 ravirajn22 commented Sep 23, 2020

@Kudo Well explained, even I had this same reason. But which one is better in terms of performance? it's all speculative you know. We can say web view has HTML and CSS parsing but on the other hand react-native also does lot of things to put views on the screen. One day I would like see a real app performance benchmark comparison between these tools.

@windev92
Copy link

@windev92 windev92 commented Sep 23, 2020

Hi all,

I will try to be as clear as possible. The new features are turbomodules, jsi, and Fabric.
I have in my current app several native modules developed 2 years ago with RCT_EXPORT_METHOD, ... i.e without jsi ( and modules are not turbo, i.e they are all loaded even if not used).
in 0.62.2 the turbomodule and jsi support are fully operational, and I managed to migrate my native modules as turbomodules and added the jsi support for sync support (global.mymodule). This all works like a charm ( even if I don't really see significant benchmarks enhancement comparing to the version with the bridge...)
For the modules I have replaced my modules that used to derive from RCTBridgeModule and they now derived from jsi::TurboModule.
So the point of this message is :
In my app I also have a UI module, i.e derives from RCTViewManager which itself derives from RCTBridgeModule (and therefore has async RCT_EXPORT_METHOD exposed). My guess is that the Fabric is here to refactor this part. I currently have a hybrid implementation, with the native module (non GUI), using jsi, and the UI module using the bridge.
question: what shall I do to remove the RCTViewManager and have a UI module that uses JSI/Fabric.
is there any example on how to migrate old style UI components to Fabric/jsi. it is the last missing bit in my app.
many thanks!

@terrysahaidak
Copy link

@terrysahaidak terrysahaidak commented Sep 23, 2020

@Kudo Well explained, even I had this same reason. But which one is better in terms of performance? it's all speculative you know. We can say web view has HTML and CSS parsing but on the other hand react-native also does lot of things to put views on the screen. One day I would like see a real app performance benchmark comparison between these tools.

There is already technology that gives you access to native API and uses webview for the rest - Cordova.

I think you can search for some performance comparison.

@windev92
Copy link

@windev92 windev92 commented Sep 24, 2020

Here is a way to build fabric for non-patient: Fix
After pod install run ./fixpods script in the RNTester directory, to run few hacks. Repository constantly changing, so there is no sense making proper fix for it ATM.
Much have changed since last time I built fabric, had to figure out few missing changes to AppDelegate.mm.
Here is sample video:
Fabric demo

cd RNTester
pod install
=> I first had 'flow-node' not found, I then did :
npm install flow-remove-types

I now I have
Error: Cannot find module 'nullthrows'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
at Function.Module._load (internal/modules/cjs/loader.js:507:25)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)

then jscodeshift missing, then mkdirp
Is it normal to manually install everything? I am wondering if everything is supposed to run out of the box and my setup is incorrect.
KR

@michbil
Copy link

@michbil michbil commented Oct 23, 2020

@windev92 My scripts are way outdated now. Fabric made long way since then. Currently I have no idea how to build it myself.
Theoretically android should build now with
export USE_FABRIC=true && export USE_CODEGEN=true && ./gradlew installDebug
But I had no luck to actually run it.
If anyone have good manual how to run it now, pls share it here

@alexandrius
Copy link

@alexandrius alexandrius commented Mar 12, 2021

Here is a way to build fabric for non-patient: Fix
After pod install run ./fixpods script in the RNTester directory, to run few hacks. Repository constantly changing, so there is no sense making proper fix for it ATM.
Much have changed since last time I built fabric, had to figure out few missing changes to AppDelegate.mm.
Here is sample video:
Fabric demo

cd RNTester
pod install
=> I first had 'flow-node' not found, I then did :
npm install flow-remove-types

I now I have
Error: Cannot find module 'nullthrows'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
at Function.Module._load (internal/modules/cjs/loader.js:507:25)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)

then jscodeshift missing, then mkdirp
Is it normal to manually install everything? I am wondering if everything is supposed to run out of the box and my setup is incorrect.
KR

Is application rendered faster with Fabric?

@iagormoraes
Copy link

@iagormoraes iagormoraes commented Mar 22, 2021

Is the Fabric architecture going to fix problems related to the re-layout issue?

@hcminhit
Copy link

@hcminhit hcminhit commented May 29, 2021

hi guys
when the new architecture fabric, jsi, turbo , codegen are officially released, do i have to learn react-native from scratch? packages currently available on npm have to be rewritten?

@michbil
Copy link

@michbil michbil commented May 29, 2021

IMO, your experience won't change much, there will be minor compatibility problems with some modules, your tooling experience will change little bit(you won't be able chrome debugger, and need to use new one with Flipper), but otherwise developer experience should be close to what we have today.

@gaodeng

This comment was marked as off-topic.

@alexandrius

This comment has been hidden.

@gaodeng

This comment has been hidden.

@danilobuerger

This comment has been hidden.

@tabfed

This comment has been hidden.

@ntucker

This comment has been hidden.

@kelset
Copy link
Member Author

@kelset kelset commented Jun 1, 2021

ok this conversation is going a bit off the rails so I'll hide the last few comments. I agree and share your frustration about the lack of roadmap, but there's nothing we can do about it but wait. This is is not the right venue for complaning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet