Skip to content

Commit 3ae820e

Browse files
authored
feat(Worklets): docs for new bundle mode (#8759)
## Summary Requires - #8744 - #8853 ## Test plan πŸš€
1 parent 66db7e0 commit 3ae820e

40 files changed

+264
-9365
lines changed

β€Ž.yarn/patches/react-native-npm-0.83.0.patchβ€Ž

Lines changed: 0 additions & 1034 deletions
This file was deleted.

docs/docs-worklets/docs/experimental/_category_.json renamed to docs/docs-worklets/docs/bundleMode/_category_.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"label": "Experimental",
3-
"position": 5,
2+
"label": "Bundle Mode",
3+
"position": 2,
44
"link": {
55
"type": "generated-index"
66
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
sidebar_position: 1
3+
sidebar_label: Overview
4+
slug: /bundleMode
5+
---
6+
7+
import useBaseUrl from '@docusaurus/useBaseUrl';
8+
import ThemedImage from '@theme/ThemedImage';
9+
10+
<ThemedImage
11+
sources={{
12+
light: useBaseUrl('/img/bundleMode-light.png'),
13+
dark: useBaseUrl('/img/bundleMode-dark.png'),
14+
}}
15+
alt="Bundle Mode conceptual illustration"
16+
/>
17+
18+
# Overview
19+
20+
Bundle Mode is an experimental feature that gives worklets access to your whole JavaScript bundle - meaning that any code that's present in the bundle can be executed in any worklet and on any runtime. This means that third party libraries can be used in worklets without the need to patch them. It's also a performance improvement as worklets' code can benefit from all the optimizations that pre-compiled bytecode offers.
21+
22+
**We envision the Bundle Mode to be the default way of using worklets in the future.**
23+
24+
Instructions on how to enable it can be found [here](/docs/bundleMode/setup).
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
---
2+
sidebar_position: 2
3+
---
4+
5+
import Tabs from '@theme/Tabs';
6+
import TabItem from '@theme/TabItem';
7+
import useBaseUrl from '@docusaurus/useBaseUrl';
8+
import ThemedImage from '@theme/ThemedImage';
9+
10+
# Setup
11+
12+
## Package installation
13+
14+
Install `react-native-worklets` package with the `bundle-mode-preview` tag:
15+
16+
<Tabs groupId="package-managers">
17+
<TabItem value="npm" label="NPM">
18+
```bash
19+
npm i react-native-worklets@bundle-mode-preview
20+
```
21+
22+
</TabItem>
23+
<TabItem value="yarn" label="YARN">
24+
```bash
25+
yarn add react-native-worklets@bundle-mode-preview
26+
```
27+
28+
</TabItem>
29+
</Tabs>
30+
31+
## Configure Babel
32+
33+
To use `react-native-worklets`'s Bundle Mode feature, you need to make the following changes in your repository:
34+
35+
1. **Modify your Babel configuration**. [Worklets Babel Plugin](/docs/worklets-babel-plugin/about) needs to know that it has to prepare your code for the Bundle Mode. In your `babel.config.js` file, add the following:
36+
37+
```javascript {2-5,13}
38+
/** @type {import('react-native-worklets/plugin').PluginOptions} */
39+
const workletsPluginOptions = {
40+
bundleMode: true,
41+
strictGlobal: true, // optional, but recommended
42+
}
43+
44+
module.exports = {
45+
presets: [
46+
... // don't add it here :)
47+
],
48+
plugins: [
49+
...
50+
['react-native-worklets/plugin', workletsPluginOptions],
51+
],
52+
};
53+
```
54+
55+
## Configure Metro
56+
57+
2. **Modify your Metro configuration**. Metro needs to be configured pre-load Bundle Mode entry points into your JavaScript bundle. In your `metro.config.js` file, apply the config required for the bundle mode. For example:
58+
59+
```javascript {6-8,16}
60+
const {
61+
getDefaultConfig,
62+
mergeConfig,
63+
} = require('@react-native/metro-config');
64+
65+
const {
66+
bundleModeMetroConfig,
67+
} = require('react-native-worklets/bundleMode');
68+
69+
const config = {
70+
// Your Metro config
71+
};
72+
73+
module.exports = mergeConfig(
74+
getDefaultConfig(__dirname),
75+
bundleModeMetroConfig,
76+
config
77+
);
78+
```
79+
80+
## Configure your app
81+
82+
For Worklets to know that it should run in Bundle Mode, you need to toggle on `WORKLETS_BUNDLE_MODE_ENABLED` static feature flag in your app's `package.json`. You can find instructions on how to enable it [here](/docs/guides/feature-flags).
83+
84+
## Enable seamless Metro bundling
85+
86+
_This step is optional but highly recommended._
87+
88+
If you run the app after just executing the above steps, you will see an error "Failed to get the SHA-1 for ...":
89+
90+
<ThemedImage
91+
sources={{
92+
light: useBaseUrl('/img/sha-light.png'),
93+
dark: useBaseUrl('/img/sha-dark.png'),
94+
}}
95+
alt="Bundle Mode Metro error logs"
96+
/>
97+
98+
This is due to fact that Bundle Mode isolates each worklet in a separate module (file) on the fly and the Metro bundler doesn't index these isolated modules in time.
99+
100+
To fix this issue you can do one of the following:
101+
102+
1. Reload the app and Metro a couple of times until Metro picks up all the new modules. You will have to do it each time. Not recommended.
103+
2. Patch `metro` package for it to synchronously index new modules created by Bundle Mode. This is the recommended approach. **This patch does not require building React Native from source**. You can find patching instructions in the [Worklets repository](https://github.com/software-mansion/react-native-reanimated/tree/main/packages/react-native-worklets/bundleMode/patches).
104+
105+
This patch is a temporary workaround until necessary changes are merged into Metro.
106+
107+
## Enable fast refresh on Worklet Runtimes
108+
109+
_This step is optional but highly recommended._
110+
111+
React Native's Fast Refresh (hot reload) feature doesn't apply to Worklet Runtimes out of the box. Therefore, when you change worklet's code you will see an error "\[Worklets\] Unable to resolve worklet with hash ...".
112+
113+
<ThemedImage
114+
sources={{
115+
light: useBaseUrl('/img/hot-light.png'),
116+
dark: useBaseUrl('/img/hot-dark.png'),
117+
}}
118+
alt="Bundle Mode Fast Refresh error logs"
119+
/>
120+
121+
This is due to fact that the Fast Refresh update wasn't sent to the Worklet Runtime and it doesn't know that new worklet with the given hash exists.
122+
123+
To fix this issue you can do one of two thing:
124+
125+
1. Reload the app on each worklet code change. This virtually defeats the purpose of Fast Refresh. Not recommended.
126+
2. Patch `metro-runtime` package for it to send Fast Refresh updates to Worklet Runtimes. This is the recommended approach. **This patch does not require building React Native from source** You can find patching instructions in the [Worklets repository](https://github.com/software-mansion/react-native-reanimated/tree/main/packages/react-native-worklets/bundleMode/patches).
127+
128+
This patch is a temporary workaround until necessary changes are merged into Metro.
129+
130+
## Final steps
131+
132+
Make sure to clear your Metro bundler's cache to ensure that all the changes are applied correctly.
133+
134+
<Tabs groupId="package-managers">
135+
<TabItem value="npm" label="NPM">
136+
```bash
137+
npm start -- --reset-cache
138+
```
139+
</TabItem>
140+
<TabItem value="yarn" label="YARN">
141+
```bash
142+
yarn start --reset-cache
143+
```
144+
</TabItem>
145+
</Tabs>
146+
147+
And that's it! You can now happily enjoy the Bundle Mode! You can learn more about using the Bundle Mode [here](/docs/bundleMode/usage).
148+
149+
## Reference
150+
151+
To see how the setup looks in a real project, you can check out the [Bundle Mode Showcase App](https://github.com/software-mansion-labs/Bundle-Mode-showcase-app) repository.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
sidebar_position: 3
3+
---
4+
5+
# Usage
6+
7+
## Running third party libraries in Worklets
8+
9+
Third party libraries have to be on an allow-list to use them in worklets. This is because libraries can come with side-effects that would break a Worklet Runtime. For instance, a library that imports something from React Native can't be used on a Worklet Runtime. This would load a second instance of React Native and break your app.
10+
11+
To add a library to the allow-list you only need to set the `workletizableModules` option in Worklets Babel plugin, which is an array of library names. For instance, if you want to use `my-library` on a Worklet Runtime.
12+
13+
```javascript
14+
/** @type {import('react-native-worklets/plugin').PluginOptions} */
15+
const workletsPluginOptions = {
16+
bundleMode: true,
17+
strictGlobal: true, // optional, but recommended
18+
// highlight-next-line
19+
workletizableModules: ['my-library'],
20+
};
21+
```
22+
23+
`workletizableModules` API is temporary and will be replaced with a more robust solution in the future.
24+
25+
## Running network requests in Worklets
26+
27+
In React Native ecosystem, new JavaScript runtimes don't come with networking capabilities out of the box. Worklets library provides a simplified version of `fetch` API that can be used on Worklet Runtimes - however, it might not be sufficient for all use cases.
28+
29+
For this reason, to enable `fetch` on Worklet Runtimes you have to toggle the `FETCH_PREVIEW_ENABLED` static feature flag in your app's `package.json`. You can find instructions on how to enable it [here](/docs/guides/feature-flags).
30+
31+
Running `fetch` also requires installing all the patches from the [Bundle Mode setup guide](/docs/bundleMode/setup).
32+
33+
:::note
34+
We are currently looking for third-party networking solutions that would provide same networking capabilities on Worklet Runtimes as what's available on the RN Runtime. We are open to adopting or integrating with such solutions. If you know about such solutions, please reach out to us on [GitHub](https://github.com/software-mansion/react-native-reanimated/issues).
35+
36+
:::
37+
38+
## Reference
39+
40+
To see how the setup looks in a real project, you can check out the [Bundle Mode Showcase App](https://github.com/software-mansion-labs/Bundle-Mode-showcase-app) repository.

β€Ždocs/docs-worklets/docs/experimental/bundleMode.mdxβ€Ž

Lines changed: 0 additions & 124 deletions
This file was deleted.

β€Ždocs/docs-worklets/docs/guides/feature-flags.mdβ€Ž

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ Feature flags allow developers to opt-in for experimental changes or opt-out fro
88

99
## Summary of available feature flags
1010

11-
| Feature flag name | Type | Added in | Removed in | Default value |
12-
| ----------------------------------------------------------------- | :-----------------------------: | :------: | :--------: | :-----------: |
13-
| [`IOS_DYNAMIC_FRAMERATE_ENABLED`](#ios_dynamic_framerate_enabled) | [static](#static-feature-flags) | 4.1.0 | &ndash; | `true` |
11+
| Feature flag name | Type | Added in | Removed in | Default value |
12+
| ------------------------------------------------------------------ | :-----------------------------: | :------: | :--------: | :-----------: |
13+
| [`BUNDLE_MODE_ENABLED`](#bundle_mode_enabled-) | [static](#static-feature-flags) | 0.8.0 | &ndash; | `false` |
14+
| [`FETCH_PREVIEW_ENABLED`](#fetch_preview_enabled-) | [static](#static-feature-flags) | 0.8.0 | &ndash; | `false` |
15+
| [`IOS_DYNAMIC_FRAMERATE_ENABLED`](#ios_dynamic_framerate_enabled-) | [static](#static-feature-flags) | 0.6.0 | &ndash; | `true` |
1416

1517
:::info
1618

@@ -20,7 +22,16 @@ Feature flags available in `react-native-reanimated` are listed [on this page](h
2022

2123
## Description of available feature flags
2224

23-
### `IOS_DYNAMIC_FRAMERATE_ENABLED`
25+
### `BUNDLE_MODE_ENABLED` <AvailableFrom version="0.8.0" />
26+
27+
This feature flag enables [the Bundle Mode](/docs/bundleMode/). Make sure to follow the rest of the [setup instructions](/docs/bundleMode/setup/) after enabling this flag.
28+
29+
### `FETCH_PREVIEW_ENABLED` <AvailableFrom version="0.8.0" />
30+
31+
This feature flag enables the [preview of fetch API on Worklet Runtimes](/docs/bundleMode/usage#running-network-requests-in-worklets) in the [Bundle Mode](/docs/bundleMode/). Make sure to follow the rest of the [setup instructions](/docs/bundleMode/setup/) after enabling this flag.
32+
**This flag requires `BUNDLE_MODE_ENABLED` flag to be enabled as well.**
33+
34+
### `IOS_DYNAMIC_FRAMERATE_ENABLED` <AvailableFrom version="0.6.0" />
2435

2536
This feature flags is supposed to improve the visual perception and perceived smoothness of computationally expensive animations. When enabled, the frame rate will be automatically adjusted for current workload of the UI thread. For instance, if the device fails to run animations in 120 fps which would usually results in irregular frame drops, the mechanism will fallback to stable 60 fps. For more details, see [PR #7624](https://github.com/software-mansion/react-native-reanimated/pull/7624).
2637

β€Ždocs/docs-worklets/docs/memory/_category_.jsonβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"label": "Memory",
3-
"position": 3,
3+
"position": 4,
44
"link": {
55
"type": "generated-index"
66
}

β€Ždocs/docs-worklets/docs/memory/createSerializable.mdxβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,4 @@ object.a = 10; // <-- Warning: You can't mutate the object after serializing it
7676
- This function is rarely used as in almost all cases Worklets handle the creation of Serializables for you.
7777
- This function includes cycle detection to prevent infinite recursion.
7878
- `jsi::NativeState` of a passed value is preserved during serialization.
79-
- Outside of [Bundle Mode](/docs/experimental/bundleMode), `createSerializable` can be called only on the [RN Runtime](/docs/fundamentals/runtimeKinds#rn-runtime). In Bundle Mode, it can be called from any Runtime. If you need to create a Serializable on a [Worklet Runtime](/docs/fundamentals/runtimeKinds#worklet-runtime) outside of Bundle Mode, use deprecated [makeShareableCloneOnUIRecursive](/docs/memory/makeShareableCloneOnUIRecursive) instead.
79+
- Outside of [Bundle Mode](/docs/bundleMode/), `createSerializable` can be called only on the [RN Runtime](/docs/fundamentals/runtimeKinds#rn-runtime). In Bundle Mode, it can be called from any Runtime. If you need to create a Serializable on a [Worklet Runtime](/docs/fundamentals/runtimeKinds#worklet-runtime) outside of Bundle Mode, use deprecated [makeShareableCloneOnUIRecursive](/docs/memory/makeShareableCloneOnUIRecursive) instead.

0 commit comments

Comments
Β (0)