npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-monorepo-config

v0.3.3

Published

Configure Metro for a React Native app in a monorepo

Readme

react-native-monorepo-config

Helper to configure Metro for a React Native app in a monorepo.

Why

Metro (React Native's bundler) doesn't work well with monorepos out of the box. This package is intended to make the configuration easier.

Installation

npm install --save-dev react-native-monorepo-config

Also make sure that your're using recent version of Node.js, i.e. v20.19.0 and higher (LTS), v22.12.0 and higher (LTS) or v23.4.0 and higher.

Usage

Let's consider the following monorepo structure:

my-monorepo
├── apps
│   └── my-app
└── packages
    ├── a
    └── b

Here, my-app is a React Native app, and a and b are libraries that are used in the app.

To configure Metro for my-app, you can create a metro.config.js file in the my-app directory with the following content:

const path = require('path');
const { getDefaultConfig } = require('@react-native/metro-config'); // Import from `@expo/metro-config` if using Expo CLI
const { withMetroConfig } = require('react-native-monorepo-config');

module.exports = withMetroConfig(
  getDefaultConfig(__dirname), // Metro config to extend
  {
    root: path.resolve(__dirname, '../..'), // Path to the monorepo root
    dirname: __dirname, // Path to the current directory
  }
);

It's also recommended to disable hoisting for the React Native app's dependencies to avoid issues.

For Yarn 4, hoisting can be disabled by setting nmHoistingLimits: 'workspaces' in .yarnrc.yml. See Yarn documentation for more details.

If you want to customize the returned Metro config, remember to merge the returned config with your custom config. For example:

const monoRepoConfig = withMetroConfig(getDefaultConfig(__dirname), {
  root: path.resolve(__dirname, '../..'),
  dirname: __dirname,
});

module.exports = {
  ...monoRepoConfig,

  resolver: {
    ...monoRepoConfig.resolver,

    assetExts: monoRepoConfig.resolver.assetExts.filter((ext) => ext !== 'svg'),
    sourceExts: [...monoRepoConfig.resolver.sourceExts, 'svg'],
  },
};

Custom workspaces

By default, the workspaces are read from the workspaces field in the monorepo root's package.json. If you want to specify a custom list of workspaces, you can pass a workspaces array to the options:

const monoRepoConfig = withMetroConfig(getDefaultConfig(__dirname), {
  root: path.resolve(__dirname, '../..'),
  dirname: __dirname,
  workspaces: ['packages/a', 'packages/b'],
});

The workspaces can contain globs or relative paths. They will be resolved relative to the monorepo root.

This can be useful if you're not using Yarn workspaces or if you want to include only specific packages to improve performance in large monorepos.

How it works

This configuration will setup a few things:

  • Configure Metro to watch for changes in the monorepo root instead of only the current package.

    This may slow down the bundling process in large monorepos. In that case, you can override watchFolders to add specific folders to watch instead:

    module.exports = {
      watchFolders: [
        path.resolve(__dirname),
        // Path to packages that the app depends on
        path.resolve(__dirname, '../packages/a'),
        path.resolve(__dirname, '../packages/b'),
      ],
    
      ...monoRepoConfig,
    };
  • Block packages defined in peerDependencies of other packages in the monorepo to avoid duplicate versions from being loaded. They must be added under dependencies or devDependencies in the app's package.json to be resolved correctly.

    Loading duplicate versions of some packages such as react can cause issues. So this way multiple versions are not loaded. Make sure to specify peerDependencies for your packages appropriately.

  • If the packages defined in peerDependencies have been hoisted to the monorepo root, point Metro to them so they can be found.

  • Configure Metro's resolver to prioritize package.json#source or the source condition in package.json#exports so that the app can import source code directly from other packages in the monorepo.

    To utilize this, make sure to add the source field to the package.json of the packages you want to import from, e.g.:

    "source": "src/index.ts"

    Or in the exports field if you're using exports field and Metro 0.82.0+:

    "exports": {
       ".": {
         "source": "./src/index.ts",
         // other conditions...
       },
     }