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
```