or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asset-resolution.mdcustom-resolvers.mderror-handling.mdindex.mdpackage-resolution.mdresolution-context.mdresolution-engine.md

resolution-engine.mddocs/

0

# Resolution Engine

1

2

The core resolution engine handles all module resolution scenarios including relative paths, absolute paths, bare specifiers, and Haste modules. It orchestrates the entire resolution process through a series of specialized resolvers.

3

4

## Capabilities

5

6

### Main Resolve Function

7

8

The primary entry point for all module resolution operations.

9

10

```typescript { .api }

11

/**

12

* Resolve a module name to a file path or asset collection based on the resolution context

13

* @param context - Resolution context containing configuration and helper functions

14

* @param moduleName - Module name to resolve (relative, absolute, or bare specifier)

15

* @param platform - Target platform (e.g., 'ios', 'android', 'web') for platform-specific resolution

16

* @returns Resolution result containing file path or asset collection

17

*/

18

function resolve(

19

context: ResolutionContext,

20

moduleName: string,

21

platform: string | null

22

): Resolution;

23

```

24

25

**Usage Examples:**

26

27

```javascript

28

const Resolver = require("metro-resolver");

29

30

// Resolve relative import

31

const relativeResult = Resolver.resolve(context, './utils/helper', 'ios');

32

// { type: 'sourceFile', filePath: '/app/src/utils/helper.ios.js' }

33

34

// Resolve bare specifier

35

const packageResult = Resolver.resolve(context, 'lodash', null);

36

// { type: 'sourceFile', filePath: '/node_modules/lodash/index.js' }

37

38

// Resolve asset

39

const assetResult = Resolver.resolve(context, './icon.png', 'ios');

40

// { type: 'assetFiles', filePaths: ['./icon@2x.ios.png', './icon.ios.png'] }

41

42

// Handle empty resolution (excluded module)

43

const emptyResult = Resolver.resolve(context, 'excluded-module', null);

44

// { type: 'empty' }

45

```

46

47

### Resolution Result Types

48

49

Different types of resolution outcomes based on the target module.

50

51

```typescript { .api }

52

type Resolution = FileResolution | Readonly<{ type: 'empty' }>;

53

54

type FileResolution = AssetResolution | SourceFileResolution;

55

56

interface SourceFileResolution {

57

readonly type: 'sourceFile';

58

readonly filePath: string;

59

}

60

61

interface AssetResolution {

62

readonly type: 'assetFiles';

63

readonly filePaths: ReadonlyArray<string>;

64

}

65

```

66

67

### Resolution Process Flow

68

69

The resolver follows a systematic process:

70

71

1. **Custom Resolver Check**: If a custom resolver is provided, delegate to it first

72

2. **Path Type Detection**: Determine if the module name is relative, absolute, or bare specifier

73

3. **Relative/Absolute Resolution**: Resolve using file system lookups for direct paths

74

4. **Subpath Import Resolution**: Handle package.json imports field for `#` prefixed imports

75

5. **Module Redirection**: Apply any path redirections before further resolution

76

6. **Haste Resolution**: Check Haste module map if enabled

77

7. **Package Resolution**: Resolve bare specifiers through node_modules hierarchy

78

8. **Error Handling**: Throw appropriate errors for failed resolutions

79

80

### Platform-Specific Resolution

81

82

The resolver supports platform-specific file resolution for React Native development.

83

84

**Resolution Priority:**

85

1. Platform-specific file (e.g., `Component.ios.js`)

86

2. Native platform file (e.g., `Component.native.js`) if `preferNativePlatform` is true

87

3. Generic file (e.g., `Component.js`)

88

89

**Usage Example:**

90

91

```javascript

92

// With platform = 'ios', the resolver will try:

93

// 1. ./Component.ios.js

94

// 2. ./Component.native.js (if preferNativePlatform: true)

95

// 3. ./Component.js

96

const result = Resolver.resolve(context, './Component', 'ios');

97

```

98

99

### Extension Resolution

100

101

The resolver attempts multiple extensions based on configuration.

102

103

**Resolution Order:**

104

1. Exact filename match (no extension)

105

2. Source extensions in order (`.js`, `.ts`, `.tsx`, etc.)

106

3. Asset extensions for asset files (`.png`, `.jpg`, etc.)

107

108

### Hierarchical Lookup

109

110

For bare specifiers, the resolver searches through the node_modules hierarchy.

111

112

**Search Order:**

113

1. Current directory's node_modules

114

2. Parent directory's node_modules

115

3. Continue up the directory tree

116

4. Global node_modules paths from context

117

118

**Example Hierarchy:**

119

```

120

/project/src/components/Button.js

121

-> /project/src/components/node_modules/package

122

-> /project/src/node_modules/package

123

-> /project/node_modules/package

124

-> /node_modules/package

125

```

126

127

### Empty Module Resolution

128

129

The resolver can return empty resolutions for excluded modules.

130

131

```typescript { .api }

132

interface EmptyResolution {

133

readonly type: 'empty';

134

}

135

```

136

137

This is useful for:

138

- Conditional compilation

139

- Platform-specific exclusions

140

- Build-time module replacement

141

142

**Usage Example:**

143

144

```javascript

145

// If redirectModulePath returns false for a module

146

const context = {

147

// ... other config

148

redirectModulePath: (path) => {

149

if (path.includes('server-only')) return false;

150

return path;

151

}

152

};

153

154

const result = Resolver.resolve(context, 'server-only-module', null);

155

// { type: 'empty' }

156

```