facebook / metro

🚇 The JavaScript bundler for React Native
https://metrobundler.dev
MIT License
5.25k stars 626 forks source link

Absolute Paths [global packages] are not working in React Native 0.73.1 #1166

Closed prateekuttreja2020 closed 11 months ago

prateekuttreja2020 commented 11 months ago

Description

Absolute Paths are not working in React Native 0.73.1

Error: undefined Unable to resolve module utility from /Users/apple/sample/App.tsx: utility could not be found within the project or in these directories:

Steps to reproduce

1) Install Application 2) Notice Crash

React Native Version

0.73.1

Affected Platforms

Runtime - Android, Runtime - iOS

Output of npx react-native info

System:
  OS: macOS 13.4.1
  CPU: (8) arm64 Apple M1
  Memory: 175.92 MB / 16.00 GB
  Shell:
    version: 3.2.57
    path: /bin/bash
Binaries:
  Node:
    version: 20.10.0
    path: ~/.nvm/versions/node/v20.10.0/bin/node
  Yarn: Not Found
  npm:
    version: 10.2.3
    path: ~/.nvm/versions/node/v20.10.0/bin/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.14.3
    path: /usr/local/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 22.4
      - iOS 16.4
      - macOS 13.3
      - tvOS 16.4
      - watchOS 9.4
  Android SDK: Not Found
IDEs:
  Android Studio: 2021.3 AI-213.7172.25.2113.9014738
  Xcode:
    version: 14.3/14E222b
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.9
    path: /usr/local/opt/openjdk@17/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.73.1
    wanted: 0.73.1
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Stacktrace or Logs

Error: undefined Unable to resolve module utility from /Users/apple/sample/App.tsx: utility could not be found within the project or in these directories:

Reproducer

https://github.com/prateekuttreja2020/sample

Screenshots and Videos

Simulator Screenshot - iPhone 14 Pro - 2024-01-05 at 17 50 34

cortinico commented 11 months ago

The key part is here: https://github.com/prateekuttreja2020/sample/blob/47e35353d86e0a5d9d19c19845ab65d314001a1c/App.tsx#L27-L28

// import { getNumber } from './src/utility';   //working
import { getNumber } from 'utility';   // not working

@prateekuttreja2020 is this a regression from 0.72?

I'm passing this over to Metro

robhogan commented 11 months ago

Hi @prateekuttreja2020 - what you're describing there is known as a "global package" in Metro. Global package resolution is indeed disabled by default now, as a breaking change in Metro 0.79+ (React Native 0.73+).

We felt it was rarely used, non-standard and more often led to confusion or issues with conflicts - it's also not natively understood by the likes of TypeScript, Jest or Node.js.

The recommended approach now that Metro supports symlink resolution is to make packages like your utility a workspace. For example, if you're using Yarn v1, add "workspaces": [ "src/utility" ] to your root package.json, and run yarn. That creates a symlink at node_modules/utility to ../src/utility, which Metro can follow as of React Native 0.73. This should also work seamlessly with other tooling.

If you do still want to use global packages (not recommended), you can enable it by setting resolver.enableGlobalPackages: true in your Metro config.

// metro.config.js

const config = {
  resolver: {
    enableGlobalPackages: true,
    // ...
  },
  // ...
}
sasweb commented 9 months ago

@robhogan I am not that much into details about how metro works. But AFAIK know in previous RN versions we needed only to set paths in tsconfig.json to make absolute imports (aka aliases) work. Do I understand correct that this is not working anymore due to metro changes?

robhogan commented 8 months ago

Hi @sasweb - sorry for the delay. Metro itself(*) doesn't read tsconfig.json, and never has. If it appeared to work that way it was only because there was some overlap in certain setups between Metro global packages and TS paths, but they're really completely different mechanisms and never intended to mimic each other - there were always lots of cases where tsconfig.json#paths would work in TypeScript but not Metro.

() Expo CLI does* support tsconfig.json#paths via a custom resolver - that should still work, and is a much better solution than enableGlobalPackages. I'd still recommend using workspaces if possible though - that should work with zero config for every tool.