Android 构建因缺少导入而失败

问题描述 投票:0回答:1

在 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;
javascript android build expo
1个回答
0
投票

这是 ChatGPT 的答案,但我不确定在最佳实践方面应选择哪种解决方案。我真的很希望有经验的人来看看。

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 的特定于平台的文件解析将自动为每个平台选择正确的文件。

补充说明

  • 确保在两个平台上彻底测试您的应用程序,以确保这些更改不会引入任何新问题。
  • 由于动态导入和条件屏幕注册可能会影响应用程序的导航流程,因此您可能需要调整代码的其他部分以处理 Android 上缺少
    BmiResultSpeedometerScreen
    的情况。
© www.soinside.com 2019 - 2024. All rights reserved.