or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cache-management.mdconfiguration.mdcore-transformation.mderror-handling.mdindex.md

cache-management.mddocs/

0

# Cache Management

1

2

Metro Transform Worker provides comprehensive cache key generation for efficient incremental builds and cache invalidation across the transformation pipeline.

3

4

## Capabilities

5

6

### Cache Key Generation

7

8

Generates deterministic cache keys based on transformer configuration, file dependencies, and transformation settings to enable efficient caching.

9

10

```javascript { .api }

11

/**

12

* Generate cache key for transformer configuration

13

* @param config - Transformer configuration object

14

* @returns String cache key that changes when configuration affects transformation output

15

*/

16

function getCacheKey(config: JsTransformerConfig): string;

17

```

18

19

**Usage Examples:**

20

21

```javascript

22

const { getCacheKey } = require("metro-transform-worker");

23

24

const config = {

25

babelTransformerPath: require.resolve("@react-native/metro-babel-transformer"),

26

minifierPath: require.resolve("metro-minify-terser"),

27

assetRegistryPath: "react-native/Libraries/Image/AssetRegistry",

28

assetPlugins: [],

29

enableBabelRCLookup: true,

30

enableBabelRuntime: false,

31

globalPrefix: "",

32

hermesParser: false,

33

minifierConfig: {

34

output: { ascii_only: true },

35

compress: { reduce_funcs: false },

36

},

37

optimizationSizeLimit: 150000,

38

publicPath: "/assets",

39

allowOptionalDependencies: "ignore",

40

unstable_disableModuleWrapping: false,

41

unstable_compactOutput: false,

42

unstable_allowRequireContext: false,

43

};

44

45

// Generate cache key for configuration

46

const cacheKey = getCacheKey(config);

47

console.log(cacheKey); // "abc123def456...ghi789$hjk012$lmn345"

48

49

// Cache keys change when configuration changes

50

const modifiedConfig = { ...config, dev: true };

51

const newCacheKey = getCacheKey(modifiedConfig);

52

console.log(cacheKey !== newCacheKey); // true

53

```

54

55

### Cache Key Components

56

57

The cache key is composed of several components that ensure invalidation when transformation behavior changes:

58

59

#### File Dependencies

60

- **Transform worker source**: Main transformation logic

61

- **Babel transformer**: Configured Babel transformer module

62

- **Minifier**: Configured minifier module

63

- **Utility modules**: Asset transformer, minifier loader, etc.

64

- **Metro internals**: Import name generation, file wrapping, etc.

65

- **Transform plugins**: All Metro transform plugin files

66

67

#### Configuration Hash

68

- **Transformer config**: All configuration options except paths

69

- **Stable hashing**: Deterministic serialization of configuration objects

70

- **Nested object handling**: Deep hashing of complex configuration structures

71

72

#### Babel Transformer Integration

73

- **Babel cache key**: Includes Babel transformer's own cache key if available

74

- **Plugin dependencies**: Babel plugin file dependencies

75

- **Preset dependencies**: Babel preset file dependencies

76

77

### Cache Key Structure

78

79

```javascript { .api }

80

// Cache key format: "files$config$babel"

81

interface CacheKeyComponents {

82

/** Hash of all file dependencies that affect transformation */

83

filesKey: string;

84

/** Hash of configuration object (excluding file paths) */

85

configHash: string;

86

/** Babel transformer's cache key (if available) */

87

babelKey: string;

88

}

89

```

90

91

The final cache key is constructed by joining these components with `$` separators:

92

93

```javascript

94

const cacheKey = [filesKey, configHash, babelKey].join("$");

95

```

96

97

### Dependency Tracking

98

99

The cache system tracks dependencies across multiple layers:

100

101

#### Transform Worker Dependencies

102

```javascript

103

const coreFiles = [

104

__filename, // metro-transform-worker/src/index.js

105

require.resolve(babelTransformerPath),

106

require.resolve(minifierPath),

107

require.resolve("./utils/getMinifier"),

108

require.resolve("./utils/assetTransformer"),

109

];

110

```

111

112

#### Metro Internal Dependencies

113

```javascript

114

const metroFiles = [

115

require.resolve("metro/private/ModuleGraph/worker/generateImportNames"),

116

require.resolve("metro/private/ModuleGraph/worker/JsFileWrapping"),

117

];

118

```

119

120

#### Transform Plugin Dependencies

121

```javascript

122

const pluginFiles = metroTransformPlugins.getTransformPluginCacheKeyFiles();

123

```

124

125

### Configuration Hashing

126

127

The configuration hash excludes file paths (which are already covered by file dependency tracking) and focuses on options that affect transformation behavior:

128

129

```javascript { .api }

130

interface HashedConfigSubset {

131

// Excludes: babelTransformerPath, minifierPath

132

assetPlugins: ReadonlyArray<string>;

133

assetRegistryPath: string;

134

asyncRequireModulePath: string;

135

dynamicDepsInPackages: DynamicRequiresBehavior;

136

enableBabelRCLookup: boolean;

137

enableBabelRuntime: boolean | string;

138

globalPrefix: string;

139

hermesParser: boolean;

140

minifierConfig: MinifierConfig;

141

optimizationSizeLimit: number;

142

publicPath: string;

143

allowOptionalDependencies: AllowOptionalDependencies;

144

unstable_dependencyMapReservedName?: string;

145

unstable_disableModuleWrapping: boolean;

146

unstable_disableNormalizePseudoGlobals: boolean;

147

unstable_compactOutput: boolean;

148

unstable_allowRequireContext: boolean;

149

unstable_memoizeInlineRequires?: boolean;

150

unstable_nonMemoizedInlineRequires?: ReadonlyArray<string>;

151

unstable_renameRequire?: boolean;

152

}

153

```

154

155

### Cache Invalidation Scenarios

156

157

The cache key changes automatically when any of these conditions occur:

158

159

#### File Changes

160

- Transform worker source code modifications

161

- Babel transformer implementation changes

162

- Minifier implementation changes

163

- Metro internal module updates

164

- Transform plugin updates

165

166

#### Configuration Changes

167

- Any transformer configuration option modification

168

- Babel transformer configuration changes

169

- Minifier configuration adjustments

170

- Asset processing settings updates

171

- Experimental feature flag changes

172

173

#### Environment Changes

174

- Node.js version changes (affects require.resolve paths)

175

- Package installation/updates (affects resolved module paths)

176

- Metro version updates

177

178

### Integration with Metro Caching

179

180

Metro Transform Worker's cache keys integrate with Metro's broader caching system:

181

182

```javascript

183

// Metro uses the cache key for:

184

// 1. Transformation result caching

185

// 2. Source map caching

186

// 3. Dependency graph caching

187

// 4. Asset processing caching

188

189

const metroConfig = {

190

transformer: {

191

getTransformCacheKeyFn: () => getCacheKey(transformerConfig),

192

// ... other transformer options

193

},

194

};

195

```

196

197

### Performance Considerations

198

199

#### Cache Key Generation Performance

200

- **File stat caching**: Module resolution results are cached by Node.js

201

- **Hash computation**: Uses fast hashing algorithm (metro-cache stableHash)

202

- **Incremental updates**: Only recomputes when dependencies change

203

204

#### Cache Hit Optimization

205

- **Deterministic ordering**: Configuration objects are serialized consistently

206

- **Path normalization**: Absolute paths are normalized for cross-platform consistency

207

- **Version pinning**: Dependency versions are included in file-based hashing

208

209

### Debugging Cache Issues

210

211

When experiencing unexpected cache behavior:

212

213

```javascript

214

// Enable Metro cache debugging

215

process.env.DEBUG = "Metro:Cache";

216

217

// Check cache key components

218

const cacheKey = getCacheKey(config);

219

const [filesKey, configHash, babelKey] = cacheKey.split("$");

220

221

console.log("Files key:", filesKey);

222

console.log("Config hash:", configHash);

223

console.log("Babel key:", babelKey);

224

225

// Verify configuration serialization

226

console.log("Config subset:", JSON.stringify(configSubset, null, 2));

227

```