babel import-plugin still rewrites react-native-web internals, causing a circular-import crash on web (incomplete fix of #196 / #202)
メンテナーはふだん 3 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 48/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- react-native, typescript
- 領域
- build-system, frontend
調査の方向性
Start in src/babel/import-plugin.ts, at isFromThisModule and parseReactNativeWebSource, to see how relative imports inside react-native-web/dist get rewritten. Then compare webResolver in src/metro/resolver.ts with nativeResolver, which already skips rewriting when the origin is react-native/index.js. Done means a web bundle with Animated loads without the circular-import TypeError; the reporter has no public repro, so you will need to build one from the steps in the issue first.
索引モデルが issue の本文から書いたものです。
説明
Before submitting a new issue
- I tested using the latest version of the library, as the bug might be already fixed.
- I tested using a supported version of react native.
- I checked for possible duplicate issues, with possible answers.
Bug summary
This is a follow-up to #196 — the fix in #202 is incomplete, so the react-native-web circular-import crash still reproduces on web with [email protected].
On web, the app crashes at bundle load time:
Web ERROR [TypeError: Cannot read properties of undefined (reading 'default')]
Code: index.js
35 | export { default as Button } from './exports/Button';
36 | export { default as CheckBox } from './exports/CheckBox';
> 37 | export { default as FlatList } from './exports/FlatList';
Call Stack
<global> (react-native-web/dist/index.js:37)
<global> (react-native-css/dist/commonjs/components/FlatList.js:17)
<global> (react-native-web/dist/vendor/react-native/Animated/components/AnimatedFlatList.js:12)
<global> (react-native-web/dist/vendor/react-native/Animated/Animated.js:13)
(In a production bundle this surfaces as can't access property "default", _exportsFlatList2 is undefined.)
Root cause
There are two layers that rewrite react-native(-web) imports to react-native-css/components/*: the metro webResolver (src/metro/resolver.ts) and the babel import-plugin (src/babel/import-plugin.ts). #202 only touched the resolver, and only by excluding resolution targets inside react-native-web/dist/vendor (plus VirtualizedList). Neither layer excludes origins inside react-native-web, and the babel plugin was not changed at all.
The babel plugin's parseReactNativeWebSource resolves relative import specifiers against the current filename and rewrites anything that lands inside react-native-web/dist. So react-native-web's own internal imports get rewritten, which creates the cycle:
- Something touches
Animated→react-native-web/dist/vendor/react-native/Animated/Animated.jsloadsAnimatedFlatList.js. AnimatedFlatList.jsimports../../../../exports/FlatList→ resolves intoreact-native-web/dist→ babel rewrites it toreact-native-css/components/FlatList. (The resolver's vendor exclusion doesn't help: it checks the target path, and the target here isexports/FlatList, not a vendor file. The babel plugin rewrites the specifier before the resolver would matter anyway.)react-native-css/components/FlatListimportsreact-native→react-native-web/dist/index.js.- The index's own
export { default as FlatList } from './exports/FlatList'was also babel-rewritten toreact-native-css/components/FlatList— which is the module currently mid-initialization in step 3 → its partial exports have nodefault→ crash.
Note the native side already has exactly the guard that's missing here: nativeResolver skips rewriting when the origin is react-native/index.js.
Suggested fix (verified locally via pnpm patch against the published dist):
src/babel/import-plugin.ts— extend the existingisFromThisModuleskip so files insidereact-native-webare never rewritten:
function isFromThisModule(filename: string) {
return (
filename.startsWith(thisModuleDist) ||
filename.startsWith(thisModuleSrc) ||
// react-native-web internals must keep their raw imports, otherwise
// rnw/index -> css component -> "react-native" -> rnw/index cycles
filename.includes(`${sep}react-native-web${sep}`)
);
}
src/metro/resolver.ts— add the equivalent origin guard towebResolver(mirrorsnativeResolver'sisReactNativeIndexguard):
export function webResolver(resolver, context, moduleName, platform) {
const resolution = resolver(context, moduleName, platform);
if (
isFromThisModule(context.originModulePath) ||
// Don't rewrite react-native-web's own internal imports
context.originModulePath.includes(`${sep}react-native-web${sep}`) ||
resolution.type !== "sourceFile" ||
...
With both guards in place: userland imports of react-native / react-native-web still resolve to the wrapped components (via the resolver / babel rewrite of their imports), the wrappers still receive the raw react-native-web implementations, the cycle is gone, and the app renders on web. Android/native is unaffected. Happy to open a PR if that helps.
Library version
3.0.7
Environment info
expo: ~57.0.7 (SDK 57 default template + expo-router)
react-native: 0.86.0
react: 19.2.3
react-native-web: ~0.21.0 (0.21.2 installed)
nativewind: 5.0.0-preview.4
react-native-css: 3.0.7
node: 24.15.0, pnpm: 11.10.0, OS: Linux
React Compiler enabled, bundling via `expo start` (dev) and `expo export` (prod) — both crash identically
Steps to reproduce
- Create an Expo SDK 57 app (
create-expo-app, default template — it already usesAnimatedvia its demo screens; any code path that touches react-native-web'sAnimatedexport triggers the bug). - Install NativeWind v5 preview (
[email protected]+[email protected]) with the standardwithNativewindmetro config andnativewind/babelpreset. expo start, open the web target.- The bundle crashes at load with the error above before anything renders.
Reproducible example repository
The full root-cause analysis and a verified fix are included above; my project is private, but I can extract a minimal public repro from the steps above if needed.
- 主要言語
- TypeScript
- スター
- 166
- フォーク
- 45
- 平均マージ
- 13日 14時間
- マージ済み PR(30日)
- 1
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
nativewind/react-native-css のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
nativewind/react-native-css#545 ·
メンテナーはふだん 3 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
nativewind/react-native-css#544 ·
メンテナーはふだん 3 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
nativewind/react-native-css#543 ·
メンテナーはふだん 3 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
nativewind/react-native-css#540 ·
メンテナーはふだん 3 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
nativewind/react-native-css#538 ·
メンテナーはふだん 3 日以内に返信
nativewind/react-native-css の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
CopilotKit/openmuse#215 ·
メンテナーはふだん 3 日以内に返信
-
b:minor bug
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
software-mansion/argent#1698 ·
メンテナーはふだん 1 日以内に返信
-
e2e-failure ready-to-code
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
redhat-developer/rhdh-plugin-export-overlays#4624 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信