expo / expo

An open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.
https://docs.expo.dev
MIT License
34.6k stars 5.56k forks source link

[SDK52] Android release variant build crashes on Windows #33151

Open andrejpavlovic opened 1 day ago

andrejpavlovic commented 1 day ago

Minimal reproducible example

https://github.com/allboatsrise/expo-52-test

What platform(s) does this occur on?

Android

Where did you reproduce the issue?

in a development build

Summary

I'm getting Error: Unable to resolve module error when trying to run npx expo run:android --variant release on Windows on fresh install.

Reproduce:

npx create-expo-app@latest my-app
cd my-app
npx expo run:android --variant release

Result:

√ Created native directory
√ Updated package.json | no changes
√ Finished prebuild
› Building app...
Starting Metro Bundler
warning: Bundler cache is empty, rebuilding (this may take a minute)
Error: Unable to resolve module ./C:/Users/Andrej/my-app/node_modules/expo-router/entry.js from C:\Users\Andrej\my-app/.:

None of these files exist:
  * C:\Users\Andrej\my-app\node_modules\expo-router\entry.js(.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx|.android.mjs|.native.mjs|.mjs|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json|.android.cjs|.native.cjs|.cjs|.android.scss|.native.scss|.scss|.android.sass|.native.sass|.sass|.android.css|.native.css|.css)
  * C:\Users\Andrej\my-app\node_modules\expo-router\entry.js
Error: Unable to resolve module ./C:/Users/Andrej/my-app/node_modules/expo-router/entry.js from C:\Users\Andrej\my-app/.:

None of these files exist:
  * C:\Users\Andrej\my-app\node_modules\expo-router\entry.js(.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx|.android.mjs|.native.mjs|.mjs|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json|.android.cjs|.native.cjs|.cjs|.android.scss|.native.scss|.scss|.android.sass|.native.sass|.sass|.android.css|.native.css|.css)
  * C:\Users\Andrej\my-app\node_modules\expo-router\entry.js
    at ModuleResolver.resolveDependency (C:\Users\Andrej\my-app\node_modules\metro\src\node-haste\DependencyGraph\ModuleResolution.js:112:15)
    at DependencyGraph.resolveDependency (C:\Users\Andrej\my-app\node_modules\metro\src\node-haste\DependencyGraph.js:235:43)
    at C:\Users\Andrej\my-app\node_modules\metro\src\lib\transformHelpers.js:160:21
    at Server._resolveRelativePath (C:\Users\Andrej\my-app\node_modules\metro\src\Server.js:1104:12)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at MetroBundlerDevServer.resolveRelativePathAsync (C:\Users\Andrej\my-app\node_modules\@expo\cli\src\start\server\metro\MetroBundlerDevServer.ts:1677:12)
    at MetroBundlerDevServer.metroLoadModuleContents (C:\Users\Andrej\my-app\node_modules\@expo\cli\src\start\server\metro\MetroBundlerDevServer.ts:506:35)
    at MetroBundlerDevServer.legacySinglePageExportBundleAsync (C:\Users\Andrej\my-app\node_modules\@expo\cli\src\start\server\metro\MetroBundlerDevServer.ts:809:20)
    at exportEmbedBundleAndAssetsAsync (C:\Users\Andrej\my-app\node_modules\@expo\cli\src\export\embed\exportEmbedAsync.ts:193:21)
    at exportEmbedInternalAsync (C:\Users\Andrej\my-app\node_modules\@expo\cli\src\export\embed\exportEmbedAsync.ts:125:37)

It looks like some sort of an issue building on Windows since the path seems to be prefixed with ./

Environment

expo-env-info 1.2.1 environment info:
    System:
      OS: Windows 10 10.0.19045
    Binaries:
      Node: 18.18.0 - C:\Program Files\nodejs\node.EXE
      Yarn: 1.22.22 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
      npm: 10.2.5 - C:\Program Files\nodejs\npm.CMD
      Watchman: 20240728.093121.0 - C:\ProgramData\chocolatey\bin\watchman.EXE
    IDEs:
      Android Studio: AI-242.21829.142.2421.12409432
    npmPackages:
      expo: ~52.0.9 => 52.0.9
      expo-router: ~4.0.7 => 4.0.7
      react: 18.3.1 => 18.3.1
      react-dom: 18.3.1 => 18.3.1
      react-native: 0.76.2 => 0.76.2
      react-native-web: ~0.19.13 => 0.19.13
    Expo Workflow: bare

Expo Doctor Diagnostics

✔ Check package.json for common issues
✔ Check Expo config for common issues
✔ Check native tooling versions
✔ Check if the project meets version requirements for submission to app stores
✔ Check for common project setup issues
✔ Check dependencies for packages that should not be installed directly
✔ Check for app config fields that may not be synced in a non-CNG project
✔ Check npm/ yarn versions
✔ Check for issues with Metro config
✔ Check Expo config (app.json/ app.config.js) schema
✔ Validate packages against React Native Directory package metadata
✔ Check that native modules do not use incompatible support packages
✔ Check for legacy global CLI installed locally
✔ Check that packages match versions required by installed Expo SDK
✔ Check that native modules use compatible support package versions for installed Expo SDK
andrejpavlovic commented 1 day ago

It looks the issue is caused by this line which I assume is checking whether the path is absolute, and if not, prepends ./ to it. However the absolute check doesn't work as expected on Windows.

https://github.com/expo/expo/blob/97cb399b53dd57171429b2afeb78eb3ff38f2501/packages/%40expo/cli/src/start/server/metro/MetroBundlerDevServer.ts#L804-L807

andrejpavlovic commented 1 day ago

This patch worked for me, though I hope there is a more robust way to do this check - maybe path.isAbsolute.

@expo+cli+0.21.7.patch

diff --git a/node_modules/@expo/cli/build/src/start/server/metro/MetroBundlerDevServer.js b/node_modules/@expo/cli/build/src/start/server/metro/MetroBundlerDevServer.js
index a91ee15..ae7ec91 100644
--- a/node_modules/@expo/cli/build/src/start/server/metro/MetroBundlerDevServer.js
+++ b/node_modules/@expo/cli/build/src/start/server/metro/MetroBundlerDevServer.js
@@ -635,7 +635,7 @@ class MetroBundlerDevServer extends _bundlerDevServer.BundlerDevServer {
             serializerOutput: "static"
         };
         // https://github.com/facebook/metro/blob/2405f2f6c37a1b641cc379b9c733b1eff0c1c2a1/packages/metro/src/lib/parseOptionsFromUrl.js#L55-L87
-        if (!opts.mainModuleName.startsWith("/")) {
+        if (!opts.mainModuleName.startsWith("/") && !/^[a-zA-Z]:\\/.test(opts.mainModuleName)) {
             opts.mainModuleName = "./" + opts.mainModuleName;
         }
         const output = await this.metroLoadModuleContents(opts.mainModuleName, opts, extraOptions);
Kudo commented 6 hours ago

33114 covers the path.isAbsolute fwiw