External module can't resolve it's dependencies

I configured metro.config.js with the extraNodeModules setting so metro will find my shared modules from outside my project.

Metro is finding my external module (see dumb-module below), but I’m getting an error when that external module tries to import react. I get no error when the imported module does not import react.

Here’s the error:

Unable to resolve module @babel/runtime/helpers/interopRequireDefault from /Users/jim/.../modules/dumb-module/index.js: @babel/runtime/helpers/interopRequireDefault could not be found within the project.

If you are sure the module exists, try these steps:
 1. Clear watchman watches: watchman watch-del-all
 2. Delete node_modules and run yarn install
 3. Reset Metro's cache: yarn start --reset-cache
 4. Remove the cache: rm -rf /tmp/metro-*
> 1 | import React from 'react';
  2 | import { Text } from 'react-native';
  3 |
  4 | const DumbModule = () => {

Because it’s showing the contents of dumb-module, it’s clearly able to find my external modules. But it looks like it can’t resolve that module trying to import react.

I’ve tried, as you might expect, everything. Would love to get some ideas here.

metro.config.js

const path = require('path');

const extraNodeModules = {
    'modules': path.resolve(path.join(__dirname, '../../modules'))
};

const watchFolders = [
    path.resolve(path.join(__dirname, '../../modules'))
];

const nodeModulesPaths = [path.resolve(path.join(__dirname, './node_modules'))];

module.exports = {
    transformer: {
        getTransformOptions: async () => ({
            transform: {
                experimentalImportSupport: true,
                inlineRequires: true,
            },
        }),
    },
    resolver: {
        extraNodeModules,
        nodeModulesPaths
    },
    watchFolders
};

dumb-module/index.js

import React from 'react';
import { Text } from 'react-native';

const DumbModule = () => {
    return (
        <Text>I am useless.</Text>
    );
};

export default DumbModule;

expo diagnostics:

expo diagnostics

  Expo CLI 4.12.0 environment info:
    System:
      OS: macOS 11.6
      Shell: 5.8 - /bin/zsh
    Binaries:
      Node: 14.16.1 - ~/.nvm/versions/node/v14.16.1/bin/node
      Yarn: 1.22.11 - ~/.nvm/versions/node/v14.16.1/bin/yarn
      npm: 7.24.0 - ~/.nvm/versions/node/v14.16.1/bin/npm
    Managers:
      CocoaPods: 1.11.2 - /usr/local/bin/pod
    SDKs:
      iOS SDK:
        Platforms: iOS 15.0, DriverKit 20.4, macOS 11.3, tvOS 15.0, watchOS 8.0
    IDEs:
      Xcode: 13.0/13A233 - /usr/bin/xcodebuild
    npmPackages:
      expo: ~42.0.1 => 42.0.4 
      react: 16.13.1 => 16.13.1 
      react-dom: 16.13.1 => 16.13.1 
      react-native: https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz => 0.63.2 
      react-native-web: ~0.13.12 => 0.13.18 
    npmGlobalPackages:
      expo-cli: 4.12.0
    Expo Workflow: managed

OK, I think I figured out what I was doing wrong.

Indeed the trick to make this work was adding my app’s node_modules path to nodeModulesPaths in metro.config.js. The above config file lets expo pull in modules from outside it’s tree, and lets those modules resolve from within the tree.

Combined with the yarn “nohoist” option set on the app in the root package.json, this appears to work without the need for expo-yarn-workspaces.

(What was holding me back was that somewhere along the way I got the broken notion that --reset-cache had been replaced by --clear, so much of my debugging was blunted by the metro cache being out of date.)

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.