From 548330d8c9ec7b80e468b4870c7d518e6ef67452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Thu, 10 Mar 2022 15:21:14 +0100 Subject: [PATCH] Unversion Architecture docs (#3000) Co-authored-by: Bartosz Kaszubowski --- docs/fabric-renderer.md | 28 --- .../architecture}/_fabric-warning.mdx | 0 .../architecture}/architecture-glossary.md | 1 + .../architecture}/architecture-overview.md | 1 + .../fabric-renderer.md | 10 +- .../architecture}/render-pipeline.md | 22 +- .../architecture}/threading-model.md | 0 .../architecture}/view-flattening.md | 4 +- .../architecture}/xplat-implementation.md | 6 +- website/docusaurus.config.js | 52 ++-- website/sidebars.json | 26 +- website/sidebarsArchitecture.json | 26 ++ website/static/_redirects | 25 ++ .../version-0.66/architecture-glossary.md | 48 ---- .../version-0.66/architecture-overview.md | 6 - .../version-0.66/render-pipeline.md | 221 ----------------- .../version-0.66/threading-model.md | 84 ------- .../version-0.66/view-flattening.md | 47 ---- .../version-0.66/xplat-implementation.md | 34 --- .../version-0.67/architecture-glossary.md | 48 ---- .../version-0.67/architecture-overview.md | 6 - .../version-0.67/fabric-renderer.md | 28 --- .../version-0.67/render-pipeline.md | 222 ------------------ .../version-0.67/threading-model.md | 84 ------- .../version-0.67/view-flattening.md | 47 ---- .../version-0.67/xplat-implementation.md | 34 --- .../version-0.66-sidebars.json | 45 ---- .../version-0.67-sidebars.json | 26 +- 28 files changed, 108 insertions(+), 1073 deletions(-) delete mode 100644 docs/fabric-renderer.md rename {docs => website/architecture}/_fabric-warning.mdx (100%) rename {docs => website/architecture}/architecture-glossary.md (99%) rename {docs => website/architecture}/architecture-overview.md (95%) rename website/{versioned_docs/version-0.66 => architecture}/fabric-renderer.md (69%) rename {docs => website/architecture}/render-pipeline.md (87%) rename {docs => website/architecture}/threading-model.md (100%) rename {docs => website/architecture}/view-flattening.md (88%) rename {docs => website/architecture}/xplat-implementation.md (73%) create mode 100644 website/sidebarsArchitecture.json delete mode 100644 website/versioned_docs/version-0.66/architecture-glossary.md delete mode 100644 website/versioned_docs/version-0.66/architecture-overview.md delete mode 100644 website/versioned_docs/version-0.66/render-pipeline.md delete mode 100644 website/versioned_docs/version-0.66/threading-model.md delete mode 100644 website/versioned_docs/version-0.66/view-flattening.md delete mode 100644 website/versioned_docs/version-0.66/xplat-implementation.md delete mode 100644 website/versioned_docs/version-0.67/architecture-glossary.md delete mode 100644 website/versioned_docs/version-0.67/architecture-overview.md delete mode 100644 website/versioned_docs/version-0.67/fabric-renderer.md delete mode 100644 website/versioned_docs/version-0.67/render-pipeline.md delete mode 100644 website/versioned_docs/version-0.67/threading-model.md delete mode 100644 website/versioned_docs/version-0.67/view-flattening.md delete mode 100644 website/versioned_docs/version-0.67/xplat-implementation.md diff --git a/docs/fabric-renderer.md b/docs/fabric-renderer.md deleted file mode 100644 index 5e000f594af..00000000000 --- a/docs/fabric-renderer.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -id: fabric-renderer -title: Fabric ---- - -Fabric is React Native's new rendering system, a conceptual evolution of the legacy render system. The core principles are to unify more render logic in C++, improve interoperability with [host platforms](architecture-glossary#host-platform), and to unlock new capabilities for React Native. Development began in 2018 and in 2021, React Native in the Facebook app is backed by the new renderer. - -This documentation provides an overview of the [new renderer](architecture-glossary#fabric-render) and its concepts. It avoids platform specifics and doesn’t contain any code snippets or pointers. This documentation covers key concepts, motivation, benefits, and an overview of the render pipeline in different scenarios. - -## Motivations and Benefits of the new renderer - -The render architecture was created to unlock better user experiences that weren’t possible with the legacy architecture. Some examples include: - -- With improved interoperability between [host views](architecture-glossary#host-view-tree-and-host-view) and React views, the renderer is able to measure and render React surfaces synchronously. In the legacy architecture, React Native layout was asynchronous which led to a layout “jump” issue when embedding a React Native rendered view in a _host view_. -- With support of multi-priority and synchronous events, the renderer can prioritize certain user interactions to ensure they are handled in a timely manner. -- [Integration with React Suspense](https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html) which allows for more intuitive design of data fetching in React apps. -- Enable React [Concurrent Features](https://github.com/reactwg/react-18/discussions/4) on React Native. -- Easier to implement server side rendering for React Native. - -The new architecture also provides benefits in code quality, performance, and extensibility: - -- **Type safety:** code generation to ensure type safety across the JS and [host platforms](architecture-glossary#host-platform). The code generation uses JavaScript component declarations as source of truth to generate C++ structs to hold the props. Mismatch between JavaScript and host component props triggers a build error. -- **Shared C++ core**: the renderer is implemented in C++ and the core is shared among platforms. This increases consistency and makes it easier to adopt React Native on new platforms. -- **Better Host Platform Interoperability**: Synchronous and thread-safe layout calculation improves user experiences when embedding host components into React Native, which means easier integration with host platform frameworks that require synchronous APIs. -- **Improved Performance**: With the new cross-platform implementation of the renderer system, every platform benefits from performance improvements that may have been motivated by limitations of one platform. For example, view flattening was originally a performance solution for Android and is now provided by default on both Android and iOS. -- **Consistency**: The new render system is cross-platform, it is easier to keep consistency among different platforms. -- **Faster Startup**: Host components are lazily initialized by default. -- **Less serialization of data between JS and host platform**: React used to transfer data between JavaScript and _host platform_ as serialized JSON. The new renderer improves the transfer of data by accessing JavaScript values directly using [JavaScript Interfaces (JSI)](architecture-glossary#javascript-interfaces-jsi). diff --git a/docs/_fabric-warning.mdx b/website/architecture/_fabric-warning.mdx similarity index 100% rename from docs/_fabric-warning.mdx rename to website/architecture/_fabric-warning.mdx diff --git a/docs/architecture-glossary.md b/website/architecture/architecture-glossary.md similarity index 99% rename from docs/architecture-glossary.md rename to website/architecture/architecture-glossary.md index 1e5a50c0ff5..d3ab96ce21f 100644 --- a/docs/architecture-glossary.md +++ b/website/architecture/architecture-glossary.md @@ -1,6 +1,7 @@ --- id: architecture-glossary title: Glossary +slug: /glossary --- ## Fabric Renderer diff --git a/docs/architecture-overview.md b/website/architecture/architecture-overview.md similarity index 95% rename from docs/architecture-overview.md rename to website/architecture/architecture-overview.md index a29e48b2475..8200802d846 100644 --- a/docs/architecture-overview.md +++ b/website/architecture/architecture-overview.md @@ -1,6 +1,7 @@ --- id: architecture-overview title: Architecture Overview +slug: /overview --- This section is a work in progress intended to share conceptual overviews of how React Native's architecture works. Its intended audience includes library authors, core contributors, and the exceptionally curious. It is not a requirement to be familiar with this material to use React Native. diff --git a/website/versioned_docs/version-0.66/fabric-renderer.md b/website/architecture/fabric-renderer.md similarity index 69% rename from website/versioned_docs/version-0.66/fabric-renderer.md rename to website/architecture/fabric-renderer.md index e81773b32f2..dc24c2d8a92 100644 --- a/website/versioned_docs/version-0.66/fabric-renderer.md +++ b/website/architecture/fabric-renderer.md @@ -3,15 +3,15 @@ id: fabric-renderer title: Fabric --- -Fabric is React Native's new rendering system, a conceptual evolution of the legacy render system. The core principles are to unify more render logic in C++, improve interoperability with [host platforms](architecture-glossary#host-platform), and to unlock new capabilities for React Native. Development began in 2018 and in 2021, React Native in the Facebook app is backed by the new renderer. +Fabric is React Native's new rendering system, a conceptual evolution of the legacy render system. The core principles are to unify more render logic in C++, improve interoperability with [host platforms](architecture-glossary.md#host-platform), and to unlock new capabilities for React Native. Development began in 2018 and in 2021, React Native in the Facebook app is backed by the new renderer. -This documentation provides an overview of the [new renderer](architecture-glossary#fabric-render) and its concepts. It avoids platform specifics and doesn’t contain any code snippets or pointers. This documentation covers key concepts, motivation, benefits, and an overview of the render pipeline in different scenarios. +This documentation provides an overview of the [new renderer](architecture-glossary.md#fabric-render) and its concepts. It avoids platform specifics and doesn’t contain any code snippets or pointers. This documentation covers key concepts, motivation, benefits, and an overview of the render pipeline in different scenarios. ## Motivations and Benefits of the new renderer The render architecture was created to unlock better user experiences that weren’t possible with the legacy architecture. Some examples include: -- With improved interoperability between [host views](architecture-glossary#host-view-tree-and-host-view) and React views, the renderer is able to measure and render React surfaces synchronously. In the legacy architecture, React Native layout was asynchronous which led to a layout “jump” issue when embedding a React Native rendered view in a _host view_. +- With improved interoperability between [host views](architecture-glossary.md#host-view-tree-and-host-view) and React views, the renderer is able to measure and render React surfaces synchronously. In the legacy architecture, React Native layout was asynchronous which led to a layout “jump” issue when embedding a React Native rendered view in a _host view_. - With support of multi-priority and synchronous events, the renderer can prioritize certain user interactions to ensure they are handled in a timely manner. - [Integration with React Suspense](https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html) which allows for more intuitive design of data fetching in React apps. - Enable React [Concurrent Features](https://github.com/reactwg/react-18/discussions/4) on React Native. @@ -19,10 +19,10 @@ The render architecture was created to unlock better user experiences that weren The new architecture also provides benefits in code quality, performance, and extensibility: -- **Type safety:** code generation to ensure type safety across the JS and [host platforms](architecture-glossary#host-platform). The code generation uses JavaScript component declarations as source of truth to generate C++ structs to hold the props. Mis-match between JavaScript and host component props triggers a build error. +- **Type safety:** code generation to ensure type safety across the JS and [host platforms](architecture-glossary.md#host-platform). The code generation uses JavaScript component declarations as source of truth to generate C++ structs to hold the props. Mismatch between JavaScript and host component props triggers a build error. - **Shared C++ core**: the renderer is implemented in C++ and the core is shared among platforms. This increases consistency and makes it easier to adopt React Native on new platforms. - **Better Host Platform Interoperability**: Synchronous and thread-safe layout calculation improves user experiences when embedding host components into React Native, which means easier integration with host platform frameworks that require synchronous APIs. - **Improved Performance**: With the new cross-platform implementation of the renderer system, every platform benefits from performance improvements that may have been motivated by limitations of one platform. For example, view flattening was originally a performance solution for Android and is now provided by default on both Android and iOS. - **Consistency**: The new render system is cross-platform, it is easier to keep consistency among different platforms. - **Faster Startup**: Host components are lazily initialized by default. -- **Less serialization of data between JS and host platform**: React used to transfer data between JavaScript and _host platform_ as serialized JSON. The new renderer improves the transfer of data by accessing JavaScript values directly using [JavaScript Interfaces (JSI)](architecture-glossary#javascript-interfaces-jsi). +- **Less serialization of data between JS and host platform**: React used to transfer data between JavaScript and _host platform_ as serialized JSON. The new renderer improves the transfer of data by accessing JavaScript values directly using [JavaScript Interfaces (JSI)](architecture-glossary.md#javascript-interfaces-jsi). diff --git a/docs/render-pipeline.md b/website/architecture/render-pipeline.md similarity index 87% rename from docs/render-pipeline.md rename to website/architecture/render-pipeline.md index a0aa8a610c1..7c0373844e4 100644 --- a/docs/render-pipeline.md +++ b/website/architecture/render-pipeline.md @@ -7,13 +7,13 @@ import FabricWarning from './\_fabric-warning.mdx'; -The React Native renderer goes through a sequence of work to render React logic to a [host platform](architecture-glossary#host-platform). This sequence of work is called the render pipeline and occurs for initial renders and updates to the UI state. This document goes over the render pipeline and how it differs in those scenarios. +The React Native renderer goes through a sequence of work to render React logic to a [host platform](architecture-glossary.md#host-platform). This sequence of work is called the render pipeline and occurs for initial renders and updates to the UI state. This document goes over the render pipeline and how it differs in those scenarios. The render pipeline can be broken into three general phases: -1. **Render:** React executes product logic which creates a [React Element Tree](architecture-glossary#react-element-tree-and-react-element) in JavaScript. From this tree, the renderer creates a [React Shadow Tree](architecture-glossary#react-shadow-tree-and-react-shadow-node) in C++. +1. **Render:** React executes product logic which creates a [React Element Trees](architecture-glossary.md#react-element-tree-and-react-element) in JavaScript. From this tree, the renderer creates a [React Shadow Tree](architecture-glossary.md#react-shadow-tree-and-react-shadow-node) in C++. 2. **Commit**: After a React Shadow Tree is fully created, the renderer triggers a commit. This **promotes** both the React Element Tree and the newly created React Shadow Tree as the “next tree” to be mounted. This also schedules calculation of its layout information. -3. **Mount:** The React Shadow Tree, now with the results of layout calculation, is transformed into a [Host View Tree](architecture-glossary#host-view-tree-and-host-view). +3. **Mount:** The React Shadow Tree, now with the results of layout calculation, is transformed into a [Host View Tree](architecture-glossary.md#host-view-tree-and-host-view). > The phases of the render pipeline may occur on different threads. Refer to the [Threading Model](threading-model) doc for more detail. @@ -37,13 +37,13 @@ function MyComponent() { // ``` -In the example above, `` is a [React Element](architecture-glossary#react-element-tree-and-react-element). React recursively reduces this _React Element_ to a terminal [React Host Component](architecture-glossary#react-host-components-or-host-components) by invoking it (or its `render` method if implemented with a JavaScript class) until every _React Element_ cannot be reduced any further. Now you have a _React Element Tree_ of [React Host Components](architecture-glossary#react-host-components-or-host-components). +In the example above, `` is a [React Element](architecture-glossary.md#react-element-tree-and-react-element). React recursively reduces this _React Element_ to a terminal [React Host Component](architecture-glossary.md#react-host-components-or-host-components) by invoking it (or its `render` method if implemented with a JavaScript class) until every _React Element_ cannot be reduced any further. Now you have a _React Element Tree_ of [React Host Components](architecture-glossary.md#react-host-components-or-host-components). ### Phase 1. Render ![Phase one: render](/docs/assets/Architecture/renderer-pipeline/phase-one-render.png) -During this process of element reduction, as each _React Element_ is invoked, the renderer also synchronously creates a [React Shadow Node](architecture-glossary#react-shadow-tree-and-react-shadow-node). This happens only for _React Host Components_, not for [React Composite Components](architecture-glossary#react-composite-components). In the example above, the `` leads to the creation of a `ViewShadowNode` object, and the +During this process of element reduction, as each _React Element_ is invoked, the renderer also synchronously creates a [React Shadow Node](architecture-glossary.md#react-shadow-tree-and-react-shadow-node). This happens only for _React Host Components_, not for [React Composite Components](architecture-glossary.md#react-composite-components). In the example above, the `` leads to the creation of a `ViewShadowNode` object, and the `` leads to the creation of a `TextShadowNode` object. Notably, there is never a _React Shadow Node_ that directly represents ``. Whenever React creates a parent-child relationship between two _React Element Nodes_, the renderer creates the same relationship between the corresponding _React Shadow Nodes_. This is how the _React Shadow Tree_ is assembled. @@ -89,7 +89,7 @@ The mount phase transforms the _React Shadow Tree_ (which now contains data from ``` -At a high level, React Native renderer creates a corresponding [Host View](architecture-glossary#host-view-tree-and-host-view) for each _React Shadow Node_ and mounts it on screen. In the example above, the renderer creates an instance of `android.view.ViewGroup` for the `` and `android.widget.TextView` for `` and populates it with “Hello World”. Similarly for iOS a `UIView` is created with and text is populated with a call to `NSLayoutManager`. Each host view is then configured to use props from its React Shadow Node, and its size and position is configured using the calculated layout information. +At a high level, React Native renderer creates a corresponding [Host View](architecture-glossary.md#host-view-tree-and-host-view) for each _React Shadow Node_ and mounts it on screen. In the example above, the renderer creates an instance of `android.view.ViewGroup` for the `` and `android.widget.TextView` for `` and populates it with “Hello World”. Similarly for iOS a `UIView` is created with and text is populated with a call to `NSLayoutManager`. Each host view is then configured to use props from its React Shadow Node, and its size and position is configured using the calculated layout information. ![Step two](/docs/assets/Architecture/renderer-pipeline/render-pipeline-3.png) @@ -150,7 +150,7 @@ When a state update occurs, the renderer needs to conceptually update the _React Let’s explore each phase of the render pipeline during a state update. -### Phase 1: Render +### Phase 1. Render ![Phase one: render](/docs/assets/Architecture/renderer-pipeline/phase-one-render.png) @@ -173,7 +173,7 @@ After these operations, **Node 1'** represents the root of the new _React Elemen Notice how **T** and **T'** both share **Node 4**. Structural sharing improves performance and reduces memory usage. -### Phase 2: Commit +### Phase 2. Commit ![Phase two: commit](/docs/assets/Architecture/renderer-pipeline/phase-two-commit.png) @@ -185,7 +185,7 @@ After React creates the new _React Element Tree_ and _React Shadow Tree_, it mus - **Tree Diffing:** This step computes the diff between the “previously rendered tree” (**T**) and the “next tree” (**T'**). The result is a list of atomic mutation operations to be performed on _host views_. - In the above example, the operations consist of: `UpdateView(**Node 3'**, {backgroundColor: '“yellow“})` -### Phase 3: Mount +### Phase 3. Mount ![Phase three: mount](/docs/assets/Architecture/renderer-pipeline/phase-three-mount.png) @@ -211,13 +211,13 @@ With two important differences: 1. They skip the “render phase” since React is not involved. 2. The updates can originate and happen on any thread, including the main thread. -### Phase 2: Commit +### Phase 2. Commit ![Phase two: commit](/docs/assets/Architecture/renderer-pipeline/phase-two-commit.png) When performing a _C++ State_ update, a block of code requests an update of a `ShadowNode` (**N**) to set _C++ State_ to value **S**. React Native renderer will repeatedly attempt to get the latest committed version of **N**, clone it with a new state **S**, and commit **N’** to the tree. If React, or another _C++ State_ update, has performed another commit during this time, the _C++ State_ commit will fail and the renderer will retry the _C++ State_ update many times until a commit succeeds. This prevents source-of-truth collisions and races. -### Phase 3: Mount +### Phase 3. Mount ![Phase three: mount](/docs/assets/Architecture/renderer-pipeline/phase-three-mount.png) diff --git a/docs/threading-model.md b/website/architecture/threading-model.md similarity index 100% rename from docs/threading-model.md rename to website/architecture/threading-model.md diff --git a/docs/view-flattening.md b/website/architecture/view-flattening.md similarity index 88% rename from docs/view-flattening.md rename to website/architecture/view-flattening.md index 386eb442f17..323ac63acee 100644 --- a/docs/view-flattening.md +++ b/website/architecture/view-flattening.md @@ -9,7 +9,7 @@ import FabricWarning from './\_fabric-warning.mdx'; #### View Flattening is an optimization by the React Native renderer to avoid deep layout trees. -The React API is designed to be declarative and reusable through composition. This provides a great model for intuitive development. However, in implementation, these qualities of the API lead to the creation of deep [React Element Trees](architecture-glossary#react-element-tree-and-react-element), where a large majority of React Element Nodes only affect the layout of a View and don’t render anything on the screen. We call these types of nodes **“Layout-Only”** Nodes. +The React API is designed to be declarative and reusable through composition. This provides a great model for intuitive development. However, in implementation, these qualities of the API lead to the creation of deep [React Element Trees](architecture-glossary.md#react-element-tree-and-react-element), where a large majority of React Element Nodes only affect the layout of a View and don’t render anything on the screen. We call these types of nodes **“Layout-Only”** Nodes. Conceptually, each of the Nodes of the React Element Tree have a 1:1 relationship with a view on the screen, therefore rendering a deep React Element Tree that is composed by a large amount of “Layout-Only” Node leads to poor performance during rendering. @@ -38,7 +38,7 @@ As part of the render process, React Native will produce the following trees: Note that the Views (2) and (3) are “Layout Only” views, because they are rendered on the screen but they only render a `margin` of `10 px` on top of their children. -To improve the performance of these types of React Element Trees, the renderer implements a View Flattening mechanism that merges or flattens these types of Nodes, reducing the depth of the [host view](architecture-glossary#host-view-tree-and-host-view) hierarchy that is rendered on the screen. This algorithm takes into consideration props like: `margin`, `padding`, `backgroundColor`, `opacity`, etc. +To improve the performance of these types of React Element Trees, the renderer implements a View Flattening mechanism that merges or flattens these types of Nodes, reducing the depth of the [host view](architecture-glossary.md#host-view-tree-and-host-view) hierarchy that is rendered on the screen. This algorithm takes into consideration props like: `margin`, `padding`, `backgroundColor`, `opacity`, etc. The View Flattening algorithm is integrated by design as part of the diffing stage of the renderer, which means that we don’t use extra CPU cycles to optimize the React Element Tree flattening these types of views. As the rest of the core, the View flattening algorithm is implemented in C++ and its benefits are shared by default on all supported platforms. diff --git a/docs/xplat-implementation.md b/website/architecture/xplat-implementation.md similarity index 73% rename from docs/xplat-implementation.md rename to website/architecture/xplat-implementation.md index 77e27bff138..ad7355cd6dd 100644 --- a/docs/xplat-implementation.md +++ b/website/architecture/xplat-implementation.md @@ -9,15 +9,15 @@ import FabricWarning from './\_fabric-warning.mdx'; #### The React Native renderer utilizes a core render implementation to be shared across platforms -In the previous render system of React Native, the **[React Shadow Tree](architecture-glossary#react-shadow-tree-and-react-shadow-node)**, layout logic, and **[View Flattening](view-flattening.md)** algorithm were implemented once for each platform. The current renderer was designed to be a cross-platform solution by sharing a core C++ implementation. +In the previous render system of React Native, the **[React Shadow Tree](architecture-glossary.md#react-shadow-tree-and-react-shadow-node)**, layout logic, and **[View Flattening](view-flattening.md)** algorithm were implemented once for each platform. The current renderer was designed to be a cross-platform solution by sharing a core C++ implementation. The React Native team intends to incorporate an animation system into the render system and also extend the React Native render system to new platforms such as Windows, and operating systems in game consoles, televisions, and more. -Leveraging C++ for the core render system introduces several advantages. A single implementation reduces the cost of development and maintenance. It improves the performance of creating React Shadow Trees and layout calculation because the overhead of integrating [Yoga](architecture-glossary#yoga-tree-and-yoga-node) with the renderer is minimized on Android (i.e. no more [JNI](architecture-glossary#java-native-interface-jni) for Yoga). Finally, the memory footprint of each React Shadow Node is smaller in C++ than it would be if allocated from Kotlin or Swift. +Leveraging C++ for the core render system introduces several advantages. A single implementation reduces the cost of development and maintenance. It improves the performance of creating React Shadow Trees and layout calculation because the overhead of integrating [Yoga](architecture-glossary.md#yoga-tree-and-yoga-node) with the renderer is minimized on Android (i.e. no more [JNI](architecture-glossary.md#java-native-interface-jni) for Yoga). Finally, the memory footprint of each React Shadow Node is smaller in C++ than it would be if allocated from Kotlin or Swift. The team is also leveraging C++ features that enforce immutability to ensure there are no issues related to concurrent access to shared but not protected resources. -It is important to recognize that the renderer use case for Android still incurs the cost of [JNI](architecture-glossary#java-native-interface-jni) for two primary use cases: +It is important to recognize that the renderer use case for Android still incurs the cost of [JNI](architecture-glossary.md#java-native-interface-jni) for two primary use cases: - Layout calculation of complex views (e.g. `Text`, `TextInput`, etc.) requires sending props over JNI. - The mount phase requires sending mutation operations over JNI. diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 673a3392fe6..4a05efdfd34 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -3,6 +3,14 @@ const versions = require('./versions.json'); const lastVersion = versions[0]; +const commonDocsOptions = { + showLastUpdateAuthor: false, + showLastUpdateTime: true, + editUrl: + 'https://github.com/facebook/react-native-website/blob/master/website/', + remarkPlugins: [require('@react-native-website/remark-snackplayer')], +}; + /** @type {import('@docusaurus/types').DocusaurusConfig} */ (module.exports = { title: 'React Native', @@ -53,13 +61,8 @@ const lastVersion = versions[0]; /** @type {import('@docusaurus/preset-classic').Options} */ ({ docs: { - showLastUpdateAuthor: false, - showLastUpdateTime: true, - editUrl: - 'https://github.com/facebook/react-native-website/blob/master/website/', path: '../docs', sidebarPath: require.resolve('./sidebars.json'), - remarkPlugins: [require('@react-native-website/remark-snackplayer')], editCurrentVersion: true, onlyIncludeVersions: process.env.PREVIEW_DEPLOY === 'true' @@ -70,6 +73,7 @@ const lastVersion = versions[0]; badge: false, // Do not show version badge for last RN version }, }, + ...commonDocsOptions, }, blog: { path: 'blog', @@ -93,6 +97,28 @@ const lastVersion = versions[0]; ], plugins: [ 'docusaurus-plugin-sass', + [ + 'content-docs', + /** @type {import('@docusaurus/plugin-content-docs').Options} */ + ({ + id: 'architecture', + path: 'architecture', + routeBasePath: '/architecture', + sidebarPath: require.resolve('./sidebarsArchitecture.json'), + ...commonDocsOptions + }), + ], + [ + 'content-docs', + /** @type {import('@docusaurus/plugin-content-docs').Options} */ + ({ + id: 'contributing', + path: 'contributing', + routeBasePath: '/contributing', + sidebarPath: require.resolve('./sidebarsContributing.json'), + ...commonDocsOptions + }), + ], [ '@docusaurus/plugin-pwa', { @@ -148,21 +174,6 @@ const lastVersion = versions[0]; ], }, ], - [ - 'content-docs', - /** @type {import('@docusaurus/plugin-content-docs').Options} */ - ({ - id: 'contributing', - path: 'contributing', - routeBasePath: 'contributing', - sidebarPath: require.resolve('./sidebarsContributing.json'), - showLastUpdateAuthor: false, - showLastUpdateTime: true, - editUrl: - 'https://github.com/facebook/react-native-website/blob/master/website/', - remarkPlugins: [require('@react-native-website/remark-snackplayer')], - }), - ], ], themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ @@ -219,6 +230,7 @@ const lastVersion = versions[0]; type: 'doc', docId: 'architecture-overview', position: 'right', + docsPluginId: 'architecture', }, { to: '/contributing/how-to-contribute', diff --git a/website/sidebars.json b/website/sidebars.json index 89d8490cfcb..d8f98b37187 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -229,29 +229,5 @@ "rect", "viewtoken" ] - }, - "architecture": [ - { - "type": "category", - "label": "Architecture", - "collapsed": false, - "items": [ - "architecture-overview", - { - "type": "category", - "label": "Rendering", - "collapsible": false, - "collapsed": false, - "items": [ - "fabric-renderer", - "render-pipeline", - "xplat-implementation", - "view-flattening", - "threading-model" - ] - }, - "architecture-glossary" - ] - } - ] + } } diff --git a/website/sidebarsArchitecture.json b/website/sidebarsArchitecture.json new file mode 100644 index 00000000000..5fc6c125af7 --- /dev/null +++ b/website/sidebarsArchitecture.json @@ -0,0 +1,26 @@ +{ + "architecture": [ + { + "type": "category", + "label": "Architecture", + "collapsed": false, + "items": [ + "architecture-overview", + { + "type": "category", + "label": "Rendering", + "collapsible": false, + "collapsed": false, + "items": [ + "fabric-renderer", + "render-pipeline", + "xplat-implementation", + "view-flattening", + "threading-model" + ] + }, + "architecture-glossary" + ] + } + ] +} diff --git a/website/static/_redirects b/website/static/_redirects index e9982af95e1..e04bbd11472 100644 --- a/website/static/_redirects +++ b/website/static/_redirects @@ -12,3 +12,28 @@ # Changed blog post dates /blog/2021/03/11/version-0.64 /blog/2021/03/12/version-0.64 + +# Architecture pages move to unversioned docs +/docs/architecture-overview /architecture/overview +/docs/fabric-renderer /architecture/fabric-renderer +/docs/render-pipeline /architecture/render-pipeline +/docs/xplat-implementation /architecture/xplat-implementation +/docs/view-flattening /architecture/view-flattening +/docs/threading-model /architecture/threading-model +/docs/architecture-glossary /architecture/glossary + +/docs/next/architecture-overview /architecture/overview +/docs/next/fabric-renderer /architecture/fabric-renderer +/docs/next/render-pipeline /architecture/render-pipeline +/docs/next/xplat-implementation /architecture/xplat-implementation +/docs/next/view-flattening /architecture/view-flattening +/docs/next/threading-model /architecture/threading-model +/docs/next/architecture-glossary /architecture/glossary + +/docs/0.66/architecture-overview /architecture/overview +/docs/0.66/fabric-renderer /architecture/fabric-renderer +/docs/0.66/render-pipeline /architecture/render-pipeline +/docs/0.66/xplat-implementation /architecture/xplat-implementation +/docs/0.66/view-flattening /architecture/view-flattening +/docs/0.66/threading-model /architecture/threading-model +/docs/0.66/architecture-glossary /architecture/glossary diff --git a/website/versioned_docs/version-0.66/architecture-glossary.md b/website/versioned_docs/version-0.66/architecture-glossary.md deleted file mode 100644 index 1e5a50c0ff5..00000000000 --- a/website/versioned_docs/version-0.66/architecture-glossary.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -id: architecture-glossary -title: Glossary ---- - -## Fabric Renderer - -React Native executes the same React framework code as React for the web. However, React Native renders to general platform views (host views) instead of DOM nodes (which can be considered web’s host views). Rendering to host views is made possible by the Fabric Renderer. Fabric lets React talk to each platform and manage its host view instances. The Fabric Renderer exists in JavaScript and targets interfaces made available by C++ code. [Read more about React renderers in this blog post.](https://overreacted.io/react-as-a-ui-runtime/#renderers) - -## Host platform - -The platform embedding React Native (e.g., Android, iOS, macOS, Windows). - -## Host View Tree (and Host View) - -Tree representation of views in the host platform (e.g. Android, iOS). On Android, the host views are instances of `android.view.ViewGroup`, `android.widget.TextView`, etc. which are the building blocks of the host view tree. The size and location of each host view are based on `LayoutMetrics` calculated with Yoga, and the style and content of each host view are based on information from the React Shadow Tree. - -## JavaScript Interfaces (JSI) - -A lightweight API to embed a JavaScript engine in a C++ application. Fabric uses it to communicate between Fabric’s C++ core and React. - -## Java Native Interface (JNI) - -An [API for to write Java native methods](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/) used to communicate between Fabric’s C++ core and Android, written in Java. - -## React Component - -A JavaScript function or class that instructs how to create a React Element. [Read more about React components, elements in this blog post.](https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html) - -## React Composite Components - -React Components with `render` implementations that reduce to other React Composite Components or React Host Components. - -## React Host Components or Host Components - -React Components whose view implementation is provided by a host view (e.g., `, ` ). On the Web, ReactDOM's Host components would be components like `

` and `

`. - -## React Element Tree (and React Element) - -A _React Element Tree_ is created by React in JavaScript and consists of React Elements. A _React Element_ is a plain JavaScript object that describes what should appear on the screen. It includes props, styles, and children. React Elements only exist in JavaScript and can represent instantiations of either React Composite Components or React Host Components. [Read more about React components and elements in this blog post.](https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html) - -## React Shadow Tree (and React Shadow Node) - -A _React Shadow Tree_ is created by the Fabric Renderer and consists of React Shadow Nodes. A React Shadow Node is an object that represents a React Host Component to be mounted, and contains props that originate from JavaScript. They also contain layout information (x, y, width, height). In Fabric, React Shadow Node objects exist in C++. Before Fabric, these existed in the mobile runtime heap (e.g. Android JVM). - -## Yoga Tree (and Yoga Node) - -The _Yoga Tree_ is used by [Yoga](https://yogalayout.com/) to calculate layout information for a React Shadow Tree. Each React Shadow Node typically creates a _Yoga Node_ because React Native employs Yoga to calculate layout. However, this is not a hard requirement. Fabric can also create React Shadow Nodes that do not use Yoga; the implementation of each React Shadow Node determines how to calculate layout. diff --git a/website/versioned_docs/version-0.66/architecture-overview.md b/website/versioned_docs/version-0.66/architecture-overview.md deleted file mode 100644 index 0b22e32564a..00000000000 --- a/website/versioned_docs/version-0.66/architecture-overview.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -id: architecture-overview -title: Architecture Overview ---- - -This section is a work in progress intended to share conceptual overviews of how React Native's architecture works. Its intended audience includes library authors, core contributors, and the exceptionally curious. diff --git a/website/versioned_docs/version-0.66/render-pipeline.md b/website/versioned_docs/version-0.66/render-pipeline.md deleted file mode 100644 index 1db563dce8b..00000000000 --- a/website/versioned_docs/version-0.66/render-pipeline.md +++ /dev/null @@ -1,221 +0,0 @@ ---- -id: render-pipeline -title: Render, Commit, and Mount ---- - -> This document refers to the architecture of the new renderer, [Fabric](fabric-renderer), that is in active roll-out. - -The React Native renderer goes through a sequence of work to render React logic to a [host platform](architecture-glossary#host-platform). This sequence of work is called the render pipeline and occurs for initial renders and updates to the UI state. This document goes over the render pipeline and how it differs in those scenarios. - -The render pipeline can be broken into three general phases: - -1. **Render:** React executes product logic which creates a [React Element Trees](architecture-glossary#react-element-tree-and-react-element) in JavaScript. From this tree, the renderer creates a [React Shadow Tree](architecture-glossary#react-shadow-tree-and-react-shadow-node) in C++. -2. **Commit**: After a React Shadow Tree is fully created, the renderer triggers a commit. This **promotes** both the React Element Tree and the newly created React Shadow Tree as the “next tree” to be mounted. This also schedules calculation of its layout information. -3. **Mount:** The React Shadow Tree, now with the results of layout calculation, is transformed into a [Host View Tree](architecture-glossary#host-view-tree-and-host-view). - -> The phases of the render pipeline may occur on different threads. Refer to the [Threading Model](threading-model) doc for more detail. - -![React Native renderer Data flow](/docs/assets/Architecture/renderer-pipeline/data-flow.jpg) - -The render pipeline is executed in three different scenarios: - -- [Initial Render](#initial-render) - - [Phase 1. Render](#phase-1-render) - - [Phase 2. Commit](#phase-2-commit) - - [Phase 3. Mount](#phase-3-mount) -- [React State Updates](#react-state-updates) -- [React Native Renderer State Updates](#react-native-renderer-state-updates) - ---- - -## Initial Render - -Imagine you want to render the following: - -```jsx -function MyComponent() { - return ( - - Hello, World - - ); -} - -// -``` - -In the example above, `` is a [React Element](architecture-glossary#react-element-tree-and-react-element). React recursively reduces this _React Element_ to a terminal [React Host Component](architecture-glossary#react-host-components-or-host-components) by invoking it (or its `render` method if implemented with a JavaScript class) until every _React Element_ cannot be reduced any further. Now you have a _React Element Tree_ of [React Host Components](architecture-glossary#react-host-components-or-host-components). - -### Phase 1. Render - -![Phase one: render](/docs/assets/Architecture/renderer-pipeline/phase-one-render.png) - -During this process of element reduction, as each _React Element_ is invoked, the renderer also synchronously creates a [React Shadow Node](architecture-glossary#react-shadow-tree-and-react-shadow-node). This happens only for _React Host Components_, not for [React Composite Components](architecture-glossary#react-composite-components). In the example above, the `` leads to the creation of a `ViewShadowNode` object, and the -`` leads to the creation of a `TextShadowNode` object. Notably, there is never a _React Shadow Node_ that directly represents ``. - -Whenever React creates a parent-child relationship between two _React Element Nodes_, the renderer creates the same relationship between the corresponding _React Shadow Nodes_. This is how the _React Shadow Tree_ is assembled. - -**Additional Details** - -- The operations (creation of _React Shadow Node_, creation of parent-child relationship between two _React Shadow Nodes_) are synchronous and thread-safe operations that are executed from React (JavaScript) into the renderer (C++), usually on the JavaScript thread. -- The _React Element Tree_ (and its constituent _React Element Nodes_) do not exist indefinitely. It is a temporal representation materialized by “fibers” in React. Each “fiber” that represents a host component stores a C++ pointer to the _React Shadow Node_, made possible by JSI. [Learn more about “fibers” in this document.](https://github.com/acdlite/react-fiber-architecture#what-is-a-fiber) -- The _React Shadow Tree_ is immutable. In order to update any _React Shadow Node_, the renderer creates a new _React Shadow Tree_. However, the renderer provides cloning operations to make state updates more performant (see [React State Updates](render-pipeline#react-state-updates) for more details). - -In the example above, the result of the render phase looks like this: - -![Step one](/docs/assets/Architecture/renderer-pipeline/render-pipeline-1.png) - -After the _React Shadow Tree_ is complete, the renderer triggers a commit of the _React Element Tree_. - -### Phase 2. Commit - -![Phase two: commit](/docs/assets/Architecture/renderer-pipeline/phase-two-commit.png) - -The commit phase consists of two operations: _Layout Calculation_ and _Tree Promotion_. - -- **Layout Calculation:** This operation calculates the position and size of each _React Shadow Node_. In React Native, this involves invoking Yoga to calculate the layout of each _React Shadow Node_. The actual calculation requires each _React Shadow Node_’s styles which originate from a _React Element_ in JavaScript. It also requires the layout constraints of the root of the _React Shadow Tree_, which determines the amount of available space that the resulting nodes can occupy. - -![Step two](/docs/assets/Architecture/renderer-pipeline/render-pipeline-2.png) - -- **Tree Promotion (New Tree → Next Tree):** This operation promotes the new _React Shadow Tree_ as the “next tree” to be mounted. This promotion indicates that the new _React Shadow Tree_ has all the information to be mounted and represents the latest state of the _React Element Tree_. The “next tree” mounts on the next “tick” of the UI Thread. - -**Additional Details** - -- These operations are asynchronously executed on a background thread. -- Majority of layout calculation executes entirely within C++. However, the layout calculation of some components depend on the _host platform_ (e.g. `Text`, `TextInput`, etc.). Size and position of text is specific to each _host platform_ and needs to be calculated on the _host platform_ layer. For this purpose, Yoga invokes a function defined in the _host platform_ to calculate the component’s layout. - -### Phase 3. Mount - -![Phase three: mount](/docs/assets/Architecture/renderer-pipeline/phase-three-mount.png) - -The mount phase transforms the _React Shadow Tree_ (which now contains data from layout calculation) into a _Host_ _View Tree_ with rendered pixels on the screen. As a reminder, the _React Element Tree_ looks like this: - -```jsx - - Hello, World - -``` - -At a high level, React Native renderer creates a corresponding [Host View](architecture-glossary#host-view-tree-and-host-view) for each _React Shadow Node_ and mounts it on screen. In the example above, the renderer creates an instance of `android.view.ViewGroup` for the `` and `android.widget.TextView` for `` and populates it with “Hello World”. Similarly for iOS a `UIView` is created with and text is populated with a call to `NSLayoutManager`. Each host view is then configured to use props from its React Shadow Node, and its size and position is configured using the calculated layout information. - -![Step two](/docs/assets/Architecture/renderer-pipeline/render-pipeline-3.png) - -In more detail, the mounting phase consists of these three steps: - -- **Tree Diffing:** This step computes the diff between the “previously rendered tree” and the “next tree” entirely in C++. The result is a list of atomic mutation operations to be performed on host views (e.g. `createView`, `updateView`, `removeView`, `deleteView`, etc). This step is also where the React Shadow Tree is flattened to avoid creating unnecessary host views. See [View Flattening](view-flattening) for details about this algorithm. -- **Tree Promotion (Next Tree → Rendered Tree)**: This step atomically promotes the “next tree” to “previously rendered tree” so that the next mount phase computes a diff against the proper tree. -- **View Mounting**: This step applies the atomic mutation operations onto corresponding host views. This step executes in the _host platform_ on UI thread. - -**Additional Details** - -- The operations are synchronously executed on UI thread. If the commit phase executes on background thread, the mounting phase is scheduled for the next “tick” of UI thread. On the other hand, if the commit phase executes on UI thread, mounting phase executes synchronously on the same thread. -- Scheduling, implementation, and execution of the mounting phase heavily depends on the _host platform_. For example, the renderer architecture of the mounting layer currently differs between Android and iOS. -- During the initial render, the “previously rendered tree” is empty. As such, the tree diffing step will result in a list of mutation operations that consists only of creating views, setting props, and adding views to each other. Tree diffing becomes more important for performance when processing [React State Updates](#react-state-updates). -- In current production tests, a _React Shadow Tree_ typically consists of about 600-1000 _React Shadow Nodes_ (before view flattening), the trees get reduced to ~200 nodes after view flattening. On iPad or desktop apps, this quantity may increase 10-fold. - ---- - -## React State Updates - -Let’s explore each phase of the render pipeline when the state of a _React Element Tree_ is updated. Let’s say, you’ve rendered the following component in an initial render: - -```jsx -function MyComponent() { - return ( - - - - - ); -} -``` - -Applying what was described in the [Initial Render](#initial-render) section, you would expect the following trees to be created: - -![Render pipeline 4](/docs/assets/Architecture/renderer-pipeline/render-pipeline-4.png) - -Notice that **Node 3** maps to a host view with a **red background**, and **Node 4** maps to a host view with a **blue background**. Assume that as the result of a state update in JavaScript product logic, the background of the first nested `` changes from `'red'` to `'yellow'`. This is what the new _React Element Tree_ might look: - -```jsx - - - - -``` - -**How is this update processed by React Native?** - -When a state update occurs, the renderer needs to conceptually update the _React Element Tree_ in order to update the host views that are already mounted. But in order to preserve thread safety, both the _React Element Tree_ as well as the _React Shadow Tree_ must be immutable. This means that instead of mutating the current _React Element Tree_ and _React Shadow Tree_, React must create a new copy of each tree which incorporates the new props, styles, and children. - -Let’s explore each phase of the render pipeline during a state update. - -![Phase one: render](/docs/assets/Architecture/renderer-pipeline/phase-one-render.png) - -When React creates a new _React Element Tree_ that incorporates the new state, it must clone every _React Element_ and _React Shadow Node_ that is impacted by the change. After cloning, the new _React Shadow Tree_ is committed. - -React Native renderer leverages structural sharing to minimize the overhead of immutability. When a _React Element_ is cloned to include the new state, every _React Element_ that is on the path up to the root is cloned. **React will only clone a React Element if it requires an update to its props, style, or children.** Any _React Elements_ that are unchanged by the state update are shared by the old and new trees. - -In the above example, React creates the new tree using these operations: - -1. CloneNode(**Node 3**, {backgroundColor: 'yellow'}) → **Node 3'** -2. CloneNode(**Node 2**) → **Node 2'** -3. AppendChild(**Node 2'**, **Node 3'**) -4. AppendChild(**Node 2'**, **Node 4**) -5. CloneNode(**Node 1**) → **Node 1'** -6. AppendChild(**Node 1'**, **Node 2'**) - -After these operations, **Node 1'** represents the root of the new _React Element Tree_. Let's assign **T** to the “previously rendered tree” and **T'** to the “new tree”: - -![Render pipeline 5](/docs/assets/Architecture/renderer-pipeline/render-pipeline-5.png) - -Notice how **T** and **T'** both share **Node 4**. Structural sharing improves performance and reduces memory usage. - -![Phase two: commit](/docs/assets/Architecture/renderer-pipeline/phase-two-commit.png) - -After React creates the new _React Element Tree_ and _React Shadow Tree_, it must commit them. - -- **Layout Calculation:** Similar to Layout Calculation during [Initial Render](#initial-render). One important difference is that layout calculation may cause shared _React Shadow Nodes_ to be cloned. This can happen because if the parent of a shared _React Shadow Node_ incurs a layout change, the layout of the shared _React Shadow Node_ may also change. -- **Tree Promotion (New Tree → Next Tree):** Similar to Tree Promotion during [Initial Render](#initial-render). - -- **Tree Diffing:** This step computes the diff between the “previously rendered tree” (**T**) and the “next tree” (**T'**). The result is a list of atomic mutation operations to be performed on _host views_. - - In the above example, the operations consist of: `UpdateView(**Node 3'**, {backgroundColor: '“yellow“})` - -![Phase three: mount](/docs/assets/Architecture/renderer-pipeline/phase-three-mount.png) - -- **Tree Promotion (Next Tree → Rendered Tree)**: This step atomically promotes the “next tree” to “previously rendered tree” so that the next mount phase computes a diff against the proper tree. - Diff can be calculated for any currently mounted tree with any new tree. The renderer can skip some intermediate versions of the tree. -- **View Mounting**: This step applies the atomic mutation operations onto corresponding _host views_. In the above example, only the `backgroundColor` of **View 3** will be updated (to yellow). - -![Render pipeline 6](/docs/assets/Architecture/renderer-pipeline/render-pipeline-6.png) - ---- - -## React Native Renderer State Updates - -For most information in the _Shadow Tree_, React is the single owner and single source of truth. All data originates from React and there is a single-direction flow of data. - -However, there is one exception and important mechanism: components in C++ can contain state that is not directly exposed to JavaScript, and JavaScript is not the source of truth. C++ and _Host Platform_ control this _C++ State_. Generally, this is only relevant if you are developing a complicated _Host Component_ that needs _C++ State_. The vast majority of _Host Components_ do not need this functionality. - -For example, `ScrollView` uses this mechanism to let the renderer know what’s the current offset. The update is triggered from the _host platform_, specifically from the host view that represents the `ScrollView` component. The information about offset is used in an API like [measure](https://reactnative.dev/docs/direct-manipulation#measurecallback). Since this update stems from the host platform, and does not affect the React Element Tree, this state data is held by _C++ State_. - -Conceptually, _C++ State_ updates are similar to the [React State Updates](render-pipeline#react-state-updates) described above. -With two important differences: - -1. They skip the “render phase” since React is not involved. -2. The updates can originate and happen on any thread, including the main thread. - -![Phase two: commit](/docs/assets/Architecture/renderer-pipeline/phase-two-commit.png) - -When performing a _C++ State_ update, a block of code requests an update of a `ShadowNode` (**N**) to set _C++ State_ to value **S**. React Native renderer will repeatedly attempt to get the latest committed version of **N**, clone it with a new state **S**, and commit **N’** to the tree. If React, or another _C++ State_ update, has performed another commit during this time, the _C++ State_ commit will fail and the renderer will retry the _C++ State_ update many times until a commit succeeds. This prevents source-of-truth collisions and races. - -![Phase three: mount](/docs/assets/Architecture/renderer-pipeline/phase-three-mount.png) - -The _Mount Phase_ is practically identical to the [Mount Phase of React State Updates](#react-state-updates). The renderer still needs to recompute layout perform a tree diff, etc. See above sections for details. diff --git a/website/versioned_docs/version-0.66/threading-model.md b/website/versioned_docs/version-0.66/threading-model.md deleted file mode 100644 index c3b0398cb67..00000000000 --- a/website/versioned_docs/version-0.66/threading-model.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -id: threading-model -title: Threading Model ---- - -> This document refers to the architecture of the new renderer, [Fabric](fabric-renderer), that is in active roll-out. - -#### The React Native renderer distributes the work of the [render pipeline](render-pipeline) across multiple threads. - -Here we define the threading model and provide some examples to illustrate thread usage of the render pipeline. - -React Native renderer is designed to be thread safe. At a high level thread safety is guaranteed by using immutable data structures in the internals of the framework (enforced by C++ “const correctness” feature). This means that every update in React creates or clones new objects in the renderer instead of updating data structures. This allows the framework to expose thread safe and synchronous APIs to React. - -The renderer uses three different threads: - -- **UI thread** (often called main): The only thread that can manipulate host views. -- **JavaScript thread**: This is where React’s render phase is executed. -- **Background thread**: Thread dedicated to layout. - -Let’s review the supported scenarios of execution for each phase: - -
- Threading model symbols -
- -## Render Scenarios - -### Render in a Background Thread - -This is the most common scenario where most of the render pipeline happens on JavaScript and background thread. - -
- Threading model use case one -
- ---- - -### Render in the UI Thread - -When there is a high priority event on the UI Thread, the renderer is able to execute all the render pipeline synchronously on the UI thread. - -
- Threading model use case two -
- ---- - -### Default or continuous event interruption - -This scenario shows the interruption of the render phase by a low priority event in the UI thread. React and the React Native renderer are able to interrupt the render phase and merge its state with a low priority event that is executed on the UI thread. In this case the render process continues executing in the background thread. - -
- Threading model use case three -
- ---- - -### Discrete event interruption - -The render phase is interruptible. This scenario shows the interruption of the render phase by a high priority event in the UI thread. React and the renderer are able to interrupt the render phase and merge its state with a high priority event that was executed on the UI thread. The render phase executes synchronously on the UI thread. - -
- Threading model use case four -
- ---- - -### Background thread batches updates from JavaScript - -Before background thread dispatches update to UI thread, it checks if a newer update hasn’t come in from JavaScript. This way, the renderer doesn’t render stale state when it knows a newer state is coming it. - -
- Threading model use case five -
- ---- - -### C++ State update - -Update originating on UI thread and skips rendering phase. See [React Native Renderer State Updates](render-pipeline#react-native-renderer-state-updates) for more details. - -
- Threading model use case six -
diff --git a/website/versioned_docs/version-0.66/view-flattening.md b/website/versioned_docs/version-0.66/view-flattening.md deleted file mode 100644 index 397068ac1bc..00000000000 --- a/website/versioned_docs/version-0.66/view-flattening.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: view-flattening -title: View Flattening ---- - -> This document refers to the architecture of the new renderer, [Fabric](fabric-renderer), that is in active roll-out. - -#### View Flattening is an optimization by the React Native renderer to avoid deep layout trees. - -The React API is designed to be declarative and reusable through composition. This provides a great model for intuitive development. However, in implementation, these qualities of the API lead to the creation of deep [React Element Trees](architecture-glossary#react-element-tree-and-react-element), where a large majority of React Element Nodes only affect the layout of a View and don’t render anything on the screen. We call these types of nodes **“Layout-Only”** Nodes. - -Conceptually, each of the Nodes of the React Element Tree have a 1:1 relationship with a view on the screen, therefore rendering a deep React Element Tree that is composed by a large amount of “Layout-Only” Node leads to poor performance during rendering. - -Here is a common use case that is affected by the cost of "Layout Only" views. - -Imagine you want to render an image and a title that is handled by the `TitleComponent`, and you include this component as a child of the `ContainerComponent` that has some margin styles. After decomposing the components, the React code would look like this: - -```jsx -function MyComponent() { - return ( - // ReactAppComponent - // ContainerComponent - // TitleComponent - - This is a title - - - - ); -} -``` - -As part of the render process, React Native will produce the following trees: - -![Diagram one](/docs/assets/Architecture/view-flattening/diagram-one.png) - -Note that the Views (2) and (3) are “Layout Only” views, because they are rendered on the screen but they only render a `margin` of `10 px` on top of their children. - -To improve the performance of these types of React Element Trees, the renderer implements a View Flattening mechanism that merges or flattens these types of Nodes, reducing the depth of the [host view](architecture-glossary#host-view-tree-and-host-view) hierarchy that is rendered on the screen. This algorithm takes into consideration props like: `margin`, `padding`, `backgroundColor`, `opacity`, etc. - -The View Flattening algorithm is integrated by design as part of the diffing stage of the renderer, which means that we don’t use extra CPU cycles to optimize the React Element Tree flattening these types of views. As the rest of the core, the View flattening algorithm is implemented in C++ and its benefits are shared by default on all supported platforms. - -In the case of the previous example, the Views (2) and (3) would be flattened as part of the “diffing algorithm” and as a result their styles will be merged into the View (1): - -![Diagram two](/docs/assets/Architecture/view-flattening/diagram-two.png) - -It is important to note that this optimization allows the renderer to avoid the creation and render of two host views. From the user’s perspective there are no visible changes on the screen. diff --git a/website/versioned_docs/version-0.66/xplat-implementation.md b/website/versioned_docs/version-0.66/xplat-implementation.md deleted file mode 100644 index dc40876a4dc..00000000000 --- a/website/versioned_docs/version-0.66/xplat-implementation.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -id: xplat-implementation -title: Cross Platform Implementation ---- - -> This document refers to the architecture of the new renderer, [Fabric](fabric-renderer), that is in active roll-out. - -#### The React Native renderer utilizes a core render implementation to be shared across platforms - -In the previous render system of React Native, the **[React Shadow Tree](architecture-glossary#react-shadow-tree-and-react-shadow-node)**, layout logic, and **[View Flattening](view-flattening.md)** algorithm were implemented once for each platform. The current renderer was designed to be a cross-platform solution by sharing a core C++ implementation. - -The React Native team intends to incorporate an animation system into the render system and also extend the React Native render system to new platforms such as Windows, and operating systems in game consoles, televisions, and more. - -Leveraging C++ for the core render system introduces several advantages. A single implementation reduces the cost of development and maintenance. It improves the performance of creating React Shadow Trees and layout calculation because the overhead of integrating [Yoga](architecture-glossary#yoga-tree-and-yoga-node) with the renderer is minimized on Android (i.e. no more [JNI](architecture-glossary#java-native-interface-jni) for Yoga). Finally, the memory footprint of each React Shadow Node is smaller in C++ than it would be if allocated from Kotlin or Swift. - -The team is also leveraging C++ features that enforce immutability to ensure there are no issues related to concurrent access to shared but not protected resources. - -It is important to recognize that the renderer use case for Android still incurs the cost of [JNI](architecture-glossary#java-native-interface-jni) for two primary use cases: - -- Layout calculation of complex views (e.g. `Text`, `TextInput`, etc.) requires sending props over JNI. -- The mount phase requires sending mutation operations over JNI. - -The team is exploring replacing `ReadableMap` with a new mechanism to serialize data using `ByteBuffer` to reduce overhead of JNI. Our goal is to reduce overhead of JNI by 35–50%. - -The renderer provides two sides of its C++ APIs: - -- **(i)** to communicate with React -- **(ii)** to communicate with the host platform - -For **(i)**, React communicates with the renderer to **render** a React Tree and to “listen” for **events** (e.g. `onLayout`, `onKeyPress`, touch, etc). - -For **(ii)**, the React Native renderer communicates with the host platform to mount host views on the screen (create, insert, update or delete of host views) and it listens for **events** that are generated by the user on the host platform. - -![Cross-platform implementation diagram](/docs/assets/Architecture/xplat-implementation/xplat-implementation-diagram.png) diff --git a/website/versioned_docs/version-0.67/architecture-glossary.md b/website/versioned_docs/version-0.67/architecture-glossary.md deleted file mode 100644 index 1e5a50c0ff5..00000000000 --- a/website/versioned_docs/version-0.67/architecture-glossary.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -id: architecture-glossary -title: Glossary ---- - -## Fabric Renderer - -React Native executes the same React framework code as React for the web. However, React Native renders to general platform views (host views) instead of DOM nodes (which can be considered web’s host views). Rendering to host views is made possible by the Fabric Renderer. Fabric lets React talk to each platform and manage its host view instances. The Fabric Renderer exists in JavaScript and targets interfaces made available by C++ code. [Read more about React renderers in this blog post.](https://overreacted.io/react-as-a-ui-runtime/#renderers) - -## Host platform - -The platform embedding React Native (e.g., Android, iOS, macOS, Windows). - -## Host View Tree (and Host View) - -Tree representation of views in the host platform (e.g. Android, iOS). On Android, the host views are instances of `android.view.ViewGroup`, `android.widget.TextView`, etc. which are the building blocks of the host view tree. The size and location of each host view are based on `LayoutMetrics` calculated with Yoga, and the style and content of each host view are based on information from the React Shadow Tree. - -## JavaScript Interfaces (JSI) - -A lightweight API to embed a JavaScript engine in a C++ application. Fabric uses it to communicate between Fabric’s C++ core and React. - -## Java Native Interface (JNI) - -An [API for to write Java native methods](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/) used to communicate between Fabric’s C++ core and Android, written in Java. - -## React Component - -A JavaScript function or class that instructs how to create a React Element. [Read more about React components, elements in this blog post.](https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html) - -## React Composite Components - -React Components with `render` implementations that reduce to other React Composite Components or React Host Components. - -## React Host Components or Host Components - -React Components whose view implementation is provided by a host view (e.g., `, ` ). On the Web, ReactDOM's Host components would be components like `

` and `

`. - -## React Element Tree (and React Element) - -A _React Element Tree_ is created by React in JavaScript and consists of React Elements. A _React Element_ is a plain JavaScript object that describes what should appear on the screen. It includes props, styles, and children. React Elements only exist in JavaScript and can represent instantiations of either React Composite Components or React Host Components. [Read more about React components and elements in this blog post.](https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html) - -## React Shadow Tree (and React Shadow Node) - -A _React Shadow Tree_ is created by the Fabric Renderer and consists of React Shadow Nodes. A React Shadow Node is an object that represents a React Host Component to be mounted, and contains props that originate from JavaScript. They also contain layout information (x, y, width, height). In Fabric, React Shadow Node objects exist in C++. Before Fabric, these existed in the mobile runtime heap (e.g. Android JVM). - -## Yoga Tree (and Yoga Node) - -The _Yoga Tree_ is used by [Yoga](https://yogalayout.com/) to calculate layout information for a React Shadow Tree. Each React Shadow Node typically creates a _Yoga Node_ because React Native employs Yoga to calculate layout. However, this is not a hard requirement. Fabric can also create React Shadow Nodes that do not use Yoga; the implementation of each React Shadow Node determines how to calculate layout. diff --git a/website/versioned_docs/version-0.67/architecture-overview.md b/website/versioned_docs/version-0.67/architecture-overview.md deleted file mode 100644 index a29e48b2475..00000000000 --- a/website/versioned_docs/version-0.67/architecture-overview.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -id: architecture-overview -title: Architecture Overview ---- - -This section is a work in progress intended to share conceptual overviews of how React Native's architecture works. Its intended audience includes library authors, core contributors, and the exceptionally curious. It is not a requirement to be familiar with this material to use React Native. diff --git a/website/versioned_docs/version-0.67/fabric-renderer.md b/website/versioned_docs/version-0.67/fabric-renderer.md deleted file mode 100644 index 5e000f594af..00000000000 --- a/website/versioned_docs/version-0.67/fabric-renderer.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -id: fabric-renderer -title: Fabric ---- - -Fabric is React Native's new rendering system, a conceptual evolution of the legacy render system. The core principles are to unify more render logic in C++, improve interoperability with [host platforms](architecture-glossary#host-platform), and to unlock new capabilities for React Native. Development began in 2018 and in 2021, React Native in the Facebook app is backed by the new renderer. - -This documentation provides an overview of the [new renderer](architecture-glossary#fabric-render) and its concepts. It avoids platform specifics and doesn’t contain any code snippets or pointers. This documentation covers key concepts, motivation, benefits, and an overview of the render pipeline in different scenarios. - -## Motivations and Benefits of the new renderer - -The render architecture was created to unlock better user experiences that weren’t possible with the legacy architecture. Some examples include: - -- With improved interoperability between [host views](architecture-glossary#host-view-tree-and-host-view) and React views, the renderer is able to measure and render React surfaces synchronously. In the legacy architecture, React Native layout was asynchronous which led to a layout “jump” issue when embedding a React Native rendered view in a _host view_. -- With support of multi-priority and synchronous events, the renderer can prioritize certain user interactions to ensure they are handled in a timely manner. -- [Integration with React Suspense](https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html) which allows for more intuitive design of data fetching in React apps. -- Enable React [Concurrent Features](https://github.com/reactwg/react-18/discussions/4) on React Native. -- Easier to implement server side rendering for React Native. - -The new architecture also provides benefits in code quality, performance, and extensibility: - -- **Type safety:** code generation to ensure type safety across the JS and [host platforms](architecture-glossary#host-platform). The code generation uses JavaScript component declarations as source of truth to generate C++ structs to hold the props. Mismatch between JavaScript and host component props triggers a build error. -- **Shared C++ core**: the renderer is implemented in C++ and the core is shared among platforms. This increases consistency and makes it easier to adopt React Native on new platforms. -- **Better Host Platform Interoperability**: Synchronous and thread-safe layout calculation improves user experiences when embedding host components into React Native, which means easier integration with host platform frameworks that require synchronous APIs. -- **Improved Performance**: With the new cross-platform implementation of the renderer system, every platform benefits from performance improvements that may have been motivated by limitations of one platform. For example, view flattening was originally a performance solution for Android and is now provided by default on both Android and iOS. -- **Consistency**: The new render system is cross-platform, it is easier to keep consistency among different platforms. -- **Faster Startup**: Host components are lazily initialized by default. -- **Less serialization of data between JS and host platform**: React used to transfer data between JavaScript and _host platform_ as serialized JSON. The new renderer improves the transfer of data by accessing JavaScript values directly using [JavaScript Interfaces (JSI)](architecture-glossary#javascript-interfaces-jsi). diff --git a/website/versioned_docs/version-0.67/render-pipeline.md b/website/versioned_docs/version-0.67/render-pipeline.md deleted file mode 100644 index ab15f888769..00000000000 --- a/website/versioned_docs/version-0.67/render-pipeline.md +++ /dev/null @@ -1,222 +0,0 @@ ---- -id: render-pipeline -title: Render, Commit, and Mount ---- - -> This document refers to the architecture of the new renderer, [Fabric](fabric-renderer), that is in active roll-out. - -The React Native renderer goes through a sequence of work to render React logic to a [host platform](architecture-glossary#host-platform). This sequence of work is called the render pipeline and occurs for initial renders and updates to the UI state. This document goes over the render pipeline and how it differs in those scenarios. - -The render pipeline can be broken into three general phases: - -1. **Render:** React executes product logic which creates a [React Element Tree](architecture-glossary#react-element-tree-and-react-element) in JavaScript. From this tree, the renderer creates a [React Shadow Tree](architecture-glossary#react-shadow-tree-and-react-shadow-node) in C++. -2. **Commit**: After a React Shadow Tree is fully created, the renderer triggers a commit. This **promotes** both the React Element Tree and the newly created React Shadow Tree as the “next tree” to be mounted. This also schedules calculation of its layout information. -3. **Mount:** The React Shadow Tree, now with the results of layout calculation, is transformed into a [Host View Tree](architecture-glossary#host-view-tree-and-host-view). - -> The phases of the render pipeline may occur on different threads. Refer to the [Threading Model](threading-model) doc for more detail. - -![React Native renderer Data flow](/docs/assets/Architecture/renderer-pipeline/data-flow.jpg) - ---- - -## Initial Render - -Imagine you want to render the following: - -```jsx -function MyComponent() { - return ( - - Hello, World - - ); -} - -// -``` - -In the example above, `` is a [React Element](architecture-glossary#react-element-tree-and-react-element). React recursively reduces this _React Element_ to a terminal [React Host Component](architecture-glossary#react-host-components-or-host-components) by invoking it (or its `render` method if implemented with a JavaScript class) until every _React Element_ cannot be reduced any further. Now you have a _React Element Tree_ of [React Host Components](architecture-glossary#react-host-components-or-host-components). - -### Phase 1. Render - -![Phase one: render](/docs/assets/Architecture/renderer-pipeline/phase-one-render.png) - -During this process of element reduction, as each _React Element_ is invoked, the renderer also synchronously creates a [React Shadow Node](architecture-glossary#react-shadow-tree-and-react-shadow-node). This happens only for _React Host Components_, not for [React Composite Components](architecture-glossary#react-composite-components). In the example above, the `` leads to the creation of a `ViewShadowNode` object, and the -`` leads to the creation of a `TextShadowNode` object. Notably, there is never a _React Shadow Node_ that directly represents ``. - -Whenever React creates a parent-child relationship between two _React Element Nodes_, the renderer creates the same relationship between the corresponding _React Shadow Nodes_. This is how the _React Shadow Tree_ is assembled. - -**Additional Details** - -- The operations (creation of _React Shadow Node_, creation of parent-child relationship between two _React Shadow Nodes_) are synchronous and thread-safe operations that are executed from React (JavaScript) into the renderer (C++), usually on the JavaScript thread. -- The _React Element Tree_ (and its constituent _React Element Nodes_) do not exist indefinitely. It is a temporal representation materialized by “fibers” in React. Each “fiber” that represents a host component stores a C++ pointer to the _React Shadow Node_, made possible by JSI. [Learn more about “fibers” in this document.](https://github.com/acdlite/react-fiber-architecture#what-is-a-fiber) -- The _React Shadow Tree_ is immutable. In order to update any _React Shadow Node_, the renderer creates a new _React Shadow Tree_. However, the renderer provides cloning operations to make state updates more performant (see [React State Updates](render-pipeline#react-state-updates) for more details). - -In the example above, the result of the render phase looks like this: - -![Step one](/docs/assets/Architecture/renderer-pipeline/render-pipeline-1.png) - -After the _React Shadow Tree_ is complete, the renderer triggers a commit of the _React Element Tree_. - -### Phase 2. Commit - -![Phase two: commit](/docs/assets/Architecture/renderer-pipeline/phase-two-commit.png) - -The commit phase consists of two operations: _Layout Calculation_ and _Tree Promotion_. - -- **Layout Calculation:** This operation calculates the position and size of each _React Shadow Node_. In React Native, this involves invoking Yoga to calculate the layout of each _React Shadow Node_. The actual calculation requires each _React Shadow Node_’s styles which originate from a _React Element_ in JavaScript. It also requires the layout constraints of the root of the _React Shadow Tree_, which determines the amount of available space that the resulting nodes can occupy. - -![Step two](/docs/assets/Architecture/renderer-pipeline/render-pipeline-2.png) - -- **Tree Promotion (New Tree → Next Tree):** This operation promotes the new _React Shadow Tree_ as the “next tree” to be mounted. This promotion indicates that the new _React Shadow Tree_ has all the information to be mounted and represents the latest state of the _React Element Tree_. The “next tree” mounts on the next “tick” of the UI Thread. - -**Additional Details** - -- These operations are asynchronously executed on a background thread. -- Majority of layout calculation executes entirely within C++. However, the layout calculation of some components depend on the _host platform_ (e.g. `Text`, `TextInput`, etc.). Size and position of text is specific to each _host platform_ and needs to be calculated on the _host platform_ layer. For this purpose, Yoga invokes a function defined in the _host platform_ to calculate the component’s layout. - -### Phase 3. Mount - -![Phase three: mount](/docs/assets/Architecture/renderer-pipeline/phase-three-mount.png) - -The mount phase transforms the _React Shadow Tree_ (which now contains data from layout calculation) into a _Host_ _View Tree_ with rendered pixels on the screen. As a reminder, the _React Element Tree_ looks like this: - -```jsx - - Hello, World - -``` - -At a high level, React Native renderer creates a corresponding [Host View](architecture-glossary#host-view-tree-and-host-view) for each _React Shadow Node_ and mounts it on screen. In the example above, the renderer creates an instance of `android.view.ViewGroup` for the `` and `android.widget.TextView` for `` and populates it with “Hello World”. Similarly for iOS a `UIView` is created with and text is populated with a call to `NSLayoutManager`. Each host view is then configured to use props from its React Shadow Node, and its size and position is configured using the calculated layout information. - -![Step two](/docs/assets/Architecture/renderer-pipeline/render-pipeline-3.png) - -In more detail, the mounting phase consists of these three steps: - -- **Tree Diffing:** This step computes the diff between the “previously rendered tree” and the “next tree” entirely in C++. The result is a list of atomic mutation operations to be performed on host views (e.g. `createView`, `updateView`, `removeView`, `deleteView`, etc). This step is also where the React Shadow Tree is flattened to avoid creating unnecessary host views. See [View Flattening](view-flattening) for details about this algorithm. -- **Tree Promotion (Next Tree → Rendered Tree)**: This step atomically promotes the “next tree” to “previously rendered tree” so that the next mount phase computes a diff against the proper tree. -- **View Mounting**: This step applies the atomic mutation operations onto corresponding host views. This step executes in the _host platform_ on UI thread. - -**Additional Details** - -- The operations are synchronously executed on UI thread. If the commit phase executes on background thread, the mounting phase is scheduled for the next “tick” of UI thread. On the other hand, if the commit phase executes on UI thread, mounting phase executes synchronously on the same thread. -- Scheduling, implementation, and execution of the mounting phase heavily depends on the _host platform_. For example, the renderer architecture of the mounting layer currently differs between Android and iOS. -- During the initial render, the “previously rendered tree” is empty. As such, the tree diffing step will result in a list of mutation operations that consists only of creating views, setting props, and adding views to each other. Tree diffing becomes more important for performance when processing [React State Updates](#react-state-updates). -- In current production tests, a _React Shadow Tree_ typically consists of about 600-1000 _React Shadow Nodes_ (before view flattening), the trees get reduced to ~200 nodes after view flattening. On iPad or desktop apps, this quantity may increase 10-fold. - ---- - -## React State Updates - -Let’s explore each phase of the render pipeline when the state of a _React Element Tree_ is updated. Let’s say, you’ve rendered the following component in an initial render: - -```jsx -function MyComponent() { - return ( - - - - - ); -} -``` - -Applying what was described in the [Initial Render](#initial-render) section, you would expect the following trees to be created: - -![Render pipeline 4](/docs/assets/Architecture/renderer-pipeline/render-pipeline-4.png) - -Notice that **Node 3** maps to a host view with a **red background**, and **Node 4** maps to a host view with a **blue background**. Assume that as the result of a state update in JavaScript product logic, the background of the first nested `` changes from `'red'` to `'yellow'`. This is what the new _React Element Tree_ might look: - -```jsx - - - - -``` - -**How is this update processed by React Native?** - -When a state update occurs, the renderer needs to conceptually update the _React Element Tree_ in order to update the host views that are already mounted. But in order to preserve thread safety, both the _React Element Tree_ as well as the _React Shadow Tree_ must be immutable. This means that instead of mutating the current _React Element Tree_ and _React Shadow Tree_, React must create a new copy of each tree which incorporates the new props, styles, and children. - -Let’s explore each phase of the render pipeline during a state update. - -### Phase 1: Render - -![Phase one: render](/docs/assets/Architecture/renderer-pipeline/phase-one-render.png) - -When React creates a new _React Element Tree_ that incorporates the new state, it must clone every _React Element_ and _React Shadow Node_ that is impacted by the change. After cloning, the new _React Shadow Tree_ is committed. - -React Native renderer leverages structural sharing to minimize the overhead of immutability. When a _React Element_ is cloned to include the new state, every _React Element_ that is on the path up to the root is cloned. **React will only clone a React Element if it requires an update to its props, style, or children.** Any _React Elements_ that are unchanged by the state update are shared by the old and new trees. - -In the above example, React creates the new tree using these operations: - -1. CloneNode(**Node 3**, {backgroundColor: 'yellow'}) → **Node 3'** -2. CloneNode(**Node 2**) → **Node 2'** -3. AppendChild(**Node 2'**, **Node 3'**) -4. AppendChild(**Node 2'**, **Node 4**) -5. CloneNode(**Node 1**) → **Node 1'** -6. AppendChild(**Node 1'**, **Node 2'**) - -After these operations, **Node 1'** represents the root of the new _React Element Tree_. Let's assign **T** to the “previously rendered tree” and **T'** to the “new tree”: - -![Render pipeline 5](/docs/assets/Architecture/renderer-pipeline/render-pipeline-5.png) - -Notice how **T** and **T'** both share **Node 4**. Structural sharing improves performance and reduces memory usage. - -### Phase 2: Commit - -![Phase two: commit](/docs/assets/Architecture/renderer-pipeline/phase-two-commit.png) - -After React creates the new _React Element Tree_ and _React Shadow Tree_, it must commit them. - -- **Layout Calculation:** Similar to Layout Calculation during [Initial Render](#initial-render). One important difference is that layout calculation may cause shared _React Shadow Nodes_ to be cloned. This can happen because if the parent of a shared _React Shadow Node_ incurs a layout change, the layout of the shared _React Shadow Node_ may also change. -- **Tree Promotion (New Tree → Next Tree):** Similar to Tree Promotion during [Initial Render](#initial-render). - -- **Tree Diffing:** This step computes the diff between the “previously rendered tree” (**T**) and the “next tree” (**T'**). The result is a list of atomic mutation operations to be performed on _host views_. - - In the above example, the operations consist of: `UpdateView(**Node 3'**, {backgroundColor: '“yellow“})` - -### Phase 3: Mount - -![Phase three: mount](/docs/assets/Architecture/renderer-pipeline/phase-three-mount.png) - -- **Tree Promotion (Next Tree → Rendered Tree)**: This step atomically promotes the “next tree” to “previously rendered tree” so that the next mount phase computes a diff against the proper tree. - Diff can be calculated for any currently mounted tree with any new tree. The renderer can skip some intermediate versions of the tree. -- **View Mounting**: This step applies the atomic mutation operations onto corresponding _host views_. In the above example, only the `backgroundColor` of **View 3** will be updated (to yellow). - -![Render pipeline 6](/docs/assets/Architecture/renderer-pipeline/render-pipeline-6.png) - ---- - -## React Native Renderer State Updates - -For most information in the _Shadow Tree_, React is the single owner and single source of truth. All data originates from React and there is a single-direction flow of data. - -However, there is one exception and important mechanism: components in C++ can contain state that is not directly exposed to JavaScript, and JavaScript is not the source of truth. C++ and _Host Platform_ control this _C++ State_. Generally, this is only relevant if you are developing a complicated _Host Component_ that needs _C++ State_. The vast majority of _Host Components_ do not need this functionality. - -For example, `ScrollView` uses this mechanism to let the renderer know what’s the current offset. The update is triggered from the _host platform_, specifically from the host view that represents the `ScrollView` component. The information about offset is used in an API like [measure](https://reactnative.dev/docs/direct-manipulation#measurecallback). Since this update stems from the host platform, and does not affect the React Element Tree, this state data is held by _C++ State_. - -Conceptually, _C++ State_ updates are similar to the [React State Updates](render-pipeline#react-state-updates) described above. -With two important differences: - -1. They skip the “render phase” since React is not involved. -2. The updates can originate and happen on any thread, including the main thread. - -### Phase 2: Commit - -![Phase two: commit](/docs/assets/Architecture/renderer-pipeline/phase-two-commit.png) - -When performing a _C++ State_ update, a block of code requests an update of a `ShadowNode` (**N**) to set _C++ State_ to value **S**. React Native renderer will repeatedly attempt to get the latest committed version of **N**, clone it with a new state **S**, and commit **N’** to the tree. If React, or another _C++ State_ update, has performed another commit during this time, the _C++ State_ commit will fail and the renderer will retry the _C++ State_ update many times until a commit succeeds. This prevents source-of-truth collisions and races. - -### Phase 3: Mount - -![Phase three: mount](/docs/assets/Architecture/renderer-pipeline/phase-three-mount.png) - -The _Mount Phase_ is practically identical to the [Mount Phase of React State Updates](#react-state-updates). The renderer still needs to recompute layout perform a tree diff, etc. See above sections for details. diff --git a/website/versioned_docs/version-0.67/threading-model.md b/website/versioned_docs/version-0.67/threading-model.md deleted file mode 100644 index c3b0398cb67..00000000000 --- a/website/versioned_docs/version-0.67/threading-model.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -id: threading-model -title: Threading Model ---- - -> This document refers to the architecture of the new renderer, [Fabric](fabric-renderer), that is in active roll-out. - -#### The React Native renderer distributes the work of the [render pipeline](render-pipeline) across multiple threads. - -Here we define the threading model and provide some examples to illustrate thread usage of the render pipeline. - -React Native renderer is designed to be thread safe. At a high level thread safety is guaranteed by using immutable data structures in the internals of the framework (enforced by C++ “const correctness” feature). This means that every update in React creates or clones new objects in the renderer instead of updating data structures. This allows the framework to expose thread safe and synchronous APIs to React. - -The renderer uses three different threads: - -- **UI thread** (often called main): The only thread that can manipulate host views. -- **JavaScript thread**: This is where React’s render phase is executed. -- **Background thread**: Thread dedicated to layout. - -Let’s review the supported scenarios of execution for each phase: - -
- Threading model symbols -
- -## Render Scenarios - -### Render in a Background Thread - -This is the most common scenario where most of the render pipeline happens on JavaScript and background thread. - -
- Threading model use case one -
- ---- - -### Render in the UI Thread - -When there is a high priority event on the UI Thread, the renderer is able to execute all the render pipeline synchronously on the UI thread. - -
- Threading model use case two -
- ---- - -### Default or continuous event interruption - -This scenario shows the interruption of the render phase by a low priority event in the UI thread. React and the React Native renderer are able to interrupt the render phase and merge its state with a low priority event that is executed on the UI thread. In this case the render process continues executing in the background thread. - -
- Threading model use case three -
- ---- - -### Discrete event interruption - -The render phase is interruptible. This scenario shows the interruption of the render phase by a high priority event in the UI thread. React and the renderer are able to interrupt the render phase and merge its state with a high priority event that was executed on the UI thread. The render phase executes synchronously on the UI thread. - -
- Threading model use case four -
- ---- - -### Background thread batches updates from JavaScript - -Before background thread dispatches update to UI thread, it checks if a newer update hasn’t come in from JavaScript. This way, the renderer doesn’t render stale state when it knows a newer state is coming it. - -
- Threading model use case five -
- ---- - -### C++ State update - -Update originating on UI thread and skips rendering phase. See [React Native Renderer State Updates](render-pipeline#react-native-renderer-state-updates) for more details. - -
- Threading model use case six -
diff --git a/website/versioned_docs/version-0.67/view-flattening.md b/website/versioned_docs/version-0.67/view-flattening.md deleted file mode 100644 index 397068ac1bc..00000000000 --- a/website/versioned_docs/version-0.67/view-flattening.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: view-flattening -title: View Flattening ---- - -> This document refers to the architecture of the new renderer, [Fabric](fabric-renderer), that is in active roll-out. - -#### View Flattening is an optimization by the React Native renderer to avoid deep layout trees. - -The React API is designed to be declarative and reusable through composition. This provides a great model for intuitive development. However, in implementation, these qualities of the API lead to the creation of deep [React Element Trees](architecture-glossary#react-element-tree-and-react-element), where a large majority of React Element Nodes only affect the layout of a View and don’t render anything on the screen. We call these types of nodes **“Layout-Only”** Nodes. - -Conceptually, each of the Nodes of the React Element Tree have a 1:1 relationship with a view on the screen, therefore rendering a deep React Element Tree that is composed by a large amount of “Layout-Only” Node leads to poor performance during rendering. - -Here is a common use case that is affected by the cost of "Layout Only" views. - -Imagine you want to render an image and a title that is handled by the `TitleComponent`, and you include this component as a child of the `ContainerComponent` that has some margin styles. After decomposing the components, the React code would look like this: - -```jsx -function MyComponent() { - return ( - // ReactAppComponent - // ContainerComponent - // TitleComponent - - This is a title - - - - ); -} -``` - -As part of the render process, React Native will produce the following trees: - -![Diagram one](/docs/assets/Architecture/view-flattening/diagram-one.png) - -Note that the Views (2) and (3) are “Layout Only” views, because they are rendered on the screen but they only render a `margin` of `10 px` on top of their children. - -To improve the performance of these types of React Element Trees, the renderer implements a View Flattening mechanism that merges or flattens these types of Nodes, reducing the depth of the [host view](architecture-glossary#host-view-tree-and-host-view) hierarchy that is rendered on the screen. This algorithm takes into consideration props like: `margin`, `padding`, `backgroundColor`, `opacity`, etc. - -The View Flattening algorithm is integrated by design as part of the diffing stage of the renderer, which means that we don’t use extra CPU cycles to optimize the React Element Tree flattening these types of views. As the rest of the core, the View flattening algorithm is implemented in C++ and its benefits are shared by default on all supported platforms. - -In the case of the previous example, the Views (2) and (3) would be flattened as part of the “diffing algorithm” and as a result their styles will be merged into the View (1): - -![Diagram two](/docs/assets/Architecture/view-flattening/diagram-two.png) - -It is important to note that this optimization allows the renderer to avoid the creation and render of two host views. From the user’s perspective there are no visible changes on the screen. diff --git a/website/versioned_docs/version-0.67/xplat-implementation.md b/website/versioned_docs/version-0.67/xplat-implementation.md deleted file mode 100644 index dc40876a4dc..00000000000 --- a/website/versioned_docs/version-0.67/xplat-implementation.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -id: xplat-implementation -title: Cross Platform Implementation ---- - -> This document refers to the architecture of the new renderer, [Fabric](fabric-renderer), that is in active roll-out. - -#### The React Native renderer utilizes a core render implementation to be shared across platforms - -In the previous render system of React Native, the **[React Shadow Tree](architecture-glossary#react-shadow-tree-and-react-shadow-node)**, layout logic, and **[View Flattening](view-flattening.md)** algorithm were implemented once for each platform. The current renderer was designed to be a cross-platform solution by sharing a core C++ implementation. - -The React Native team intends to incorporate an animation system into the render system and also extend the React Native render system to new platforms such as Windows, and operating systems in game consoles, televisions, and more. - -Leveraging C++ for the core render system introduces several advantages. A single implementation reduces the cost of development and maintenance. It improves the performance of creating React Shadow Trees and layout calculation because the overhead of integrating [Yoga](architecture-glossary#yoga-tree-and-yoga-node) with the renderer is minimized on Android (i.e. no more [JNI](architecture-glossary#java-native-interface-jni) for Yoga). Finally, the memory footprint of each React Shadow Node is smaller in C++ than it would be if allocated from Kotlin or Swift. - -The team is also leveraging C++ features that enforce immutability to ensure there are no issues related to concurrent access to shared but not protected resources. - -It is important to recognize that the renderer use case for Android still incurs the cost of [JNI](architecture-glossary#java-native-interface-jni) for two primary use cases: - -- Layout calculation of complex views (e.g. `Text`, `TextInput`, etc.) requires sending props over JNI. -- The mount phase requires sending mutation operations over JNI. - -The team is exploring replacing `ReadableMap` with a new mechanism to serialize data using `ByteBuffer` to reduce overhead of JNI. Our goal is to reduce overhead of JNI by 35–50%. - -The renderer provides two sides of its C++ APIs: - -- **(i)** to communicate with React -- **(ii)** to communicate with the host platform - -For **(i)**, React communicates with the renderer to **render** a React Tree and to “listen” for **events** (e.g. `onLayout`, `onKeyPress`, touch, etc). - -For **(ii)**, the React Native renderer communicates with the host platform to mount host views on the screen (create, insert, update or delete of host views) and it listens for **events** that are generated by the user on the host platform. - -![Cross-platform implementation diagram](/docs/assets/Architecture/xplat-implementation/xplat-implementation-diagram.png) diff --git a/website/versioned_sidebars/version-0.66-sidebars.json b/website/versioned_sidebars/version-0.66-sidebars.json index b1479d02ff1..7661d5ca96f 100644 --- a/website/versioned_sidebars/version-0.66-sidebars.json +++ b/website/versioned_sidebars/version-0.66-sidebars.json @@ -676,50 +676,5 @@ } ] } - ], - "version-0.66/architecture": [ - { - "type": "category", - "collapsed": false, - "label": "Architecture", - "items": [ - { - "type": "doc", - "id": "version-0.66/architecture-overview" - }, - { - "type": "category", - "collapsed": false, - "collapsible": false, - "label": "Rendering", - "items": [ - { - "type": "doc", - "id": "version-0.66/fabric-renderer" - }, - { - "type": "doc", - "id": "version-0.66/render-pipeline" - }, - { - "type": "doc", - "id": "version-0.66/xplat-implementation" - }, - { - "type": "doc", - "id": "version-0.66/view-flattening" - }, - { - "type": "doc", - "id": "version-0.66/threading-model" - } - ] - }, - { - "type": "doc", - "id": "version-0.66/architecture-glossary" - } - ] - } ] } diff --git a/website/versioned_sidebars/version-0.67-sidebars.json b/website/versioned_sidebars/version-0.67-sidebars.json index 73bcf90a186..10f43368b7e 100644 --- a/website/versioned_sidebars/version-0.67-sidebars.json +++ b/website/versioned_sidebars/version-0.67-sidebars.json @@ -200,29 +200,5 @@ "rect", "viewtoken" ] - }, - "architecture": [ - { - "type": "category", - "label": "Architecture", - "collapsed": false, - "items": [ - "architecture-overview", - { - "type": "category", - "label": "Rendering", - "collapsible": false, - "collapsed": false, - "items": [ - "fabric-renderer", - "render-pipeline", - "xplat-implementation", - "view-flattening", - "threading-model" - ] - }, - "architecture-glossary" - ] - } - ] + } }