EAS build fails(managed, ios, android) - Unable to resolve module ./App

Hey, I’ve updated expo from 38 to 41 and wanted to use EAS build(need IPA and APK). I’ve followed steps in the docs to migrate from expo build to eas build, but received the next error on the both platforms:

What I’ve tried:

  1. Reinstall npm modules
  2. Clear watchman, metro bundler, npm cashes
  3. Build with and without metro running in the another terminal tab

Locally metro bundler builds project perfectly.

  1. Also I’ve tried changing main in package.json from node_modules/expo/AppEntry.js to src/main.jsx, but received another error:

Here are my configs:
app.config.js

import 'dotenv/config';

export default {
  name: 'XXX',
  slug: 'XXX',
  privacy: 'public',
  entryPoint: './src/main.jsx',
  sdkVersion: '41.0.0',
  platforms: [
    'ios',
    'android',
    'web'
  ],
  version: '1.0.0',
  orientation: 'portrait',
  icon: './src/assets/img/icon.png',
  scheme: 'myapp',
  splash: {
    image: './src/assets/img/splash-logo.png',
    resizeMode: 'contain',
    backgroundColor: '#161C23'
  },
  updates: {
    fallbackToCacheTimeout: 0
  },
  assetBundlePatterns: [
    '**/*'
  ],
  ios: {
    ...
  },
  android: {
   ...
  },
  web: {
    ...
  },
  locales: {
    en: './src/translations/languages/en.json',
    ru: './src/translations/languages/ru.json',
    uk: './src/translations/languages/uk.json',
  },
  packagerOpts: {
    config: 'metro.config.js',
    sourceExts: [
      'expo.ts',
      'expo.tsx',
      'expo.js',
      'expo.jsx',
      'ts',
      'tsx',
      'js',
      'jsx',
      'json',
      'wasm',
      'svg'
    ]
  },
  notification: {
    icon: './src/assets/img/logo_grayscale.png',
    iosDisplayInForeground: true
  },
  extra: {
    NODE_ENV: process.env.NODE_ENV,
    DOMAIN: process.env.DOMAIN,
    ...
  }
};

metro.config.js

const { getDefaultConfig } = require('expo/metro-config');

const defaultConfig = getDefaultConfig(__dirname);

defaultConfig.resolver.sourceExts.push('svg');
defaultConfig.resolver.assetExts = defaultConfig.resolver.assetExts.filter(ext => ext !== 'svg');
defaultConfig.transformer.babelTransformerPath = require.resolve('react-native-svg-transformer');
defaultConfig.transformer.getTransformOptions = async () => ({
  transform: {
    experimentalImportSupport: false,
    inlineRequires: false,
  },
});

module.exports = defaultConfig;

eas.json

{
  "builds": {
    "android": {
      "base": {
        "workflow": "managed",
        "env": {
         ...
        }
      },
      "production": {
        "extends": "base",
        "releaseChannel": "production",
        "env": {
          "NODE_ENV": "production",
           ...
        }
      },
      "staging": {
        "extends": "base",
        "distribution": "internal",
        "buildType": "apk",
        "releaseChannel": "staging",
        "env": {
          "NODE_ENV": "staging",
          ...
        }
      },
      "development": {
        "extends": "base",
        "distribution": "internal",
        "buildType": "apk",
        "releaseChannel": "development",
        "env": {
          "NODE_ENV": "development",
          ...
        }
      }
    },
    "ios": {
      "base": {
        "workflow": "managed",
        "env": {
          ...
        }
      },
      "production": {
        "extends": "base",
        "releaseChannel": "production",
        "env": {
          "NODE_ENV": "production",
          ...
        }
      },
      "staging": {
        "extends": "base",
        "releaseChannel": "staging",
        "env": {
          "NODE_ENV": "staging",
          ...
        }
      },
      "development": {
        "extends": "base",
        "releaseChannel": "development",
        "env": {
          "NODE_ENV": "development",
          ...
        }
      }
    }
  }
}

package.json

{
  "name": "XXX",
  "version": "21.5.21",
  "description": "XXX",
  "brand": "XXX",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject",
    "eslint": "npx eslint src",
    "test": "jest --watchAll"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "dependencies": {
    "@expo/vector-icons": "^12.0.0",
    "@googlemaps/polyline-codec": "^1.0.1",
    "@react-native-async-storage/async-storage": "^1.13.0",
    "@react-native-community/hooks": "^2.6.0",
    "@react-native-community/masked-view": "0.1.10",
    "@react-native-community/netinfo": "6.0.0",
    "@react-navigation/bottom-tabs": "~5.10.7",
    "@react-navigation/core": "~5.12.5",
    "@react-navigation/drawer": "~5.10.7",
    "@react-navigation/material-top-tabs": "~5.2.19",
    "@react-navigation/native": "~5.7.6",
    "@react-navigation/routers": "~5.4.12",
    "@react-navigation/stack": "~5.10.0",
    "@react-navigation/web": "~1.0.0-alpha.9",
    "axios": "^0.19.2",
    "dotenv": "^8.2.0",
    "expo": "^41.0.0",
    "expo-asset": "~8.3.1",
    "expo-camera": "~11.0.2",
    "expo-constants": "~10.1.3",
    "expo-contacts": "~9.1.2",
    "expo-firebase-analytics": "~4.0.2",
    "expo-font": "~9.1.0",
    "expo-image-picker": "~10.1.4",
    "expo-intent-launcher": "~9.0.0",
    "expo-linking": "~2.2.3",
    "expo-local-authentication": "~11.0.2",
    "expo-localization": "~10.1.0",
    "expo-location": "~12.0.4",
    "expo-notifications": "~0.11.6",
    "expo-permissions": "~12.0.1",
    "expo-splash-screen": "~0.10.2",
    "expo-web-browser": "~9.1.0",
    "geolib": "^3.3.1",
    "lodash.isempty": "^4.4.0",
    "moment": "^2.27.0",
    "node-html-parser": "^3.1.0",
    "prop-types": "^15.7.2",
    "qs": "^6.9.4",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-native": "0.63.4",
    "react-native-dash": "0.0.11",
    "react-native-gesture-handler": "~1.10.2",
    "react-native-keyboard-aware-scrollview": "^2.1.0",
    "react-native-maps": "0.27.1",
    "react-native-reanimated": "^1.13.3",
    "react-native-redash": "^15.5.2",
    "react-native-safe-area-context": "3.2.0",
    "react-native-screens": "~3.0.0",
    "react-native-tab-view": "^2.15.1",
    "react-native-web": "~0.13.12",
    "react-native-webview": "11.2.3",
    "react-redux": "^7.2.1",
    "react-redux-i18n": "^1.9.3",
    "reconnecting-websocket": "^4.4.0",
    "redux": "^4.0.5",
    "redux-form": "^8.3.6",
    "redux-form-submit-saga": "^1.2.1",
    "redux-saga": "^1.1.3",
    "styled-components": "^5.1.1",
    "uuid": "^3.4.0"
  },
  "devDependencies": {
    "@babel/core": "^7.14.3",
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/plugin-proposal-decorators": "^7.10.5",
    "@babel/plugin-proposal-do-expressions": "^7.10.4",
    "@babel/plugin-proposal-export-default-from": "^7.10.4",
    "@babel/plugin-proposal-export-namespace-from": "^7.10.4",
    "@babel/plugin-proposal-function-sent": "^7.10.4",
    "@babel/plugin-proposal-json-strings": "^7.10.4",
    "@babel/plugin-proposal-logical-assignment-operators": "^7.10.4",
    "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
    "@babel/plugin-proposal-numeric-separator": "^7.10.4",
    "@babel/plugin-proposal-optional-chaining": "^7.10.4",
    "@babel/plugin-proposal-pipeline-operator": "^7.10.5",
    "@babel/plugin-proposal-throw-expressions": "^7.10.4",
    "@babel/plugin-syntax-dynamic-import": "^7.8.3",
    "@babel/plugin-transform-flow-strip-types": "^7.10.4",
    "@babel/plugin-transform-runtime": "^7.10.5",
    "babel-eslint": "^10.0.1",
    "babel-plugin-jsx-control-statements": "^4.1.0",
    "babel-plugin-module-resolver": "^4.0.0",
    "babel-plugin-styled-components": "^1.10.7",
    "babel-preset-expo": "^8.3.0",
    "eslint": "^5.16.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-config-react-app": "^3.0.8",
    "eslint-import-resolver-babel-module": "^5.1.2",
    "eslint-import-resolver-webpack": "^0.11.0",
    "eslint-plugin-flowtype": "^3.4.2",
    "eslint-plugin-import": "^2.16.0",
    "eslint-plugin-jsx-a11y": "^6.2.1",
    "eslint-plugin-jsx-control-statements": "^2.2.1",
    "eslint-plugin-react": "^7.12.4",
    "jest-expo": "^39.0.0",
    "react-native-svg": "12.1.0",
    "react-native-svg-transformer": "^0.14.3",
    "redux-logger": "^3.0.6",
    "shortid": "^2.2.15"
  },
  "private": true
}

main.jsx

import React from 'react';

import { Provider } from 'react-redux';
import { syncTranslationWithStore } from 'react-redux-i18n';
import { setupStore } from 'SourceRoot/store';
import App from 'ScreensRoot';

import { registerRootComponent } from 'expo';

const store = setupStore();
syncTranslationWithStore(store);

const Main = () => (
  <Provider store={store}>
    <App />
  </Provider>
);

registerRootComponent(Main);

One of builds id: c422391c-5314-477e-9390-0180b483068f

I would be glad for any help or advice.

Hi @4kot!

I think there are a couple of things going on here:

  1. We deprecated the packagerOpts in the app manifest, it should not be used anymore.
    Screenshot 2021-05-31 at 14.01.55

  2. We also deprecated the *.expo.js|ts file extension, see this for more info.

  3. It’s recommended to use the index.js file (in the root of your project) to register the root component, it avoids some additional complications finding the entry point of your app. You can set this up by registering the root component in this file, and importing the component from main.jsx (see this as example)

The other files you provided seem to be good. Hope this helps you a bit!