集成nativewind与expo-router的App无法加载,求排查方案
Expo Router + NativeWind 集成后App卡在启动页无报错问题
我正在搭建集成Expo Router与NativeWind的App,完成安装配置后,App卡在启动页无法加载,且无任何报错信息。安装NativeWind之前,App运行完全正常。
项目结构包含:app目录(下有(tabs)子目录)、根目录下的package.json、metro.config.js、babel.config.js、tailwind.config.js、global.css等文件。
以下是我的配置文件:
package.json
{"name": "w-stickers","version": "1.0.0","main": "expo-router/entry","scripts": {"start": "expo start","android": "expo start --android","ios": "expo start --ios","web": "expo start --web"},"dependencies": {"@types/react": "~18.2.79","expo": "~51.0.28","expo-constants": "~16.0.2","expo-dev-client": "~4.0.26","expo-linking": "~6.3.1","expo-router": "~3.5.23","expo-splash-screen": "~0.27.5","expo-status-bar": "~1.12.1","nativewind": "^4.0.1","react": "18.2.0","react-native": "0.74.5","react-native-reanimated": "~3.10.1","react-native-safe-area-context": "4.10.5","react-native-screens": "3.31.1","tailwindcss": "^3.4.11"},"devDependencies": {"@babel/core": "^7.20.0","typescript": "^5.3.3"},"private": true}
主布局(app/_layout.tsx)
import "../global.css"; import { useCallback, useEffect, useState } from "react"; import { View } from "react-native"; import { Stack } from "expo-router"; import * as SplashScreen from "expo-splash-screen"; SplashScreen.preventAutoHideAsync(); console.log("Layout"); const RootLayout = () => { const [appIsReady, setAppIsReady] = useState(false); useEffect(() => { const prepare = async () => { try { await new Promise((resolve) => setTimeout(resolve, 2000)); console.log("Use Effect"); } catch (e) { console.warn(e); } finally { setAppIsReady(true); } }; prepare(); }, []); const onLayoutRootView = useCallback(async () => { if (appIsReady) { await SplashScreen.hideAsync(); } }, [appIsReady]); if (!appIsReady) { return null; } return ( <View className="flex-1" onLayout={onLayoutRootView}> <Stack> <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> </Stack> </View> ); }; export default RootLayout;
global.css
@tailwind base; @tailwind components; @tailwind utilities;
metro.config.js
const { getDefaultConfig } = require("expo/metro-config"); const { withNativeWind } = require("nativewind/metro"); const config = getDefaultConfig(__dirname); module.exports = withNativeWind(config, { input: "./global.css" });
babel.config.js
module.exports = function (api) { api.cache(true); return { presets: [["babel-preset-expo", { jsxImportSource: "nativewind" }], "nativewind/babel"], }; };
tailwind.config.js
/** @type {import('tailwindcss').Config} */ module.exports = { // NOTE: Update this to include the paths to all of your component files. content: ["./app/**/*.{js,jsx,ts,tsx}"], presets: [require("nativewind/preset")], theme: { extend: {}, }, plugins: [], };
我尝试过手动隐藏启动页、卸载重装依赖、重新创建项目,也尝试过AI工具排查,但均无效果。在主组件外添加console.log能正常输出,但组件内的console.log无输出,已耗费数小时仍未找到问题所在。
排查修复方案
- 调整Babel预设顺序
NativeWind v4明确要求nativewind/babel预设放在babel-preset-expo之前,否则会导致JSX编译异常。修改babel.config.js:
module.exports = function (api) { api.cache(true); return { presets: ["nativewind/babel", ["babel-preset-expo", { jsxImportSource: "nativewind" }]], }; };
修正Global CSS导入路径
主布局文件位于app/_layout.tsx时,global.css在根目录,导入路径应为./global.css而非../global.css,错误的路径会导致样式加载失败阻塞组件渲染。简化启动页逻辑排查
暂时移除复杂的启动页等待逻辑,直接隐藏启动页,验证页面是否能正常加载:
import "./global.css"; import { View } from "react-native"; import { Stack } from "expo-router"; import * as SplashScreen from "expo-splash-screen"; // 直接隐藏启动页 SplashScreen.hideAsync(); console.log("Layout"); const RootLayout = () => { return ( <View className="flex-1"> <Stack> <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> </Stack> </View> ); }; export default RootLayout;
- 清除缓存重启服务
执行命令清除Expo和Metro缓存,避免旧缓存干扰:
npx expo start --clear
- 完善Tailwind Content扫描路径
如果项目中有components等其他目录,需在tailwind.config.js中添加对应路径,确保NativeWind能扫描到所有需要样式的组件:
content: ["./app/**/*.{js,jsx,ts,tsx}", "./components/**/*.{js,jsx,ts,tsx}"],
内容的提问来源于stack exchange,提问作者Alexis Scuderi
相关产品推荐
相关产品推荐

