You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Providing a cache key when custom transformers use external inputs #918
Do you want to request a feature or report a bug?
Feature/docs
What is the current behavior?
When using custom plugins (like babel-plugin-transform-inline-environment-variables) outside factors may influence the build, which breaks transform cache invalidation.
What is the expected behavior?
We probably can't do anything automatically for arbitrary plugins, but at the very least there should be a documented way to tell the transform cache about outside factors. We have cacheVersion, but it's not well documented ("There is generally no need to set this explicitly") and feels surprising.
A way to explicitly specify/allowlist environment variables in particular (like we do with Buck) might be worthwhile, since that's likely to be the most common outside factor.
Workaround
// metro.config.jsmodule.exports={cacheVersion: [process.env.VAR_ONE,process.env.VAR_TWO].join('-')// Hash this if the values aren't safe for a file name// ...}
Hey @robhogan, does metro currently include babel plugins in transform cache keys? It looks like it doesn't so even removing/adding a babel plugin has no effect on the cache. Would it be possible to include those?
I need to have a closer look to see whether that's the right wiring or whether we can lift it up to the main thread, but I'd expect to merge that in some form before the next release.
Thanks for the response! I see, that will handle the main cases including dynamically computed plugin config values, pretty nice!
I was also interested if it's possible to only include plugins that affected the file in its cache key? E.g. injecting a variable usually affects a single export file, but if it's done via a babel plugin the entire cache will get reset if the value changes
From what I've seen this doesn't exactly look feasible to do, in which case if we still want some caching with such plugin we better have something else do that plugin's job?
Yeah, that's complicated to do efficiently - Metro effectively treats the transformer as a black box that's meant to be a pure function of explicit inputs + whatever the transformer wants to include in its getCacheKey (which is not a function of the file), we have no mechanism to express "this file is invariant under this input".
The basic problem here is simple to state - how do you know what plugins will affect a particular file, before you've even parsed it?
Maybe you can't do that, but once you've transformed once you can potentially collect inputs that were never read, and store the cache in such a way that you can hit that result the next time (even under different inputs) and work out whether you can reuse it.
That's both a big change to the way the cache works though, and has really gnarly edge cases - what if the only reason an input isn't used is because another plugin eliminated some code that would've used it, conditional on a different input? Similarly, what if one plugin conditionally injects code that uses another input?
We'd need a different API for consuming transform inputs that we could track, similar to babel.caller() but possibly stricter - like react hooks, something you couldn't consume conditionally. It's an interesting project, to be sure, but it is a project.
Also I'm not sure if #1638 covers the case of babel plugin version change? In my experience nowadays a common case for --reset-cache is when we bump reanimated's worklets plugin and it explicitly checks the versions that fails with cache in runtime, would be great to ensure that's covered as it also applies to any other plugin that gets bumped
Activity
bigcupcoffee commentedon Feb 24, 2026
Hey @robhogan, does metro currently include babel plugins in transform cache keys? It looks like it doesn't so even removing/adding a babel plugin has no effect on the cache. Would it be possible to include those?
robhogan commentedon Feb 24, 2026
@bigcupcoffee - not currently, but #1638 looks to address that.
I need to have a closer look to see whether that's the right wiring or whether we can lift it up to the main thread, but I'd expect to merge that in some form before the next release.
bigcupcoffee commentedon Feb 24, 2026
Thanks for the response! I see, that will handle the main cases including dynamically computed plugin config values, pretty nice!
I was also interested if it's possible to only include plugins that affected the file in its cache key? E.g. injecting a variable usually affects a single export file, but if it's done via a babel plugin the entire cache will get reset if the value changes
From what I've seen this doesn't exactly look feasible to do, in which case if we still want some caching with such plugin we better have something else do that plugin's job?
robhogan commentedon Feb 24, 2026
Yeah, that's complicated to do efficiently - Metro effectively treats the transformer as a black box that's meant to be a pure function of explicit inputs + whatever the transformer wants to include in its
getCacheKey(which is not a function of the file), we have no mechanism to express "this file is invariant under this input".The basic problem here is simple to state - how do you know what plugins will affect a particular file, before you've even parsed it?
Maybe you can't do that, but once you've transformed once you can potentially collect inputs that were never read, and store the cache in such a way that you can hit that result the next time (even under different inputs) and work out whether you can reuse it.
That's both a big change to the way the cache works though, and has really gnarly edge cases - what if the only reason an input isn't used is because another plugin eliminated some code that would've used it, conditional on a different input? Similarly, what if one plugin conditionally injects code that uses another input?
We'd need a different API for consuming transform inputs that we could track, similar to babel.caller() but possibly stricter - like react hooks, something you couldn't consume conditionally. It's an interesting project, to be sure, but it is a project.
bigcupcoffee commentedon Feb 25, 2026
Also I'm not sure if #1638 covers the case of babel plugin version change? In my experience nowadays a common case for
--reset-cacheis when we bump reanimated's worklets plugin and it explicitly checks the versions that fails with cache in runtime, would be great to ensure that's covered as it also applies to any other plugin that gets bumped