Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metro resolver could not resolve an import when run via xCode or from deeper directory - works without watchman #1426

Open
genesiscz opened this issue Jan 13, 2025 · 0 comments

Comments

@genesiscz
Copy link

genesiscz commented Jan 13, 2025

React Native version: 0.76.6
Metro version: 0.81.0
Watchman version: 2024.12.02.00

Hello. I am sorry this is long but I try to be as descriptive as possible. I am trying to upgrade RN 0.72.6 all the way up to the newest version and while I managed to make the project running when i do yarn start and press i (iOS), it just is incostent with xCode way of build. I have the react-native app in monorepo that spans multiple folders (e.g., packages/, col-mobile/, col-web/). node_modules are in the root and in the col-mobile/ folder too.

The first problem

Note: Full metro.config.js file below.

When I run the same command xCode does, in <projectDir>/col-mobile/ios:

node /Users/Martin/Tresors/Projects/<projectDir>/col-mobile/node_modules/react-native/scripts/bundle.js bundle --entry-file index.js --platform ios --dev true --reset-cache --bundle-output /Users/Martin/Library/Developer/Xcode/DerivedData/ColMobile-eefulauxzmjhbdgyseffwktprjcy/Build/Products/Debug-iphoneos/main.jsbundle --assets-dest /Users/Martin/Library/Developer/Xcode/DerivedData/ColMobile-eefulauxzmjhbdgyseffwktprjcy/Build/Products/Debug-iphoneos/ColMobile.app --config-cmd 'node  /Users/Martin/Tresors/Projects/<projectDir>/col-mobile/node_modules/react-native/cli.js config'

I get the following error (note that it says "unable to resolve module packages/" without the dots at the start - ../ which might be NOT wrong but changes when I run it from the col-mobile folder):

/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:148
        throw new UnableToResolveError(
              ^

UnableToResolveError: Unable to resolve module packages/col-tech/common/mobile/src/theme/themeConfigurations from /Users/Martin/Tresors/Projects/<projectDir>/col-mobile/App.tsx: packages/col-tech/common/mobile/src/theme/themeConfigurations could not be found within the project or in these directories:
  node_modules
  ../node_modules
  ../../../../../node_modules
  ...
> 6 | import { loadThemeConfigurations } from "packages/col-tech/common/mobile/src/theme/themeConfigurations";
    |                                          ^
  7 | import { AuthProvider } from "col-mobile/auth/AuthProvider";
  ...
  at ModuleResolver.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:148:15)
    at DependencyGraph.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph.js:235:43)
    ... 4 lines matching cause stack trace ...
    at async Promise.all (index 3)
    at async visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:92:5)
    at async Promise.all (index 3)
    at async visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:92:5) {
  originModulePath: '/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/App.tsx',
  targetModuleName: 'packages/col-tech/common/mobile/src/theme/themeConfigurations',
  cause: FailedToResolveNameError: Module does not exist in the Haste module map or in these directories:
    /Users/Martin/Tresors/Projects/<projectDir>/col-mobile/node_modules
    /Users/Martin/Tresors/Projects/<projectDir>/node_modules
    /Users/Martin/Tresors/Projects/CEZ/node_modules
    /Users/Martin/Tresors/Projects/node_modules
    /Users/Martin/Tresors/node_modules
    /Users/Martin/node_modules
    /Users/node_modules
    /node_modules
  
      at Object.resolve (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro-resolver/src/resolve.js:158:9)
      at resolveRequest (/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/metro.config.js:64:25)
      at Object.resolve (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro-resolver/src/resolve.js:35:12)
      at ModuleResolver.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:73:31)
      at DependencyGraph.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph.js:235:43)
      at /Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/lib/transformHelpers.js:160:21
      at resolveDependencies (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:42:25)
      at visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:83:30)
      at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
      at async Promise.all (index 3) {
    dirPaths: [
      '/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/node_modules',
      '/Users/Martin/Tresors/Projects/<projectDir>/node_modules',
      '/Users/Martin/Tresors/Projects/CEZ/node_modules',
      '/Users/Martin/Tresors/Projects/node_modules',
      '/Users/Martin/Tresors/node_modules',
      '/Users/Martin/node_modules',
      '/Users/node_modules',
      '/node_modules'
    ],
    extraPaths: []
  }
}

But when I run the command from <projectDir>/col-mobile, it builds properly. Of course, that could be a problem with current working directory, so I tried to change the PWD at top of the metro.config.js (ugly, but worked when running from terminal):

process.chdir(__dirname, "../col-mobile/");

The metro config with chdir

const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
const path = require("path");
const process = require("process");
const resolver = require("metro-resolver");
const repositoryRoot = path.resolve(__dirname, "../col-mobile/");

// Fixes resolution when the bundler is run from ios/ directory
process.chdir(__dirname, "../col-mobile/");

/**
 * Metro configuration
 * https://reactnative.dev/docs/metro
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
	cacheStores: ({ FileStore }) => [
		new FileStore({
			root: path.join(__dirname, "metro-cache4"),
		}),
	],
	transformer: {
		minifierConfig: {
			mangle: { toplevel: false },
			output: {
				ascii_only: true,
				comments: false,
				quote_style: 3,
				wrap_iife: true,
			},
			sourceMap: { includeSources: false },
			toplevel: false,
			compress: { reduce_funcs: false },
		},
	},
	resolver: {
		useWatchman: true, // does work with watchman, but not in xCode with watchman enabled. 
		projectRoot: repositoryRoot,
		sourceExts: ["js", "jsx", "json", "ts", "tsx"],
		resolverMainFields: ["react-native", "browser", "local", "main"],
		hasteImplModulePath: path.resolve(__dirname, "../col-mobile/haste.js"),
		resolveRequest: (context, moduleName, platform) => {
			const resolveRealPath = (absolutePath) => {
				return absolutePath;
			};

			const resolve = (moduleName, platform) => {
				return context.resolveRequest(context, moduleName, platform);
			};

			if (moduleName.includes("packages/")) {
				const aa = resolver.resolve(context, moduleName, platform);
				console.log("[AAA] " + moduleName + " and resolved is " + aa);
				return aa;
			}

			/// ... more code here which isn't resolved for the themeConfigurations file 
			
			return resolver.resolve({ ...context, resolveRequest: resolver.resolve }, moduleName, platform);
		},
	},
	watchFolders: [
		path.join(__dirname, "../col-web/"),
		path.join(__dirname, "../packages/"),
		path.join(__dirname, "../node_modules"),
		path.join(__dirname, "../mocks/"),
	],
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);

Problem number 2

It works! But only in Terminal. When I run build in xCode, it fails searching for the themeConfigurations.ts file. The weird thing is, the error contains a full path to the file it DID NOT FIND. The file does exist though. I guess watchman didn't pick it up somehow and the lookup is through watchman I suppose. And yes, I did this command like a hundred times:

watchman watch-del '/Users/Martin/Tresors/Projects/<projectDir>/' ; watchman watch-project '/Users/Martin/Tresors/Projects/<projectDir>/'

The error (note the I guess correct "../packages"; also, look at the <-------------- line):

UnableToResolveError: Unable to resolve module ../packages/col-tech/common/mobile/src/theme/themeConfigurations from /Users/Martin/Tresors/Projects/<projectDir>/col-mobile/App.tsx: 


None of these files exist:

  * ../packages/col-tech/common/mobile/src/theme/themeConfigurations(.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx)
  * ../packages/col-tech/common/mobile/src/theme/themeConfigurations

...

import { loadThemeConfigurations } from "packages/col-tech/common/mobile/src/theme/themeConfigurations"

...

    at ModuleResolver.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:112:15)
    at DependencyGraph.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph.js:235:43)
    ... 4 lines matching cause stack trace ...
    at async Promise.all (index 3)
    at async visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:92:5)
    at async Promise.all (index 3)
    at async visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:92:5) {
  originModulePath: '/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/App.tsx',
  targetModuleName: '../packages/col-tech/common/mobile/src/theme/themeConfigurations',
  cause: FailedToResolvePathError: The module could not be resolved because none of these files exist:

    * /Users/Martin/Tresors/Projects/<projectDir>/packages/col-tech/common/mobile/src/theme/themeConfigurations(.ios.js|.native.js|.js|.ios.jsx|.native.jsx|.jsx|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx) <--------------
    * /Users/Martin/Tresors/Projects/<projectDir>/packages/col-tech/common/mobile/src/theme/themeConfigurations
      at Object.resolve (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro-resolver/src/resolve.js:49:13)
      at resolveRequest (/Users/Martin/Tresors/Projects/<projectDir>/col-mobile/metro.config.js:73:25)
      at Object.resolve (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro-resolver/src/resolve.js:35:12)
      at ModuleResolver.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:73:31)
      at DependencyGraph.resolveDependency (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/node-haste/DependencyGraph.js:235:43)
      at /Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/lib/transformHelpers.js:160:21
     at resolveDependencies (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:42:25)
      at visit (/Users/Martin/Tresors/Projects/<projectDir>/node_modules/metro/src/DeltaBundler/buildSubgraph.js:83:30)
      at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
      at async Promise.all (index 3) {
    candidates: {
      file: {
        type: 'sourceFile',
        filePathPrefix: '../packages/col-tech/common/mobile/src/theme/themeConfigurations',
        candidateExts: [
          '',             '.ios.js',
          '.native.js',   '.js',
          '.ios.jsx',     '.native.jsx',
          '.jsx',         '.ios.json',
          '.native.json', '.json',
          '.ios.ts',      '.native.ts',
          '.ts',          '.ios.tsx',
          '.native.tsx',  '.tsx'
        ]
      },
      dir: {
        type: 'sourceFile',
        filePathPrefix: '../packages/col-tech/common/mobile/src/theme/themeConfigurations',
        candidateExts: []
      }
    }
  }
}

However, when I do

cat /Users/Martin/Tresors/Projects/<projectDir>/packages/col-tech/common/mobile/src/theme/themeConfigurations.ts

I get the contents of the file.

When I set useWatchman: false in the metro config, it manages to build just fine. But I guess I will lose fast refresh and so on.

What is going on? It was working in previous versions of react-native (Metro). I can give more info if needed.

@genesiscz genesiscz changed the title Metro resolver could not find a file when run via xCode when useWatchman === true Metro resolver could not resolve an import when run via xCode or from deeper directory - works without watchman Jan 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant