-
Notifications
You must be signed in to change notification settings - Fork 626
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(metro-resolver): use proper isRelativeImport
check that works with Windows paths
#1286
base: main
Are you sure you want to change the base?
Conversation
…ith Windows paths
4423f54
to
8c4c199
Compare
I see that Node 18.12 just timed out, it didn't fail. Also, might be nice to drop Node 16 (EOL version) some time, and start testing on Node 20 (current LTS version). |
Interesting... afaik, import/require paths should only ever use posix separators, including on Windows, so my first instinct is that they aren't valid module specifiers and the caller should be normalising to posix. Even Node's algorithm spec defines a relative path as one beginning I wouldn't be surprised if there are more issues than just this one though, given it's not something the resolver is designed or tested for generally. Have you tried these paths with Webpack or Vite? |
Node mostly uses the I think that's the reason why it succeeds in Node, but I'm not sure if Node qualifies
But right now, I'm leaning towards the first option, as it would mean that Node violates it's own module resolution spec. |
To summarize, Metro assumes that all module specifiers ( This does not apply to folder references passed to Metro, e.g. the project root. |
# Why Fixes #29631 Related facebook/metro#1286 # How - Added `convertPathToModuleSpecifier` to **src/start/server/middleware/metroOptions.ts** - Replaced all `'.' + path.sep + ...` statements with posix notation (`'./' + ...`) in **src/start/server/metro/MetroBundlerDevServer.ts** - Added `convertPathToModuleSpecifier` to all module references related to resolve in **src/start/server/metro/MetroBundlerDevServer.ts** # Test Plan Run this PR on Windows. - `$ npx create-expo-app ./test-windows` - `$ cd ./test-windows` - `$ npx expo export --platform web` - Should work without throwing errors like #29631 # Checklist <!-- Please check the appropriate items below if they apply to your diff. This is required for changes to Expo modules. --> - [ ] Documentation is up to date to reflect these changes (eg: https://docs.expo.dev and README.md). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin).
Fixes #29631 Related facebook/metro#1286 - Added `convertPathToModuleSpecifier` to **src/start/server/middleware/metroOptions.ts** - Replaced all `'.' + path.sep + ...` statements with posix notation (`'./' + ...`) in **src/start/server/metro/MetroBundlerDevServer.ts** - Added `convertPathToModuleSpecifier` to all module references related to resolve in **src/start/server/metro/MetroBundlerDevServer.ts** Run this PR on Windows. - `$ npx create-expo-app ./test-windows` - `$ cd ./test-windows` - `$ npx expo export --platform web` - Should work without throwing errors like #29631 <!-- Please check the appropriate items below if they apply to your diff. This is required for changes to Expo modules. --> - [ ] Documentation is up to date to reflect these changes (eg: https://docs.expo.dev and README.md). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin).
Summary
Found an issue with the
isRelativeImport
from the resolver on Windows, resulting in the following issues:The summary of this is that Expo resolves the
main
field from the package during static rendering here. On Windows, it results in a path like.\\node_modules\\expo-router\\entry
, which is correct. Node can resolve this path usingrequire.resolve
:Unfortunately, the
metro-resolver
can't handle this properly because of a single reason:isRelativeImport
returns false for.\\node_modules\\expo-router\\entry
, because the regex only tests posix paths, not Windows paths. It results in the following resolve chain:resolveModulePath
is never called, as this path is not absolute, and incorrectly marked as not relative eitherrealModuleName
is also not false, as the module path is not redirectedisDirectImport
also results infalse
, for the same reasons as 1context.allowHaste
is disabled during Expo static renderingdisableHierarchicalLookup
andextraNodeModules
aren't set by default in Expo projects.allDirPaths
already contain<project>\\node_modules
, and when joining with.\\node_modules\\expo-router\\entry
, it creates paths with<project>\\node_modules\\node_modules\\...
, which are also incorrect.Overview of all values through the debugger
This change adds the Windows path, as a valid path separator, to the
isRelativeImport
test - making it compatible with Windows.Changelog: [Fix] Detect relative imports in the Metro Resolver correctly on Windows
Test plan
Only reproducible on Windows.
$ npm create expo ./test-metro-resolve
$ cd ./test-metro-resolve
$ npx expo export --platform web