Skip to content

Allow usage of pnpm #1207

Description

@dancojocaru2000

Allow the usage on pnpm instead of yarn or npm.

Perhaps a guide for doing the init manually would be helpful until such capability is introduced.

Activity

  1. github-actions commented on Nov 27, 2022

    @github-actions

    There hasn't been any activity on this issue in the past 3 months, so it has been marked as stale and it will be closed automatically if no further activity occurs in the next 7 days.

  2. thymikee commented on Dec 5, 2022

    @thymikee
    Member

    Reopening, pnpm is something that we'd like to support

  3. TMisiukiewicz commented on Dec 21, 2022

    @TMisiukiewicz
    Collaborator

    Hey, support for pnpm is something i have been working on for a while. I was able to make it work with init command and make project running on iOS and Android. However, since pnpm is using symlinks, I discovered a few pitfalls here.

    1. node_modules structure is different. - there is a need of manual changing the paths in the following files in android and ios folders:
    • ios/Podfile - path to native_modules
    • android/app/build.gradle - path to native_modules.gradle
    • android/settings.gradle - path to native_modules.gradle

    The pnpm paths are strongly dependent on installed versions of the dependencies, e.g. .pnpm/@react-native-community+cli-platform-android@9.3.1/node_modules/@react-native-community/cli-platform-android/native_modules.gradle

    1. there is a need of adding the Metro resolver for symlinks: rnx-kit/metro-resolver-symlinks
    2. Developer needs to manually run pod install after initializing the project - CocoaPods installation fails due to incorrect native_modules path in Podfile mentioned in 1, but that step can be just skipped in init when using pnpm as package manager.

    Another possible solution is creating a .npmrc file, adding node-linker: hoisted inside of it and running pnpm install, but i think it's missing the point of using pnpm as the node_modules structure will become similar to the one known from yarn and npm.

    Where to go from there? I think adding all the required steps to make it work to the docs is one of the options, but definitely not the best one.

  4. rahulpandey commented on Mar 10, 2024

    @rahulpandey

    Following steps working for me
    Added public-hoist-pattern configuration in .npmrc to hoist packages from specific scopes:
    .npmrc:

    public-hoist-pattern[]=*@react-native-community*
    public-hoist-pattern[]=*@react-native*
    

    Also integrated the following changes in metro.config.js:

    const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
    const path = require('path');
    
    /**
     * Metro configuration
     * https://facebook.github.io/metro/docs/configuration
     *
     * @type {import('metro-config').MetroConfig}
     */
    const projectRoot = __dirname;
    
    const config = {
      watchFolders: [projectRoot],
      resolver: {
        nodeModulesPaths: [path.resolve(projectRoot, 'node_modules')],
      },
    };
    module.exports = mergeConfig(getDefaultConfig(__dirname), config);
    

    React and React Native versions:
    "react": "18.2.0",
    "react-native": "0.73.5",

    It seems that every Gradle command is working fine through the command line. However, when I try to sync from Android Studio, the following error is displayed: 'Missing ExternalProject for:'

  5. WarrenBuffering commented on Jul 11, 2024

    @WarrenBuffering

    Are you saying these changes worked for you @rahulpandey? Or are you still getting the Missing ExternalProject for: error?

  6. bimusiek commented on Jul 17, 2024

    @bimusiek

    For us we had react native working with pnpm without hoisting. With new arch enabled. Then at one point of upgrading to newest RN, it stopped working with the error:

    Missing ExternalProject for :
    

    However, it works if using gradle from the command line.

  7. bimusiek commented on Jul 17, 2024

    @bimusiek

    Ok, I found the fix for React Native.

    Instead of

    includeBuild('../node_modules/@react-native/gradle-plugin')
    

    you have to do

    includeBuild(file("../node_modules/@react-native/gradle-plugin").toPath().toRealPath().toAbsolutePath().toString())
    

    then it works in newest Android Studio.

  8. JDScript commented on Jul 17, 2024

    @JDScript

    Ok, I found the fix for React Native.

    Instead of

    includeBuild('../node_modules/@react-native/gradle-plugin')
    

    you have to do

    includeBuild(file("../node_modules/@react-native/gradle-plugin").toPath().toRealPath().toAbsolutePath().toString())
    

    then it works in newest Android Studio.

    You saved my day!!!!

  9. shaquibimdad commented on Aug 1, 2024

    @shaquibimdad
        "@react-native-community/cli": "^13.6.4",
        "@react-native-community/cli-platform-android": "^13.6.4",
        "@react-native-community/cli-platform-ios": "^13.6.4",
        "@react-native/gradle-plugin": "^0.74.86",
    

    adding above deps to dev dependencies and then from @bimusiek solution for android studio

    pnpm works smoothly no issues so far

  10. GSFZamai commented on Sep 12, 2025

    @GSFZamai

    Hi there, hope you're fine.
    I'm struggling to run my development environment on iOS:
    I'm getting the following error message:
    .../node_modules/.pnpm/react-native@0.80.2_@babel+core@7.28.3_@react-native-community+cli@19.1.1_typescript@5._3af7c2724a56ff00268a468b9be1dd98/node_modules/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h:10:10 'jsinspector-modern/cdp/CdpJson.h' file not found
    But I noticed that the file existe, because when I click in the import reference It navigates to the file. I think this might be a module resolution.

    I'm using:

    pnpm: 10.14.0,
    react: 19.1.0,
    react-native: 0.80.2
    

    On Android It's working fine until now

  11. rmit-s3804879-sainathreddy-kodiganti commented on Sep 17, 2025

    @rmit-s3804879-sainathreddy-kodiganti

    Hey @GSFZamai ,

    were you able to fix this?

  12. GSFZamai commented on Sep 17, 2025

    @GSFZamai

    Hey @GSFZamai ,

    were you able to fix this?

    Hey!
    My decision atm was to change the package manager to yarn.

  13. bimusiek commented on Oct 4, 2025

    @bimusiek
  14. devBaunz commented on Nov 24, 2025

    @devBaunz

    Works just fine, assuming the following tweaks made:

    metro.config.js

    const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
    const path = require("path");
    
    /**
     * Metro configuration
     * https://reactnative.dev/docs/metro
     * Tweaks by @devBaunz
     *
     * @type {import('metro-config').MetroConfig}
     */
    const config = {
      // This means we watch the entire repo (change path accordingly if needed)
      watchFolders: [path.join(__dirname, "..", "..")],
      resolver: {
        nodeModulesPaths: [
          // PNPM installs symlink app's node_modules, not workspace one
          path.resolve(__dirname, "node_modules"),
        ],
        // This allows us to work with PNPM
        unstable_enablePackageExports: true,
      },
      // If you use react-native-reanimated, you might need this
      // transformer: {
      //   getTransformOptions: async () => ({
      //     transform: {
      //       experimentalImportSupport: false,
      //       inlineRequires: true,
      //     },
      //   }),
      // },
    };
    
    module.exports = mergeConfig(getDefaultConfig(__dirname), config);

    settings.gradle (optional, if you want to use AndroidStudio directly), thanks to @bimusiek

    // NOTE: Handle via node-module paths
    pluginManagement { includeBuild(file("../node_modules/@react-native/gradle-plugin").toPath().toRealPath().toAbsolutePath().toString()) }
    plugins { id("com.facebook.react.settings") }
    extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
    rootProject.name = 'YourAppName'
    include ':app'
    includeBuild(file("../node_modules/@react-native/gradle-plugin").toPath().toRealPath().toAbsolutePath().toString())

    babel.config.js (extra, if you want to use node functionality such as crypto/buffer) (make sure you have the packages as runtime dependancies)

    module.exports = {
      presets: ["module:@react-native/babel-preset"],
      plugins: [
        [
          "module-resolver",
          {
            root: ["."],
            alias: {
              // Node functionality for react-native
              crypto: "react-native-quick-crypto",
              "node:crypto": "react-native-quick-crypto",
              stream: "readable-stream",
              "node:stream": "readable-stream",
              buffer: "@craftzdog/react-native-buffer",
              "node:buffer": "@craftzdog/react-native-buffer",
            },
          },
        ],
      ],
    };

    Another nice change to make if you want a better pnpm experience in monorepo setup:

    .npmrc (allows installing per directory with proper dep-management, mainly useful for ci/cd)

    legacy-peer-deps=true
    registry=https://registry.npmjs.org/
    link-workspace-packages=true
    recursive-install=false
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions