Compare commits

...
1 Commits
Author SHA1 Message Date
Rob Hogan 6bd00c292f Invalidate transform cache on update of/local changes to @react-native/babel-preset (#53867)
Summary:

`react-native/metro-babel-transformer` implements `getCacheKey` for Metro, but does not vary the cache key on changes to `react-native/babel-preset`, one of its dependencies, leading to false positive cache hits (changes not being reflected).

This is particularly a problem in development, although it potentially also leads to issues in the unusual case that `react-native/babel-preset` is updated via npm, but no other package is.

This adds a `getCacheKey` to `react-native/babel-preset` and incorporates it into `react-native/metro-babel-transformer`'s `getCacheKey`. It's based on `package.json#version` in production and a hash of package contents in development (`version.endsWith('-main')`).

Changelog:
[General][Fixed] Invalidate transform cache when `react-native/babel-preset` is updated

Reviewed By: huntie

Differential Revision: D82893894
2025-09-26 03:56:07 -07:00
2 changed files with 32 additions and 1 deletions
+30
View File
@@ -10,11 +10,41 @@
'use strict';
const {version: packageVersion} = require('../package.json');
const main = require('./configs/main');
module.exports = function (babel, options) {
return main(options);
};
let cacheKey;
module.exports.getCacheKey = () => {
if (cacheKey != null) {
// Memoize
return cacheKey;
}
if (!packageVersion.endsWith('-main')) {
// Assume the integrity of package contents for published npm releases.
cacheKey = packageVersion;
return cacheKey;
}
// For anyone working with a `-main` version, contents may vary over time
// even though the version does not. Hash the relevant contents of this
// package. Lazy-load dependencies we only need on this slow path.
const {createHash} = require('crypto');
const {readFileSync} = require('fs');
const key = createHash('md5');
[
readFileSync(__filename),
readFileSync(require.resolve('./configs/main.js')),
readFileSync(require.resolve('./configs/hmr.js')),
readFileSync(require.resolve('./configs/lazy-imports.js')),
readFileSync(require.resolve('./passthrough-syntax-plugins.js')),
readFileSync(require.resolve('./plugin-warn-on-deep-imports.js')),
].forEach(part => key.update(part));
cacheKey = key.digest('hex');
return cacheKey;
};
module.exports.getPreset = main.getPreset;
module.exports.passthroughSyntaxPlugins = require('./passthrough-syntax-plugins');
+2 -1
View File
@@ -23,13 +23,14 @@ import type {
*/
const {parseSync, transformFromAstSync} = require('@babel/core');
const {getCacheKey: getPresetCacheKey} = require('@react-native/babel-preset');
const makeHMRConfig = require('@react-native/babel-preset/src/configs/hmr');
const crypto = require('crypto');
const fs = require('fs');
const nullthrows = require('nullthrows');
const path = require('path');
const cacheKeyParts = [fs.readFileSync(__filename)];
const cacheKeyParts = [getPresetCacheKey(), fs.readFileSync(__filename)];
// TS detection conditions copied from @react-native/babel-preset
function isTypeScriptSource(fileName /*: string */) {