在 Android 上使用 Expo 49 后
npx expo
出现以下错误。
Android Bundling failed 162ms
Unable to resolve "react-d3-speedometer"
from "screens/BmiResultSpeedometerScreen.web.tsx"
这是我的
screens/BmiResultSpeedometerScreen.web.tsx
import ReactSpeedometer, { Transition } from "react-d3-speedometer"
但是,
BmiResultSpeedometerScreen.web.tsx
永远不会在Android上显示,这是由以下代码保证的。
const screenToNavigate = Platform.OS === 'android' ? ScreenName.BMI_RESULT :
Platform.OS === 'web' ? ScreenName.BMI_RESULT_SPEEDOMETER :
ScreenName.BMI_RESULT; // the default value;
navigation.navigate(screenToNavigate, { bmi: Number.parseInt(bmiResult) });
如何从 Android 构建中删除它才能成功构建?
这是我的
package.json
{
"name": "bmi-calculator",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"web": "expo start --web",
"ts:check": "tsc"
},
"dependencies": {
"@expo/webpack-config": "^19.0.0",
"@react-native-community/slider": "4.4.2",
"@react-navigation/native-stack": "^6.9.17",
"expo": "^49.0.21",
"expo-updates": "~0.18.18",
"react": "18.2.0",
"react-d3-speedometer": "github:palerdot/react-d3-speedometer#master",
"react-dom": "^18.2.0",
"react-native-web": "^0.19.10"
},
"devDependencies": {
"@babel/core": "^7.23.6",
"@types/react": "~18.2.46",
"babel-plugin-react-native-web": "^0.19.10",
"typescript": "^5.3.3"
},
"private": true
}
这是我的
AppNavigator.tsx
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import BmiResultScreen from "../screens/BmiResultScreen";
import BmiCalculatorScreen from "../screens/BmiCalculatorScreen";
import { ScreenName } from "../types/ScreenName";
import BmiResultSpeedometerScreen from "../screens/BmiResultSpeedometerScreen.web";
const AppStack = createNativeStackNavigator();
const AppNavigator = ()=>{
return(
<AppStack.Navigator>
<AppStack.Screen
name={ScreenName.BMI_CALCULATOR}
component={BmiCalculatorScreen}
options={{
title: 'BMI CALCULATOR',
headerStyle:{
backgroundColor: "#0A0C21",
},
headerTitleStyle:{
color: 'white'
}
}}
/>
<AppStack.Screen
name={ScreenName.BMI_RESULT}
component={BmiResultScreen}
options={{
title: 'BMI CALCULATOR',
headerStyle:{
backgroundColor: "#0A0C21",
},
headerTitleStyle:{
color: 'white'
}
}}
/>
<AppStack.Screen
name={ScreenName.BMI_RESULT_SPEEDOMETER}
component={BmiResultSpeedometerScreen}
options={{
title: 'BMI CALCULATOR',
headerStyle:{
backgroundColor: "#0A0C21",
},
headerTitleStyle:{
color: 'white'
}
}}
/>
</AppStack.Navigator>
)
}
export default AppNavigator;
这是 ChatGPT 的答案,但我不确定在最佳实践方面应选择哪种解决方案。我真的很希望有经验的人来看看。
您遇到的问题是由于 Expo 的捆绑程序试图解决所有导入问题,而不管代码中特定于平台的条件如何。即使 Android 构建中未使用
BmiResultSpeedometerScreen.web.tsx
,但其导入语句仍在处理中,从而导致错误。
要解决此问题,您需要确保捆绑程序在构建 Android 时不会尝试处理
BmiResultSpeedometerScreen.web.tsx
文件。以下是您可以使用的一些策略:
修改您的
AppNavigator.tsx
以根据平台动态导入BmiResultSpeedometerScreen
。这样,有问题的模块就不会在 Android 构建中导入。
import { Platform } from 'react-native';
// Other imports...
let BmiResultSpeedometerScreen;
if (Platform.OS === 'web') {
BmiResultSpeedometerScreen = require('../screens/BmiResultSpeedometerScreen.web').default;
}
// ...
<AppStack.Screen
name={ScreenName.BMI_RESULT_SPEEDOMETER}
component={BmiResultSpeedometerScreen}
options={/* ... */}
/>
在此设置中,仅当平台为“web”时才会导入
BmiResultSpeedometerScreen
。对于 Android,此组件将为 undefined
,您应该在导航器中适当处理这种情况(例如,根本不渲染屏幕)。
另一种方法是根据平台有条件地在导航器中注册屏幕:
import { Platform } from 'react-native';
// ...
const AppNavigator = () => {
return (
<AppStack.Navigator>
{/* Other screens */}
{Platform.OS === 'web' && (
<AppStack.Screen
name={ScreenName.BMI_RESULT_SPEEDOMETER}
component={require('../screens/BmiResultSpeedometerScreen.web').default}
options={{/* ... */}}
/>
)}
</AppStack.Navigator>
);
}
在此方法中,仅当平台为“Web”时,
BmiResultSpeedometerScreen
屏幕才会添加到导航器中。对于 Android,屏幕不会被注册,因此有问题的模块不会被导入。
您可以将
BmiResultSpeedometerScreen.web.tsx
重命名为 BmiResultSpeedometerScreen.tsx
,并为 Android 创建一个名为 BmiResultSpeedometerScreen.android.tsx
的空组件或占位符组件。这样,React Native 的特定于平台的文件解析将自动为每个平台选择正确的文件。
BmiResultSpeedometerScreen
的情况。