Upgrade to Pro — share decks privately, control downloads, hide ads and more …

React Native, Meet Node.js native addons

React Native, Meet Node.js native addons

I presented this talk at React Summit US 2024 on Nov 22nd 2024.

The video is available here: https://gitnation.com/contents/react-native-meet-nodejs-native-addons/video

Jamie Birch

November 22, 2024
Tweet

More Decks by Jamie Birch

Other Decks in Programming

Transcript

  1. Contents • What are Node.js native addons? • Why should

    we care? • Use-cases: • An ABI-stable API for Hermes • Cross-ecosystem libraries (NativeScript) • Conclusion
  2. What are Node.js native addons? Just like React Native, Node.js

    has native modules – “native addons”.
 e.g. the sqlite3 npm package (TryGhost/node-sqlite3 on GitHub) And just as React Native native modules are written with JSI, Node.js native addons are written with Node-API, which is similarly engine-agnostic. sqlite3.c JSI or Node-API V8 JSC Hermes … and more!
  3. Why should we care? " Incredibly popular (20M downloads/week of

    node-addon-api). # Community-driven; de facto industry standard. $ Available for various languages (C++, Swift, Rust, C#, Nim, Zig, Go…). % Can express pretty much anything ECMAScript can. & First-class interop between native and JS (e.g. lifetimes, async functions). ' ABI-stable (long story).
  4. An ABI-stable API for Hermes What is an ABI? An

    Application Binary Interface (ABI) is the compiled version of an API. It defines: • the set of functions and their signatures • data structures
 (e.g. the layouts of structs and enums) • function calling conventions • error handling • memory management 45 78 3C 1E A6 4F 3D 06 80 E9 D3 A6 B2 A7 A8 88 55 AB D7 34 71 D2 89 B3 98 76 CC 14 12 12 42 97 30 9F 32 79 12 93 26 4C C8 03 F7 B3 65 EB 56 56 AE 5A 5D 6F FF 8B FE 70 01 93 27 4E F9 DE B2 6D 5B B8 7D F2 A4 89 8C 19 3D 8A AC CC 4C 26 4F 9C AA 2A 56 AC 5A C5 CE BC 3C 8E 9B 39 83 F2 8A 0A 34 5D A3 6F B8 D1 E3 4C 4D 49 E1 C2 0B 2E E0 ED F7 DE E7 91 C7 1F 27 39 5D 9D 18 63 D5 AA D5 AC 5D B7 8E BB 6E BF 8D 19 D3 A6 32 76 CC 68 1E 7B F8 21 34 5D E7 83 FF 7D C4 9A B5 EB D8 B2 75 2B 37 5D 77 1D BD 7A F6 24 3E 3E 8E EE 5D BB 86 FB 1F C9 FC A0 69 35 E4 71 8E 50 20 E8 09 18 07 B5 ED 71 87 3E 44 99 55 05 35 5C 6E 02 1F AF 0F 05 EA 31 76 85 69 BD 6D E1 FD 29 4A E3 FB 0B 8D 71 78 31 5B 53 EF 37 67 DC 48 D7 90 57 54 BA B9 EF A9 BF B3 63 D7 6E B2 32 D2 C9 CA 48 27 2F BF 80 39 4F FE 9D F2 CA CA 16 DB 4F 83 25 2B 87 BB EC E1 D4 29 53 70 39 5D 3C F8 B7 47 F9 F2 EB 6F 28 2F 2F E7 F6 9B 6F C2 66 B3 35 DE B9 46 7D D9 76 21 84 E8 48 0C C3 A0 7F BF BE 9C 7F EE 39 BC F1 D6 DB DC F7 D0 C3 75 02 D9 6D DB 77 00 F0 C3 BC 1F F9 61 DE 8F 75 FA EE CE CF A7 5B D7 AE E1 F7 C0 60 30 88 CF E7 0B B7 9F 7E EA 29 6C F8 E5 11 E6 CD 9F CF A2 C5 4B C8 CA CC 64 F6 09 C7 F3 FC 8B 2F B1 76 FD 7A 96 FD FC 33 C3 87 0D 25 2B B3 13 1F 7E FC 31 00 83 06 0C 08 8F D1 AF 5F 5F 00 76 EC CC AB 53 5E B0 7F FD 6B ED F6 D2 D2 BD 6C DC B4 19 80 59 C7 1F 27 C1 F8 51 E0 AB 6F BE 05 E0 CC 73 CE AB BB FD DB 6F 19 36 74 systemd (machine code) not binary compatible binary compatible (same instruction set, same compilation environment) AB AB Wikipedia: Linux API and Linux ABI.svg (cropped)
  5. An ABI-stable API for Hermes An ideal ABI is both

    safe and stable MyApp.app libHermes.0.12.0.dylib ABI safety MyApp.app libHermes.0.12.0.dylib - libHermes.0.12.0.dylib + libHermes.0.13.0.dylib ABI stability Lets a binary be used in your app without recompilation, regardless of the build mode, compiler, or language. Lets your app adopt new versions of a binary without recompilation, due to backwards compatibility. (debug) (release)
  6. An ABI-stable API for Hermes Put into practice in React

    Native Windows In order to realise these benefits, React Native Windows uses a fork of Hermes, hermes-windows, that implements an ABI-stable API based on Node-API. Since its development, Hermes has actually begun developing an official ABI‑stable API – but for now, let’s study how hermes-windows works!
  7. React Native Exposes JSI (not ABI-safe ⚠) React Native Hermes

    binary React Native Windows node-api-jsi Exposes Node-API (ABI-safe ✅) Implements JSI
 using Node-API Hermes Windows binary Microsoft.ReactNative.dll * Exposes Hermes ABI-safe API (ABI-safe ✅)
  8. An ABI-stable API for Hermes Result The main benefits are:

    • We can use the latest Hermes regardless of RNW version. • We can use prebuilt Hermes in release mode (for faster execution) whilst building the rest of our app in debug mode (for faster builds). … All thanks to Node-API!
  9. Cross-ecosystem libraries Meet NativeScript export function callPhoneNumber(platform, phoneNumber) { if(platform

    === "ios"){ UIApplication.sharedApplication.openURLOptionsCompletionHandler( NSURL.URLWithString(`tel://${phoneNumber}`), {}, (success) => console.log(success), ); return; } if(platform === "android"){ Application.android.foregroundActivity.startActivity( new android.content.Intent( android.content.Intent.ACTION_DIAL, android.net.Uri.parse(`tel:${phoneNumber}`), ) ); return; } }
  10. Cross-ecosystem libraries Node.js native addons can’t be used as-is Node.js

    native addons node_api.h Node-API js_native_api.h Although NativeScript is available as a Node.js native addon, Hermes Windows only implements the underlying API, Node-API. This means we lack module-loading support:
 require("./addon.node") + … Can we still use the library somehow?
  11. require( ); NativeScript.node NativeScript.node NativeScript.xcframework autolink Module initialiser runs objc_bridge_init().

    Call objc_bridge_init() from the native side. Typical approach (Node.js) Modified approach (React Native) How to initialise the addon Using Node.js native addons with only Node-API
  12. I recompiled Hermes Windows for iOS, then patched the following

    file to set up Node-API: react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp Using Node.js native addons with only Node-API Call objc_bridge_init() during this initialisation! Initialising from the native side
  13. Demo ᶃ Checking the battery import { useEffect, useState }

    from "react"; import { StyleSheet, Text, View } from "react-native"; export default function App() { const [batteryLevel, setBatteryLevel] = useState(-1); useEffect(() => { setBatteryLevel(UIDevice.currentDevice.batteryLevel); }, []); return ( <View style={styles.container}> <Text>ॆిɿ {batteryLevel * 100}%</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center", }, }); ,: ,:
  14. Demo ᶄ Logging native data import { useEffect } from

    "react"; import { View } from "react-native"; export default function App() { useEffect(() => { const rootView = UIApplication.sharedApplication.keyWindow.rootViewController.view; console.log(rootView.debugDescription); }, []); return <View />; } LOG <RCTRootView: 0x10550eef0; frame = (0 0; 393 852); autoresize = W+H; backgroundColor = <UIDynamicSystemColor: 0x600001730300; name = systemBackgroundColor>; layer = <CALayer: 0x60000022f0c0>>
  15. Demo ᶅ Changing the colour of a native view import

    { Button, View, StyleSheet } from "react-native"; export default function App() { return ( <View style={styles.container}> <Button title="ృΔ" onPress={() => { const rootView = UIApplication.sharedApplication.keyWindow.rootViewController.view; rootView.backgroundColor = UIColor.systemMintColor; }} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: "center", justifyContent: "center", }, }); Go Go
  16. Conclusion • Node-API upstreamed into Hermes • Support for Node.js

    native addons • Completion of the official ABI-stable Hermes API • ABI stability for React Native native modules • More cross-ecosystem collaboration Hopes for the future
  17. Conclusion • Node.js native addons are the de facto JavaScript

    native modules standard and are based on an ABI-stable API, Node-API. • ABI stability is important for flexibility in using prebuilt libraries. • Cross-ecosystem collaboration is currently limited without full Node.js native addons support, but not impossible with workarounds. • Work is underway to upstream Node-API into Hermes! Summary