Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,6 @@ lib/

# jest
coverage/

# Claude
.claude/
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ cd ios && bundler install && bundler exec pod install

The library includes native code so you will need to re-build the native app.

### Worklets Bundle Mode

If you're using [Worklets Bundle Mode](https://docs.swmansion.com/react-native-worklets/docs/bundleMode) you will have to
configure your [import forwarding](https://docs.swmansion.com/react-native-worklets/docs/worklets-babel-plugin/plugin-options#importforwarding) as follows in your `babel.config.js` file:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's also redirect users to the correct section of the Worklets docs about their metro setup (metro.config.js, and the patches). The current note suggests that they only have to configure import forwarding


```js
importForwarding: {
moduleNames: [
// your existing module names here...
// the order of the modules does not matter
'expensify-common',
'html-entities',
'react-native-live-markdown',
],
},
```

> [!NOTE]
> The library does not support Expo Go, you will need to setup Expo Dev Client (see [here](https://docs.expo.dev/workflow/prebuild/)).

Expand Down
25 changes: 24 additions & 1 deletion example/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
const path = require('path');
const pak = require('../package.json');

const monorepoRootPath = path.resolve(__dirname, '..');

/** @type {import('react-native-worklets/plugin').PluginOptions} */
const workletsPluginOptions = {
bundleMode: process.env.BUNDLE_MODE === '1',
strictGlobal: true,
importForwarding: {
moduleNames: [
'expensify-common',
'html-entities',
'react-native-live-markdown',
],
/**
* The following relative paths look like this due to monorepo structure.
* In a consumer app this wouldn't be necessary.
*/
relativePaths: [
path.join(monorepoRootPath, 'src'),
path.join(monorepoRootPath, 'lib'),
],
},
};

module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
Expand All @@ -13,6 +36,6 @@ module.exports = {
},
},
],
'react-native-worklets/plugin',
['react-native-worklets/plugin', workletsPluginOptions],
],
};
7 changes: 6 additions & 1 deletion example/metro.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const {bundleModeMetroConfig} = require('react-native-worklets/bundleMode');
const path = require('path');

const root = path.resolve(__dirname, '..');
Expand All @@ -22,4 +23,8 @@ const config = {
},
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);
module.exports = mergeConfig(
getDefaultConfig(__dirname),
bundleModeMetroConfig,
config,
);
3 changes: 2 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"android": "react-native run-android",
"ios": "react-native run-ios",
"lint": "eslint .",
"start": "react-native start --client-logs"
"start": "react-native start --client-logs",
"bundle-mode-start": "BUNDLE_MODE=1 react-native start --reset-cache --client-logs"
Comment on lines -9 to +10

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we shouldn't make it the default 🤔 Are there any drawbacks to always enabling bundle mode?

},
"dependencies": {
"expensify-common": "2.0.148",
Expand Down
4 changes: 4 additions & 0 deletions example/src/PlatformInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Platform, Text, View, StyleSheet} from 'react-native';
import {isBundleModeEnabled} from 'react-native-worklets';
import React from 'react';

function isWeb() {
Expand Down Expand Up @@ -62,6 +63,9 @@ export function PlatformInfo() {
<Text>Bridgeless: {isBridgeless() ? 'yes' : 'no'}</Text>
<Text>RN version: {getReactNativeVersion()}</Text>
<Text>RN runtime: {getRuntime()}</Text>
<Text>
Worklets Bundle Mode: {isBundleModeEnabled() ? 'yes' : 'no'}
</Text>
</>
)}
</View>
Expand Down
31 changes: 31 additions & 0 deletions patches/metro+0.84.4.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
diff --git a/node_modules/metro/src/node-haste/DependencyGraph.js b/node_modules/metro/src/node-haste/DependencyGraph.js
index 8222d8c..e36770d 100644
--- a/node_modules/metro/src/node-haste/DependencyGraph.js
+++ b/node_modules/metro/src/node-haste/DependencyGraph.js
@@ -32,6 +32,11 @@ function getOrCreateMap(map, field) {
}
return subMap;
}
+
+const workletsDirPath = _path.default.join(
+ "react-native-worklets",
+ ".worklets",
+);
class DependencyGraph extends _events.default {
#packageCache;
#dependencyPlugin;
@@ -197,6 +202,14 @@ class DependencyGraph extends _events.default {
return (0, _nullthrows.default)(this._fileSystem).getAllFiles();
}
async getOrComputeSha1(mixedPath) {
+ if (mixedPath.includes(workletsDirPath)) {
+ const createHash = require("crypto").createHash;
+ return {
+ sha1: createHash("sha1")
+ .update(performance.now().toString())
+ .digest("hex"),
+ };
+ }
const result = await this._fileSystem.getOrComputeSha1(mixedPath);
if (!result || !result.sha1) {
throw new Error(`Failed to get the SHA-1 for: ${mixedPath}.
14 changes: 14 additions & 0 deletions patches/react-native++metro-runtime+0.84.4.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
diff --git a/node_modules/react-native/node_modules/metro-runtime/src/modules/HMRClient.js b/node_modules/react-native/node_modules/metro-runtime/src/modules/HMRClient.js
index 534ac87..5773985 100644
--- a/node_modules/react-native/node_modules/metro-runtime/src/modules/HMRClient.js
+++ b/node_modules/react-native/node_modules/metro-runtime/src/modules/HMRClient.js
@@ -3,6 +3,9 @@
const EventEmitter = require("./vendor/eventemitter3");
const HEARTBEAT_INTERVAL_MS = 20_000;
const inject = ({ module: [id, code], sourceURL }) => {
+ if (global.__workletsModuleProxy?.propagateModuleUpdate) {
+ global.__workletsModuleProxy.propagateModuleUpdate(code, sourceURL);
+ }
if (global.globalEvalWithSourceUrl) {
global.globalEvalWithSourceUrl(code, sourceURL);
} else {
Loading