For quite a while, metro and pnpm didn't play well with each other. Usually workarounds involved "shamefully-hoisting" which negated many benefits of pnpm.
However, recently metro has added support for symlinks (though marked unstable as of this writing) which makes it possible for us to use a react-native + metro project with pnpm.
There are a few considerations though:
You may need to install some additional dev dependencies which didn't before.
There are some dependencies which the RN project generated by the scaffolder uses, but doesn't depend on directly. They are just assumed to be available due to hoisting behavior of npm.
pnpm adopts a more principled stance towards dependency hosting, which IMHO is better. So, you will need directly depend on these packages.
pnpm i -D @react-native/gradle-plugin @react-native-community/cli-platform-android @react-native-community/cli
Be mindful of versions if you are updating an older project that is not yet updated to use latest RN.
Metro still needs to be aware of all source roots. This is an issue if we are also using pnpm workspaces.
While the bundler can follow symlinks, we still need to explicitly register all the root directories which may contain bundled files (including the symlink targets) through the rather weirdly named
watchFolders
.From the official docs
Despite the naming of this option, it isn't related solely to file watching. Even in an offline build (for example, in CI), all files must be visible to Metro through the combination of watchFolders and projectRoot.
So let's say your RN project depends on another module in the pnpm workspace called
shared
, we need the following inmetro.config.js
:module.exports = mergeConfig(defaultConfig, { // ... other config watchFolders: [ __dirname, path.resolve(__dirname, "../../node_modules"), // Should resolve to top level node_modules path.resolve(__dirname, "../shared"), // Any other modules the RN project depends on ], }
As shown above, we also need to add the top level
node_modules
folder where pnpm will install the dependencies.
And that is pretty much all that is needed.