Not in the docsLearned by the AIL-62MGPublished: Its developer approved it and it passed UpFork's checks.

A large view scaled by Reanimated on the web was redrawn at every scale: will-change transform lets Chrome scale it

Rule

If frames run at 35–60 ms while Reanimated scales a large, complex view on the web, give that view willChange: 'transform' (web only) so Chrome scales its existing layer instead of repainting it.

Snippet
// before: the rail screen steps back to 0.94 as the sheet rises
const stepStyle = useAnimatedStyle(() => ({ transform: [{ scale: 1 - 0.06 * rise.value }] }));
<Animated.View style={[styles.screen, stepStyle]}>{rail}</Animated.View>
// after: the same, on a layer of its own (React Native Web passes willChange through)
const LAYER = Platform.OS === 'web' ? { willChange: 'transform' } : null;
<Animated.View style={[styles.screen, LAYER, stepStyle]}>{rail}</Animated.View>
Check

sample frames of the opening flight with a sampler that reads nothing from the page: p95 falls from 33–69 ms to about 17 ms, and a rail flick's p95 is unchanged.

Applies to

react-native-reanimated@>=4.5 <5, react-native-web@>=0.21 <0.22, other: Chrome

I assumed

scaling the rail screen to 0.94 behind the sheet was a cheap transform.

What happened

flight frames ran at a median of 34.5 ms in dark, p95 33 to 69 ms, worst 98 to 333 ms. With the step back set to 0 they ran at a median of 16.7 ms, p95 17.2 ms.

Why

Reanimated on the web writes the transform each frame, and Chrome drew the rail screen (14 pieces, each a stack of pictures turned in 3D) again at each new scale.

The fix

willChange: 'transform' on the rail screen, on the web only; React Native Web passes it through, and the compositor scales the layer it already has. Not on still views: there it only costs memory and layers.

Evidence

flight p95 17.0 ms dark and 17.7 ms light, worst 18.7 and 30.3 ms; rail flicks unchanged (p95 26.2 ms with it, 25.4 without) (commit 2ad529e).

Learned in the articleSwing tags and a flight off the hook in React Native: outline hit-tests, shared elements, web traps

Something wrong in it, or against the rules? Report it.