Module resolution
Module resolution is the process by which a bundler determines which file to load when you import a module. In React Native, this process has unique requirements—platform-specific files, scaled assets, and the react-native condition in package exports all need special handling.
Re.Pack is designed to match Metro's resolution behavior as closely as possible, ensuring that projects migrating from Metro or using libraries designed for Metro work correctly.
Getting module resolution right ensures that:
- Platform-specific files (
.ios.js,.android.js) load correctly for each target - Libraries with React Native-specific entry points work as expected
- Scaled assets (
@2x,@3ximages) resolve properly
How Re.Pack resolves modules
Re.Pack configures the underlying bundler's resolver to match Metro's behavior. When using Rspack, resolution is handled by rspack-resolver—a Rust port of enhanced-resolve with the same interface. When using webpack, the original enhanced-resolve is used.
The getResolveOptions() utility returns the configuration needed to match Metro's resolution behavior:
Resolution happens per-platform—each build (iOS, Android, etc.) runs as a separate bundler process with platform-specific resolution configured automatically based on the target platform.
Platform-specific resolution
React Native allows you to create platform-specific versions of files using special extensions. Re.Pack resolves these extensions in the following order:
.{platform}.{ext}(e.g.,.ios.js,.android.js).native.{ext}(whenpreferNativePlatform: true, which is the default).{ext}(base extension)
Example
Given a request for ./component on iOS, Re.Pack will look for files in this order:
The same request on Android:
Supported source extensions
Re.Pack supports these source file extensions by default:
.js,.jsx.ts,.tsx.json
Each of these can be combined with platform and native extensions:
Disabling native extension fallback
If you don't want .native.* files to be resolved as fallbacks, set preferNativePlatform to false:
This is useful when building for non-native platforms (like web) where .native.* files might contain React Native-specific code that won't work in a browser.
With this setting, a request for ./component on a web platform would only check:
Package resolution (main fields)
Main fields are package.json properties that point to a package's entry file. Packages can specify different entry points for different environments—main for Node.js, browser for web, react-native for React Native.
When resolving a package's entry point, Re.Pack checks these fields in package.json in order:
react-native— React Native-specific entry pointbrowser— Browser-compatible entry pointmain— Standard Node.js entry point
This matches Metro's default configuration and ensures React Native-optimized code is preferred.
Example
Given this package.json:
Re.Pack will resolve to lib/native.js because react-native has the highest priority.
For more details on how main fields work, see the resolve.mainFields documentation.
Package exports (conditional exports)
Package exports (exports field in package.json) are a modern replacement for main fields. They let packages define multiple entry points (e.g., pkg/utils), serve different code per environment, and hide internal files. See the Node.js docs for details.
Modern packages use the exports field in package.json to define entry points with conditions. Re.Pack supports this through the enablePackageExports option.
Package exports support is disabled by default (enablePackageExports: false) to maintain backwards compatibility with existing React Native projects. Enable it explicitly if your dependencies require it.
Enabling package exports
How conditional exports work
When enabled, Re.Pack uses the react-native condition to resolve packages. The resolver also differentiates between ESM and CommonJS:
- ESM imports: Uses conditions
['react-native', 'import'] - CommonJS requires: Uses conditions
['react-native', 'require']
These ESM/CJS conditions are always configured (via byDependency) to support package imports, even when enablePackageExports is false.
Example package with exports
With enablePackageExports: true, importing this package in React Native will resolve to the react-native condition entry points.
Some packages may have exports configurations that work differently than their main/react-native field configurations. Test thoroughly when enabling this option in existing projects.
Asset resolution
Re.Pack handles scaled assets (images with @1x, @2x, @3x suffixes) automatically using extensionAlias configuration.
Supported scalable assets
Images that support resolution scaling:
bmp,gif,jpg,jpeg,png,psd,svg,webp,tiff
How scaled resolution works
When you import an image like ./icon.png, Re.Pack's extensionAlias configuration allows the resolver to find scaled variants:
The actual asset selection (choosing the right scale for the device) happens at runtime through React Native's asset system.
Other supported asset types
Re.Pack also supports these non-scalable asset types:
- Video:
m4v,mov,mp4,mpeg,mpg,webm - Audio:
aac,aiff,caf,m4a,mp3,wav - Documents:
html,pdf,yaml,yml - Fonts:
otf,ttf - Other:
zip,obj
Troubleshooting
Most resolution issues can be solved with two configuration options:
resolve.alias— Redirect imports to a different module or filemodule.rules— Control how specific modules are processed
Package not resolving correctly
- Check the package's
package.json— Look atmain,react-native,browser, andexportsfields - Verify platform extensions — Ensure platform-specific files use correct naming (
.ios.js, not.iOS.js) - Check
enablePackageExports— Some modern packages require this to betrue
Platform-specific files not being picked up
- Verify file naming — Extensions must be lowercase (
.ios.js, not.IOS.js) - Check the platform value — Ensure you're building for the correct target platform
- Inspect resolve configuration — Log the output of
getResolveOptions()to verify extensions order
Package exports compatibility issues
When enabling enablePackageExports, some packages may resolve differently:
- Compare with Metro — Test the same import in a Metro-bundled project
- Check condition order — The
react-nativecondition should take precedence - Inspect the package — Some packages have incorrect or incomplete
exportsconfigurations
Related documentation
- getResolveOptions — API reference
- Rspack resolve configuration — Rspack resolver options
- webpack resolve configuration — webpack resolver options
- Code Splitting — For chunk resolution
- Glossary — Terminology reference


