From 6123d52c5ae7b3ef0829adebc7e142e6963f12a1 Mon Sep 17 00:00:00 2001 From: Vincent Riemer <1398555+vincentriemer@users.noreply.github.com> Date: Fri, 5 Sep 2025 17:19:57 -0700 Subject: [PATCH 1/2] Add native polyfill for willChange Use `renderToHardwareTextureAndroid` on React Native Android as an equivalent to CSS `will-change`, as both serve the purpose of promoting the element to a GPU layer. --- apps/website/docs/api/02-css/index.md | 1 + packages/react-strict-dom/src/native/css/index.js | 6 ++++++ .../react-strict-dom/src/native/css/isAllowedStyleKey.js | 1 + packages/react-strict-dom/src/types/renderer.native.js | 1 + .../tests/__snapshots__/css-test.native.js.snap-native | 7 +++++++ packages/react-strict-dom/tests/css-test.native.js | 9 +++++++++ 6 files changed, 25 insertions(+) diff --git a/apps/website/docs/api/02-css/index.md b/apps/website/docs/api/02-css/index.md index ed30d4c8..f127315c 100644 --- a/apps/website/docs/api/02-css/index.md +++ b/apps/website/docs/api/02-css/index.md @@ -277,5 +277,6 @@ The following tables represent the compatibility status of the strict CSS API fo | visibility | 🟡 | 🟡 | | | whiteSpace | ❌ | ❌ | | | width | ✅ | ✅ | | +| willChange | 🟡 | 🟡 | | | wordBreak | ❌ | ❌ | | | zIndex | ✅ | ✅ | [#100](https://github.com/facebook/react-strict-dom/issues/100) | diff --git a/packages/react-strict-dom/src/native/css/index.js b/packages/react-strict-dom/src/native/css/index.js index 931cb56e..24c02dd3 100644 --- a/packages/react-strict-dom/src/native/css/index.js +++ b/packages/react-strict-dom/src/native/css/index.js @@ -469,6 +469,12 @@ export function props( nextStyle.alignContent ??= styleValue; nextStyle.justifyContent ??= styleValue; } + // willChange polyfill + else if (styleProp === 'willChange') { + if (typeof styleValue === 'string' && styleValue !== 'auto') { + nativeProps.renderToHardwareTextureAndroid = true; + } + } // Everything else else { nextStyle[styleProp] = styleValue; diff --git a/packages/react-strict-dom/src/native/css/isAllowedStyleKey.js b/packages/react-strict-dom/src/native/css/isAllowedStyleKey.js index 7f6e0b1c..bfbb0d2b 100644 --- a/packages/react-strict-dom/src/native/css/isAllowedStyleKey.js +++ b/packages/react-strict-dom/src/native/css/isAllowedStyleKey.js @@ -156,6 +156,7 @@ const allowedStyleKeySet = new Set([ 'verticalAlign', // Android Only 'visibility', 'width', + 'willChange', // Android Only 'zIndex', // Object-value keys 'default', diff --git a/packages/react-strict-dom/src/types/renderer.native.js b/packages/react-strict-dom/src/types/renderer.native.js index 7b757537..fbfd86d4 100644 --- a/packages/react-strict-dom/src/types/renderer.native.js +++ b/packages/react-strict-dom/src/types/renderer.native.js @@ -109,6 +109,7 @@ type ReactNativeProps = { pointerEvents?: ViewProps['pointerEvents'], ref?: $FlowFixMe, referrerPolicy?: ImageProps['referrerPolicy'], + renderToHardwareTextureAndroid?: ViewProps['renderToHardwareTextureAndroid'], role?: ?string, secureTextEntry?: TextInputProps['secureTextEntry'], spellCheck?: TextInputProps['spellCheck'], diff --git a/packages/react-strict-dom/tests/__snapshots__/css-test.native.js.snap-native b/packages/react-strict-dom/tests/__snapshots__/css-test.native.js.snap-native index 1e18e109..dd2d4ddf 100644 --- a/packages/react-strict-dom/tests/__snapshots__/css-test.native.js.snap-native +++ b/packages/react-strict-dom/tests/__snapshots__/css-test.native.js.snap-native @@ -773,6 +773,13 @@ exports[`properties: general visibility: visible 1`] = ` } `; +exports[`properties: general willChange 1`] = ` +{ + "renderToHardwareTextureAndroid": true, + "style": {}, +} +`; + exports[`properties: logical direction blockSize: blockSize 1`] = ` { "style": { diff --git a/packages/react-strict-dom/tests/css-test.native.js b/packages/react-strict-dom/tests/css-test.native.js index 4519250b..8df2defe 100644 --- a/packages/react-strict-dom/tests/css-test.native.js +++ b/packages/react-strict-dom/tests/css-test.native.js @@ -775,6 +775,15 @@ describe('properties: general', () => { 'visible' ); }); + + test('willChange', () => { + const styles = css.create({ + root: { + willChange: 'transform' + } + }); + expect(css.props.call(mockOptions, styles.root)).toMatchSnapshot(); + }); }); /** From 898e5fadef0db3c724cfeb9175e60f75b2752e85 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Mon, 8 Sep 2025 09:08:29 -0700 Subject: [PATCH 2/2] Configure rollup to treeshake unused modules Otherwise rollup inserts `import 'react'` in case the module has side-effects. --- .flowconfig | 1 + packages/react-strict-dom/tools/rollup.config.mjs | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.flowconfig b/.flowconfig index 91b247b1..0d79afbf 100644 --- a/.flowconfig +++ b/.flowconfig @@ -16,6 +16,7 @@ component_syntax=true module.name_mapper='^react-strict-dom$' -> '/packages/react-strict-dom/dist/native/index.js.flow' module.system.node.resolve_dirname=flow_modules module.system.node.resolve_dirname=node_modules +react.runtime=automatic suppress_type=$FlowIssue suppress_type=$FlowFixMe diff --git a/packages/react-strict-dom/tools/rollup.config.mjs b/packages/react-strict-dom/tools/rollup.config.mjs index fa05de21..00a5c937 100644 --- a/packages/react-strict-dom/tools/rollup.config.mjs +++ b/packages/react-strict-dom/tools/rollup.config.mjs @@ -55,7 +55,10 @@ const webConfigs = [ file: path.join(__dirname, '../dist/dom/index.js'), format: 'es' }, - plugins: [...sharedPlugins] + plugins: [...sharedPlugins], + treeshake: { + moduleSideEffects: false, + }, }, // Runtime { @@ -65,7 +68,10 @@ const webConfigs = [ file: path.join(__dirname, '../dist/dom/runtime.js'), format: 'es' }, - plugins: [...sharedPlugins] + plugins: [...sharedPlugins], + treeshake: { + moduleSideEffects: false, + }, } ];