From e87bf395e1923b15bb37bd43752b8549e8a09efa Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Fri, 19 Jul 2024 12:25:45 -0700 Subject: [PATCH] fix(react-native): fix unable to resolve realm (#26983) ## Current Behavior ## Expected Behavior ## Related Issue(s) Fixes https://github.com/nrwl/nx/issues/26853 --- packages/expo/plugins/metro-resolver.ts | 45 ++++++++++++++----- packages/expo/plugins/with-nx-metro.ts | 27 ++++++++++- .../react-native/plugins/metro-resolver.ts | 45 ++++++++++++++----- .../react-native/plugins/with-nx-metro.ts | 27 ++++++++++- 4 files changed, 120 insertions(+), 24 deletions(-) diff --git a/packages/expo/plugins/metro-resolver.ts b/packages/expo/plugins/metro-resolver.ts index 9273b187ee..1ba2779331 100644 --- a/packages/expo/plugins/metro-resolver.ts +++ b/packages/expo/plugins/metro-resolver.ts @@ -13,7 +13,11 @@ import { workspaceRoot } from '@nx/devkit'; * This resolve function requires projectRoot to be set to * workspace root in order modules and assets to be registered and watched. */ -export function getResolveRequest(extensions: string[]) { +export function getResolveRequest( + extensions: string[], + exportsConditionNames: string[] = [], + mainFields: string[] = [] +) { return function ( _context: any, realModuleName: string, @@ -21,8 +25,6 @@ export function getResolveRequest(extensions: string[]) { ) { const debug = process.env.NX_REACT_NATIVE_DEBUG === 'true'; - if (debug) console.log(chalk.cyan(`[Nx] Resolving: ${realModuleName}`)); - const { resolveRequest, ...context } = _context; const resolvedPath = @@ -32,16 +34,23 @@ export function getResolveRequest(extensions: string[]) { realModuleName, platform, debug - ) || - defaultMetroResolver(context, realModuleName, platform, debug) || + ) ?? + defaultMetroResolver(context, realModuleName, platform, debug) ?? tsconfigPathsResolver( context, extensions, realModuleName, platform, debug - ) || - pnpmResolver(extensions, context, realModuleName, debug); + ) ?? + pnpmResolver( + extensions, + context, + realModuleName, + debug, + exportsConditionNames, + mainFields + ); if (resolvedPath) { return resolvedPath; } @@ -104,7 +113,9 @@ function pnpmResolver( extensions: string[], context: any, realModuleName: string, - debug: boolean + debug: boolean, + exportsConditionNames: string[] = [], + mainFields: string[] = [] ) { try { const pnpmResolve = getPnpmResolver(extensions); @@ -199,7 +210,11 @@ function getMatcher(debug: boolean) { * It is inspired form https://github.com/vjpr/pnpm-expo-example/blob/main/packages/pnpm-expo-helper/util/make-resolver.js. */ let resolver; -function getPnpmResolver(extensions: string[]) { +function getPnpmResolver( + extensions: string[], + exportsConditionNames: string[] = [], + mainFields: string[] = [] +) { if (!resolver) { const fileSystem = new CachedInputFileSystem(fs, 4000); resolver = ResolverFactory.createResolver({ @@ -207,8 +222,16 @@ function getPnpmResolver(extensions: string[]) { extensions: extensions.map((extension) => '.' + extension), useSyncFileSystemCalls: true, modules: [join(workspaceRoot, 'node_modules'), 'node_modules'], - conditionNames: ['native', 'browser', 'require', 'default'], - mainFields: ['react-native', 'browser', 'main'], + conditionNames: [ + 'native', + 'browser', + 'require', + 'default', + 'react-native', + 'node', + ...exportsConditionNames, + ], + mainFields: ['react-native', 'browser', 'main', ...mainFields], aliasFields: ['browser'], }); } diff --git a/packages/expo/plugins/with-nx-metro.ts b/packages/expo/plugins/with-nx-metro.ts index 1e7716705e..43f9bbbe1d 100644 --- a/packages/expo/plugins/with-nx-metro.ts +++ b/packages/expo/plugins/with-nx-metro.ts @@ -7,9 +7,30 @@ import { join } from 'path'; import { getResolveRequest } from './metro-resolver'; interface WithNxOptions { + /** + * Change this to true to see debugging info. + */ debug?: boolean; + /** + * A list of additional file extensions to resolve + * All the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx', 'json' + */ extensions?: string[]; + /** + * A list of additional folders to watch for changes + * By default, it watches all the folders in the workspace root except 'dist' and 'e2e' + */ watchFolders?: string[]; + /* + * A list of exports field condition names in node_modules libraries' package.json + * If a library has a package.json with an exports field, but it can't be resolved with the default conditions, you can add the name of the condition to this list. + */ + exportsConditionNames?: string[]; + /** + * A list of main fields in package.json files to use for resolution + * If a library has a package.json with a main field that can't be resolved with the default conditions, you can add the name of the field to this list. + */ + mainFields?: string[]; } export async function withNxMetro( @@ -38,7 +59,11 @@ export async function withNxMetro( const nxConfig: MetroConfig = { resolver: { - resolveRequest: getResolveRequest(extensions), + resolveRequest: getResolveRequest( + extensions, + opts.exportsConditionNames, + opts.mainFields + ), nodeModulesPaths: [join(workspaceRoot, 'node_modules')], }, watchFolders, diff --git a/packages/react-native/plugins/metro-resolver.ts b/packages/react-native/plugins/metro-resolver.ts index 9273b187ee..1ba2779331 100644 --- a/packages/react-native/plugins/metro-resolver.ts +++ b/packages/react-native/plugins/metro-resolver.ts @@ -13,7 +13,11 @@ import { workspaceRoot } from '@nx/devkit'; * This resolve function requires projectRoot to be set to * workspace root in order modules and assets to be registered and watched. */ -export function getResolveRequest(extensions: string[]) { +export function getResolveRequest( + extensions: string[], + exportsConditionNames: string[] = [], + mainFields: string[] = [] +) { return function ( _context: any, realModuleName: string, @@ -21,8 +25,6 @@ export function getResolveRequest(extensions: string[]) { ) { const debug = process.env.NX_REACT_NATIVE_DEBUG === 'true'; - if (debug) console.log(chalk.cyan(`[Nx] Resolving: ${realModuleName}`)); - const { resolveRequest, ...context } = _context; const resolvedPath = @@ -32,16 +34,23 @@ export function getResolveRequest(extensions: string[]) { realModuleName, platform, debug - ) || - defaultMetroResolver(context, realModuleName, platform, debug) || + ) ?? + defaultMetroResolver(context, realModuleName, platform, debug) ?? tsconfigPathsResolver( context, extensions, realModuleName, platform, debug - ) || - pnpmResolver(extensions, context, realModuleName, debug); + ) ?? + pnpmResolver( + extensions, + context, + realModuleName, + debug, + exportsConditionNames, + mainFields + ); if (resolvedPath) { return resolvedPath; } @@ -104,7 +113,9 @@ function pnpmResolver( extensions: string[], context: any, realModuleName: string, - debug: boolean + debug: boolean, + exportsConditionNames: string[] = [], + mainFields: string[] = [] ) { try { const pnpmResolve = getPnpmResolver(extensions); @@ -199,7 +210,11 @@ function getMatcher(debug: boolean) { * It is inspired form https://github.com/vjpr/pnpm-expo-example/blob/main/packages/pnpm-expo-helper/util/make-resolver.js. */ let resolver; -function getPnpmResolver(extensions: string[]) { +function getPnpmResolver( + extensions: string[], + exportsConditionNames: string[] = [], + mainFields: string[] = [] +) { if (!resolver) { const fileSystem = new CachedInputFileSystem(fs, 4000); resolver = ResolverFactory.createResolver({ @@ -207,8 +222,16 @@ function getPnpmResolver(extensions: string[]) { extensions: extensions.map((extension) => '.' + extension), useSyncFileSystemCalls: true, modules: [join(workspaceRoot, 'node_modules'), 'node_modules'], - conditionNames: ['native', 'browser', 'require', 'default'], - mainFields: ['react-native', 'browser', 'main'], + conditionNames: [ + 'native', + 'browser', + 'require', + 'default', + 'react-native', + 'node', + ...exportsConditionNames, + ], + mainFields: ['react-native', 'browser', 'main', ...mainFields], aliasFields: ['browser'], }); } diff --git a/packages/react-native/plugins/with-nx-metro.ts b/packages/react-native/plugins/with-nx-metro.ts index 1e7716705e..43f9bbbe1d 100644 --- a/packages/react-native/plugins/with-nx-metro.ts +++ b/packages/react-native/plugins/with-nx-metro.ts @@ -7,9 +7,30 @@ import { join } from 'path'; import { getResolveRequest } from './metro-resolver'; interface WithNxOptions { + /** + * Change this to true to see debugging info. + */ debug?: boolean; + /** + * A list of additional file extensions to resolve + * All the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx', 'json' + */ extensions?: string[]; + /** + * A list of additional folders to watch for changes + * By default, it watches all the folders in the workspace root except 'dist' and 'e2e' + */ watchFolders?: string[]; + /* + * A list of exports field condition names in node_modules libraries' package.json + * If a library has a package.json with an exports field, but it can't be resolved with the default conditions, you can add the name of the condition to this list. + */ + exportsConditionNames?: string[]; + /** + * A list of main fields in package.json files to use for resolution + * If a library has a package.json with a main field that can't be resolved with the default conditions, you can add the name of the field to this list. + */ + mainFields?: string[]; } export async function withNxMetro( @@ -38,7 +59,11 @@ export async function withNxMetro( const nxConfig: MetroConfig = { resolver: { - resolveRequest: getResolveRequest(extensions), + resolveRequest: getResolveRequest( + extensions, + opts.exportsConditionNames, + opts.mainFields + ), nodeModulesPaths: [join(workspaceRoot, 'node_modules')], }, watchFolders,