|
| 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. |
0 commit comments