babel import-plugin still rewrites react-native-web internals, causing a circular-import crash on web (incomplete fix of #196 / #202)
維護者通常 3 天內回覆
還沒有人認領這個 Issue。
評估
- 難度
- 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 小時
- 30 天內合併 PR
- 1
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 沒有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
nativewind/react-native-css 的其他 Issue
-
難度 1/5 1 小時以內 新手友好度 87/100
nativewind/react-native-css#506 ·
維護者通常 3 天內回覆
-
難度 5/5 一週以上 新手友好度 25/100
nativewind/react-native-css#510 ·
維護者通常 3 天內回覆
-
難度 3/5 1-2 天 新手友好度 56/100
nativewind/react-native-css#509 ·
維護者通常 3 天內回覆
-
難度 5/5 一週以上 新手友好度 25/100
nativewind/react-native-css#507 ·
維護者通常 3 天內回覆
-
難度 3/5 1-2 天 新手友好度 62/100
nativewind/react-native-css#481 · 1 個 reaction ·
維護者通常 3 天內回覆
查看 nativewind/react-native-css 的全部 Issue
相似的 Issue
-
Parallel reticle_verify opens per-flow leases without the source lease's ignoreHTTPSErrors可能已有人在做 @as992949791 今天認領。 未關閉good first issue help wanted
難度 2/5 1-3 小時 新手友好度 85/100
reticlehq/reticle#2033 · 1 則留言 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 78/100
維護者通常 1 天內回覆
-
area:quality p3-medium ready-for-agent type:docs
難度 2/5 1-3 小時 新手友好度 83/100
fderuiter/deruiter.dev#3589 · 1 則留言 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 75/100
manfredsteyer/angular-oauth2-oidc#1514 ·
-
難度 2/5 1-3 小時 新手友好度 76/100
marmelab/react-admin#11431 ·
維護者通常 1 天內回覆