Skip to content

Latest commit

 

History

History
184 lines (139 loc) · 8.29 KB

autolinking.md

File metadata and controls

184 lines (139 loc) · 8.29 KB

Autolinking

React Native libraries often come with platform-specific (native) code. Autolinking is a mechanism that allows your project to discover and use this code.

Add a library using your favorite package manager and run the build:

# install
yarn add react-native-webview
cd ios && pod install && cd .. # CocoaPods on iOS needs this extra step
# run
yarn react-native run-ios
yarn react-native run-android

That's it. No more editing build config files to use native code.

Also, removing a library is similar to adding a library:

# uninstall
yarn remove react-native-webview
cd ios && pod install && cd .. # CocoaPods on iOS needs this extra step

How does it work

Each platform defines its own platforms configuration. It instructs the CLI on how to find information about native dependencies. This information is exposed through the config command in a JSON format. It's then used by the scripts run by the platform's build tools. Each script applies the logic to link native dependencies specific to its platform.

Platform iOS

The react-native/scripts/react_native_pods.rb script required by Podfile gets the package metadata from react-native config command during install phase and:

  1. Adds dependencies via CocoaPods dev pods (using files from a local path).
  2. Adds build phase scripts to the App project’s build phase. (see examples below)

This means that all libraries need to ship a Podspec in the root of their folder. Podspec references the native code that your library depends on.

The implementation ensures that a library is imported only once. If you need to have a custom pod directive then include it above the use_native_modules! function.

Example

See example usage in React Native template's Podfile.

Platform Android

The autolinkLibrariesWithApp function from React Native Gradle Plugin (RNGP) must be registered in your project's settings.gradle file and called in app/build.gradle file and:

  1. At build time, before the build script is run:
    1. RNGP plugin registered in settings.gradle runs autolinkLibrariesFromCommand() method. It uses the package metadata from react-native config to add Android projects.
    2. Then in app/build.gradle it runs autolinkLibrariesWithApp() method. It creates a list of React Native packages to include in the generated /android/build/generated/rn/src/main/java/com/facebook/react/PackageList.java file.
      1. When the new architecture is turned on, the generateNewArchitectureFiles task is fired, generating /android/build/generated/rn/src/main/jni directory with the following files:
        • Android-rncli.cmake – creates a list of codegen'd libs. Used by the project's CMakeLists.txt.
        • rncli.cpp – registers codegen'd Turbo Modules and Fabric component providers. Used by MainApplicationModuleProvider.cpp and MainComponentsRegistry.cpp.
        • rncli.h - a header file for rncli.cpp.
  2. At runtime, the list of React Native packages generated in step 1.2 is registered by getPackages method of ReactNativeHost in MainApplication.java.
    1. You can optionally pass in an instance of MainPackageConfig when initializing PackageList if you want to override the default configuration of MainReactPackage.

Example

See example usage in React Native template:

What do I need to have in my package to make it work?

You’re already using Gradle, so Android support will work by default.

On the iOS side, you will need to ensure you have a Podspec to the root of your repo. The react-native-webview Podspec is a good example of a package.json-driven Podspec. Note that CocoaPods does not support having /s in the name of a dependency, so if you are using scoped packages - you may need to change the name for the Podspec.

Pure C++ libraries

Alternatively, if you have a pure C++ library and don't want to use Gradle, you can still use autolinking. You need to update your react-native.config.js to include the following:

// react-native.config.js
module.exports = {
  dependency: {
    platforms: {
      android: {
        sourceDir: 'path/to/your/c++/code',
        cxxModuleCMakeListsPath: `relative/path/to/CMakeLists.txt`, // This is relative to the sourceDir.
        cxxModuleCMakeListsModuleName: 'MyModule', // This is the name of the CMake target.
        cxxModuleHeaderName: 'MyHeader', // CLI will include this header while linking.
      },
    },
  },
};

How can I customize how autolinking works for my package?

A library can add a react-native.config.js configuration file, which will customize the defaults, example:

// react-native.config.js
module.exports = {
  dependency: {
    platforms: {
      android: null, // disable Android platform, other platforms will still autolink if provided
    },
  },
};

How can I disable autolinking for unsupported library?

During the transition period some packages may not support autolinking on certain platforms. To disable autolinking for a package, update your react-native.config.js's dependencies entry to look like this:

// react-native.config.js
module.exports = {
  dependencies: {
    'some-unsupported-package': {
      platforms: {
        android: null, // disable Android platform, other platforms will still autolink if provided
      },
    },
  },
};

How can I disable autolinking for new architecture (Fabric, TurboModules)?

It happens that packages come with their own linking setup for the new architecture. To disable autolinking in such cases (currently react-native-screens, react-native-safe-area-context, react-native-reanimated, react-native-gesture-handler), update your react-native.config.js's dependencies entry to look like this:

// react-native.config.js
module.exports = {
  dependencies: {
    'fabric-or-tm-library': {
      platforms: {
        android: {
          libraryName: null,
          componentDescriptors: null,
          cmakeListsPath: null,
          cxxModuleCMakeListsModuleName: null,
          cxxModuleCMakeListsPath: null,
          cxxModuleHeaderName: null,
        },
      },
    },
  },
};

How can I autolink a local library?

We can leverage CLI configuration to make it "see" React Native libraries that are not part of our 3rd party dependencies. To do so, update your react-native.config.js's dependencies entry to look like this:

// react-native.config.js
module.exports = {
  dependencies: {
    'local-rn-library': {
      root: path.join(__dirname, '/path/to/local-rn-library'),
    },
  },
};

Note: In the root field, it's recommended to use __dirname instead of process.cwd(). This ensures the path is consistently resolved, regardless of the current working directory.

How can I use autolinking in a monorepo?

There is nothing extra you need to do - monorepos are supported by default.

Dependencies are only linked if they are listed in the package.json of the mobile workspace, where "react-native" dependency is defined. For example, with this file structure:

/root
  /packages
    /mobile
      /ios
      /android
      package.json <-- Only dependencies listed here are auto-linked
    /components
      package.json <-- Dependencies here are ignored when auto-linking
  package.json

In this example, if you add a package with native code as a dependency of components, you need to also add it as a dependency of mobile for auto-linking to work.