Export the ReactNativeFeatureFlags subpath used by virtualized-lists - #57940
Open
giaBaoJS wants to merge 1 commit into
Open
Export the ReactNativeFeatureFlags subpath used by virtualized-lists#57940giaBaoJS wants to merge 1 commit into
giaBaoJS wants to merge 1 commit into
Conversation
react#57484 removed the "./src/*" exports mapping from the react-native package, on the basis that these import paths were never used externally. @react-native/virtualized-lists is a separately published package and a direct dependency of react-native, and it imports 'react-native/src/private/featureflags/ReactNativeFeatureFlags' at runtime from VirtualizedList.js and VirtualizeUtils.js. As a result, any app rendering FlatList makes Metro emit a package-exports violation warning and fall back to file-based resolution. Re-export that single subpath, keeping "types": null so it stays hidden from TypeScript as intended by react#57277. Also add a monorepo test that resolves every react-native subpath imported at runtime by a published package against the "exports" map, so a mapping cannot be dropped again without CI failing.
Member
|
Great spot! We'll need to solve this slightly differently however, I think by adding this API to import {ReactNativeFeatureFlags} from 'react-native/react-private-interface';Patch here: https://gist.github.com/huntie/0523e2dd114dacf904d28211ad6b67be. Can you apply/retitle this PR to match? :) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
Fixes #57933.
A fresh app that renders
FlatListmakes Metro emit a package-exports violation warning and fall back to file-based resolution.@react-native/virtualized-listsis a separately published package and a direct dependency ofreact-native. It imports the feature flags at runtime in two shipped files:packages/virtualized-lists/Lists/VirtualizedList.js:67— guardsdeferFlatListFocusChangeRenderUpdate()packages/virtualized-lists/Lists/VirtualizeUtils.js:16— guardsfixVirtualizeListCollapseWindowSize()#57484 removed the
"./src/*"mapping on the basis that "these import paths were never used externally", and its caveat covered onlyrn-testerand Fantom, which are repo-local.virtualized-listsis neither — it ships to npm, so the mapping is load-bearing. This is the same warning, from the same package, that #51699 previously fixed by re-exposingsrc/*.This PR re-exports only that one subpath, with
"types": nullso it stays invisible to TypeScript exactly as #57277 intended.src/private/*as a whole stays unexported.Alternative approach
The other option is to route feature-flag access through an already-exported entry point (a new curated secondary entry point next to
./asset-registry/./react-private-interface, or re-exporting the two flags through one of those) and change thevirtualized-listsimport.I chose the exports entry because:
ReactNativeFeatureFlagsmust stay a singleton — flags are overridden at startup — and not moving the import keeps that guaranteed.react-native/private/featureflags, which is more inviting to third parties than asrc/private/...path that is already hidden from TypeScript.If you would rather keep
src/fully unexported and take the entry-point route instead, say so and I will switch this PR over — the guard test below is valuable either way and needs no changes.Scope note:
@react-native/jest-preset@react-native/jest-presetalso deep-importsreact-native/src/private/...in four published files (jest/RefreshControlMock.js,jest/mockNativeComponent.js,jest/mocks/requireNativeComponent.js,jest/mocks/RefreshControl.js). All four areimport type, so Babel erases them and they never reach a bundler's resolver — they do not produce this warning. I left them alone to keep this change focused; the new test deliberately only checks runtime imports. Happy to follow up separately if you want those tidied.Preventing recurrence
There was no test guarding the
exportsmap, which is why this regressed silently — Metro only warns and falls back, so nothing failed in CI. The new test inscripts/monorepo-testsresolves everyreact-native/...subpath imported at runtime by a published package against theexportsmap, and fails if one is unreachable.Two things it has to work around, both documented in the test:
packages/jest-preset/jest/resolver.js) stripsexports, and Jest's patched Node module resolution ignoresexportstoo —createRequire(...).resolve()inside Jest resolves unexported paths happily. The test therefore resolves the map directly instead of relying onrequire.resolve.filesfield (__tests__,__mocks__,src/private/testing, …) are skipped, since their imports never ship.Changelog:
[GENERAL] [FIXED] - Fix package-exports warning from Metro when rendering
FlatList, caused by@react-native/virtualized-listsimporting an unexportedreact-nativesubpathTest Plan:
Reproduced the user-visible symptom using the reporter's reproducer against published
react-native@0.87.0— no simulator needed:Before (stock
react-native@0.87.0):After applying this
exportsentry to that app'snode_modules/react-native/package.json: 0 warnings, andcmpreports the two bundles are byte-identical — confirming the fix changes only the resolution path, not emitted code.Counterfactual for the new test — reverting the
package.jsonchange makes it fail with:Restoring it makes it pass again.
I also cross-checked the test's
exportsresolution against Node's real resolver (outside Jest, where it behaves correctly) over all 72react-native/...specifiers in the repo plus synthetic wildcard/conditional/missing-path probes: they agree on every one.Full suite, on
main+ this change: