getsentry / sentry-react-native

Official Sentry SDK for React Native
https://sentry.io
MIT License
1.57k stars 334 forks source link

Metro Error Unable to resolve module Appearance.js when running simulator locally #4134

Open Hathoriel opened 2 days ago

Hathoriel commented 2 days ago

Metro Error Unable to resolve module Appearance.js when running simulator locally with

Image

I installed sentry-react via wizard.


npx @sentry/wizard -s -i reactNative

┌   Sentry React Native Wizard
│
◇   ────────────────────────────────────────────────────────────────────────────────────────────────╮
│                                                                                                   │
│  The Sentry React Native Wizard will help you set up Sentry for your application.                 │
│  Thank you for using Sentry :)                                                                    │
│                                                                                                   │
│  Version: 3.32.0                                                                                  │
│                                                                                                   │
│  This wizard sends telemetry data and crash reports to Sentry. This helps us improve the Wizard.  │
│  You can turn this off at any time by running sentry-wizard --disable-telemetry.                  │
│                                                                                                   │
├───────────────────────────────────────────────────────────────────────────────────────────────────╯
│
▲  You have uncommitted or untracked files in your repo:
│
│  - .env
│
│  The wizard will create and update files.
│
◇  Do you want to continue anyway?
│  Yes
│
◇  Installed @sentry/react-native with NPM.
│
◇  Are you using Sentry SaaS or self-hosted Sentry?
│  Sentry SaaS (sentry.io)
│
◇  Do you already have a Sentry account?
│  Yes
│
●  If the browser window didn't open automatically, please open the following link to log into Sentry:
│
│  https://sentry.io/account/settings/wizard/***/
│
◇  Login complete.
│
◇  Selected project newco-yl/react-native
│
◆  Added Sentry.init to app/_layout.tsx.
│
◆  app/_layout.tsx changes saved.
│
◆  Added Sentry Expo plugin to app.config.json.
│
◆  Added .env.local to .gitignore.
│
◆  Written .env.local.
│
◆  metro.config.js changes saved.
│
◆  Added auth token to ios/sentry.properties for you to test uploading source maps and iOS debug files locally.
│
▲  ios/sentry.properties already has org and project. Will not add them.
│
▲  ios/sentry.properties already has url. Will not add one.
│
◆  Saved ios/sentry.properties.
│
▲  DO NOT commit auth token to your repository!
│
◇  Do you want to run `pod install` now?
│  Yes
│
◇  Pods installed.
│
▲  Build phase Bundle React Native code and images already includes Sentry.
│
▲  Build phase Upload Debug Symbols to Sentry already exists.
│
◆  Added auth token to android/sentry.properties for you to test uploading source maps and iOS debug files locally.
│
▲  android/sentry.properties already has org and project. Will not add them.
│
▲  android/sentry.properties already has url. Will not add one.
│
◆  Saved android/sentry.properties.
│
▲  DO NOT commit auth token to your repository!
│
▲  Android app/build.gradle file already includes Sentry.
│
◇  Looks like you have Prettier in your project. Do you want to run it on your files?
│  Yes
│
◇  Prettier has formatted your files.
│
◇  To make sure everything is set up correctly, put the following code snippet into your application.
│  The snippet will create a button that, when tapped, sends a test event to Sentry.
│
│  After that check your project issues:
│
│  ****

<Button title='Try!' onPress={ () => { Sentry.captureException(new Error('First error')) }}/>

│
◇  Have you successfully sent a test event?
│  Yes
│
└  Everything is set up!

   If you encounter any issues, let us know here: https://github.com/getsentry/sentry-react-native/issues

When I run

npx expo prebuild --clean 
npx expo run:ios

The app itself not crashes but there are errors in the build and Sentry is not working.

λ Bundling failed 1273ms node_modules/expo-router/node/render.js (1 module)
λ Bundling failed 1275ms node_modules/expo-router/node/render.js (2619 modules)
Web Bundling failed 1279ms node_modules/expo-router/entry.js (1 module)
Web Bundling failed 1282ms node_modules/expo-router/entry.js (2909 modules)
Metro error: Unable to resolve module ../Utilities/Platform from /Users/....my-app/node_modules/react-native/Libraries/Utilities/Appearance.js:

None of these files exist:
  * node_modules/react-native/Libraries/Utilities/Platform(.web.ts|.ts|.web.tsx|.tsx|.web.js|.js|.web.jsx|.jsx|.web.json|.json|.web.cjs|.cjs|.web.mjs|.mjs|.web.scss|.scss|.web.sass|.sass|.web.css|.css)
  * node_modules/react-native/Libraries/Utilities/Platform
  10 |
  11 | import NativeEventEmitter from '../EventEmitter/NativeEventEmitter';
> 12 | import Platform from '../Utilities/Platform';
     |                       ^
  13 | import EventEmitter, {
  14 |   type EventSubscription,
  15 | } from '../vendor/emitter/EventEmitter';

  1 | /**
  2 |  * Copyright (c) Meta Platforms, Inc. and affiliates.
  3 |  *

Call Stack
  <unknown> (node_modules/react-native/Libraries/Utilities/Appearance.js:0)
[myapp] Bridge call to: deviceContexts

My files: App.json

{
  "expo": {
    "name": "my-app",
    "slug": "perservance",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/images/icon.png",
    "scheme": "myapp",
    "userInterfaceStyle": "automatic",
    "splash": {
      "image": "./assets/images/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#262626"
    },
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.***",
      "googleServicesFile": "./GoogleService-Info.plist"
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/images/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      },
      "package": "com.bnwallet.perservance"
    },
    "web": {
      "bundler": "metro",
      "output": "static",
      "favicon": "./assets/images/favicon.png"
    },
    "plugins": [
      "expo-router",
      "expo-localization",
      "@react-native-google-signin/google-signin",
      [
        "@sentry/react-native/expo",
        {
          "url": "https://sentry.io/",
          "project": "react-native",
          "organization": "newco-yl"
        }
      ]
    ],
    "experiments": {
      "typedRoutes": true
    },
    "extra": {
      "eas": {
        "projectId": "***"
      }
    },
    "owner": "bn-wallet",
    "runtimeVersion": {
      "policy": "appVersion"
    },
    "updates": {
      "url": "***"
    }
  }
}

_layout.tsx

import * as SplashScreen from "expo-splash-screen";
// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();

// Initialize Amplitude
import {
  init as AmplitudeInit,
  track,
} from "@amplitude/analytics-react-native";
AmplitudeInit(process.env.EXPO_PUBLIC_AMPLITUDE_API_KEY!);

import { DarkTheme, ThemeProvider } from "@react-navigation/native";
import { useFonts } from "expo-font";
import { Stack } from "expo-router";
import { useEffect } from "react";
import "react-native-reanimated";

import { useColorScheme } from "@/hooks/useColorScheme";
import { Colors } from "@/constants/Colors";
// @ts-ignore
import { setColorScheme } from "react-native/Libraries/Utilities/Appearance";
import { init } from "@amplitude/analytics-react-native";
import * as Sentry from "@sentry/react-native";

Sentry.init({
  dsn: "https://550464b3a129103007efa3b2787ff157@o4508042022486016.ingest.us.sentry.io/4508047487467520",

  // uncomment the line below to enable Spotlight (https://spotlightjs.com)
  // enableSpotlight: __DEV__,
});

export default function RootLayout() {
  const colorScheme = useColorScheme();

  track("App Opened");

  useEffect(() => {
    setColorScheme("dark");
  }, []);

  return (
    <ThemeProvider value={DarkTheme}>
      <Stack
        screenOptions={{
          headerStyle: {
            backgroundColor: Colors.dark.background,
          },
          headerTintColor: Colors.dark.tint,
          headerTitleStyle: {
            fontWeight: "bold",
            color: Colors.dark.text,
          },
        }}
      >
        <Stack.Screen
          name="index"
          options={{
            title: "Home",
            headerShown: false,
          }}
        />
        <Stack.Screen
          name="signup"
          options={{
            headerShown: false,
          }}
        />
      </Stack>
    </ThemeProvider>
  );
}

metro.config.js

const { getSentryExpoConfig } = require("@sentry/react-native/metro");

/** @type {import('expo/metro-config').MetroConfig} */
const config = getSentryExpoConfig(__dirname);

config.transformer.babelTransformerPath = require.resolve(
  "react-native-react-bridge/lib/plugin",
);
config.resolver.extraNodeModules = {
  ...config.resolver.extraNodeModules,

  assert: require.resolve("empty-module"), // assert can be polyfilled here if needed
  http: require.resolve("empty-module"), // stream-http can be polyfilled here if needed
  https: require.resolve("empty-module"), // https-browserify can be polyfilled here if needed
  os: require.resolve("empty-module"), // os-browserify can be polyfilled here if needed
  url: require.resolve("empty-module"), // url can be polyfilled here if needed
  zlib: require.resolve("empty-module"), // browserify-zlib can be polyfilled here if needed
  path: require.resolve("empty-module"),
  crypto: require.resolve("empty-module"),
  buffer: require.resolve("@craftzdog/react-native-buffer"),
};

// config.resolveRequest = (context, moduleName, platform) => {
//   if (moduleName === "crypto") {
//     // when importing crypto, resolve to react-native-quick-crypto
//     return context.resolveRequest(context, "react-native-quick-crypto", platform);
//   }
//   // otherwise chain to the standard Metro resolver.
//   return context.resolveRequest(context, moduleName, platform);
// }

// Add this custom resolver -- due to the ZeroDev SDK using .js instead of .ts
config.resolver.resolveRequest = (context, moduleName, platform) => {
  // Check if the import ends with .js but the file is actually .ts
  if (moduleName.endsWith(".js")) {
    const tsModule = moduleName.replace(/\.js$/, ".ts");
    try {
      return context.resolveRequest(context, tsModule, platform);
    } catch (e) {
      // If .ts file doesn't exist, fall back to original request
    }
  }
  // For all other cases, use the default resolver
  return context.resolveRequest(context, moduleName, platform);
};

module.exports = config;

package.json

{
  "name": "my-app",
  "main": "expo-router/entry",
  "version": "1.0.0",
  "scripts": {
    "start": "expo start",
    "reset-project": "node ./scripts/reset-project.js",
    "rebuild:ios": "yes | npx expo prebuild --clean && npx expo run:ios",
    "android": "expo run:android",
    "ios": "expo run:ios",
    "web": "expo start --web",
    "test": "jest --watchAll",
    "lint": "expo lint",
    "format": "prettier --write ."
  },
  "jest": {
    "preset": "jest-expo"
  },
  "dependencies": {
    "@amplitude/analytics-react-native": "^1.4.10",
    "@expo/vector-icons": "^14.0.2",
    "@react-native-async-storage/async-storage": "1.23.1",
    "@react-native-google-signin/google-signin": "^13.0.1",
    "@react-native/metro-config": "^0.75.3",
    "@react-navigation/native": "^6.0.2",
    "@sentry/react-native": "^5.33.1",
    "@toruslabs/react-native-tss-lib-bridge": "^2.2.0",
    "@toruslabs/tss-dkls-lib": "^4.0.0",
    "@web3auth/base": "^8.12.4",
    "@web3auth/ethereum-mpc-provider": "^8.12.4",
    "@web3auth/mpc-core-kit": "^3.1.2",
    "@zerodev/cab": "^0.0.16",
    "@zerodev/multi-chain-validator": "^5.3.11",
    "@zerodev/sdk": "^5.3.15",
    "empty-module": "^0.0.2",
    "expo": "~51.0.28",
    "expo-constants": "~16.0.2",
    "expo-dev-client": "~4.0.26",
    "expo-font": "~12.0.9",
    "expo-linking": "~6.3.1",
    "expo-localization": "~15.0.3",
    "expo-router": "~3.5.23",
    "expo-secure-store": "~13.0.2",
    "expo-splash-screen": "~0.27.6",
    "expo-status-bar": "~1.12.1",
    "expo-system-ui": "~3.0.7",
    "expo-updates": "~0.25.24",
    "expo-web-browser": "~13.0.3",
    "i18n-js": "^4.4.3",
    "metro-react-native-babel-transformer": "^0.77.0",
    "node-libs-react-native": "^1.2.1",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-native": "0.74.5",
    "react-native-gesture-handler": "~2.16.1",
    "react-native-quick-crypto": "^0.7.5",
    "react-native-react-bridge": "^0.12.1",
    "react-native-reanimated": "~3.10.1",
    "react-native-safe-area-context": "4.10.5",
    "react-native-screens": "3.31.1",
    "react-native-web": "~0.19.10",
    "react-native-webview": "13.12.2",
    "viem": "^2.17.0"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@types/jest": "^29.5.12",
    "@types/react": "~18.2.45",
    "@types/react-test-renderer": "^18.0.7",
    "eslint": "^8.57.0",
    "eslint-config-expo": "^7.1.2",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-prettier": "^5.2.1",
    "jest": "^29.2.1",
    "jest-expo": "~51.0.3",
    "prettier": "^3.3.3",
    "react-test-renderer": "18.2.0",
    "typescript": "~5.3.3"
  },
  "private": true
}

Could you please help me what I am doing wrong?

Thank you.

Hathoriel commented 1 day ago

Looks like the Sentry dashboard received the error event, but the build is still having the same error.

krystofwoldrich commented 1 day ago

Hi @Hathoriel, thank you for the message and all the details,

based on your last update, I assume the build error was not present before adding Sentry to the project.

Is the correct? Or was the issue that error was not reported to Sentry?

krystofwoldrich commented 1 day ago

At the moment I don't see any relation to Sentry and loading the Appearence.js.

Does the same happens when using the official export import {Appearance} from 'react-native';?

https://reactnative.dev/docs/appearance

Hathoriel commented 1 day ago

Hi @Hathoriel, thank you for the message and all the details,

based on your last update, I assume the build error was not present before adding Sentry to the project.

Is the correct? Or was the issue that error was not reported to Sentry?

Yes It is correct, before this error message was not present.

It looks like the metro/expo is building web and IOs versions in parallel when I run expo run:ios

Looks like the problem affects only the web build, not the IOs. And errors are sent to the Sentry when something throws. So the IOS version looks good, but the problem is with Web.

I don't need web for now, it would be best if I can something hide it or turn off.

Hathoriel commented 1 day ago

When I commented out import

import { setColorScheme } from "react-native/Libraries/Utilities/Appearance";

The issue disappeared. But now I see different one.

Metro error: Failed to install react-native-quick-crypto: The native `QuickCrypto` Module could not be found.
* Make sure react-native-quick-crypto is correctly autolinked (run `npx react-native config` to verify)
* Make sure you rebuilt the app.

  34 |     }
  35 |     message += '\n* Make sure you rebuilt the app.';
> 36 |     throw new Error(message);
     |           ^
  37 |   }
  38 |
  39 |   // see #333, commenting this may allow the library to work in new architecture

Good that at least something changed. 👍

krystofwoldrich commented 1 day ago

Thank you for the details,

when Sentry runs in development mode it uses the Metro Dev server to symbolicate the stack trace of errors. This makes request to the server which triggers the web build.

Could you confirm for me, if you disable the local symbolication the errors are not happening? Note this does not effect release build which are symbolicated on the Sentry servers.

To disable the local symbolication add the following to your Sentry.init options.

integrations(integrations) {
  return integrations.filter(i => i.name !== 'DebugSymbolicator');
},
Hathoriel commented 1 day ago

Oh nice @krystofwoldrich, looks like this helped! I don't see any errors now in the console.

Could you confirm for me, if you disable the local symbolication the errors are not happening? Note this does not effect release build which are symbolicated on the Sentry servers.

So It means that release build will be OK? And also source mapping will work?

Thank you so far @krystofwoldrich for your help, much appreciated.