react-native-maps: Unable to resolve "../Utilities/Platform" w/ Metro bundler
Summary
Using the new Metro Bundler and, in my case, react-native-maps, I have compatibilities issues when building for web.
I have some code requiring react-native-maps like so:
if (Platform != 'web') {
const MapView = require(`react-native-maps`).default
// ...
}
When building for native everything works fine, but during a web build even though this code is not executed at runtime it seems like Metro is still trying to resolve react-native-maps and by doing so the compilation is broken, I’ll have errors like these:
Unable to resolve "../Utilities/Platform" from "node_modules/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js"
(because Platform.web.js does not exists)
However if I require react-native-maps “obfucasting” the path for Metro not to track the module like so:
export function requireNativeOnly<T = any>(path: string): T {
return ({
'require': require,
})['require'](path)
}
// ...
if (Platform != 'web') {
const MapView = requireNativeOnly(`react-native-maps`).default
// ...
}
My web build will work perfectly fine but on native at runtime when this module is required (through requireNativeOnly) I’ll have errors saying this module cannot be found:
Unknown named module: "react-native-maps"
Reproducible sample code
if (Platform != 'web') {
const MapView = require(`react-native-maps`).default
// ...
}
Steps to reproduce
Try to make a web build using metro and the code above.
expo start --clear --web
Expected result
I would expect require(react-native-maps) not to be executed/resolved on a web build.
OR
I would expect require(react-native-maps) to be resolved to an empty module on a web build.
Actual result
Metro tells me:
Web Bundling failed 12368ms
Unable to resolve "../Utilities/Platform" from "node_modules/react-native/Libraries/ReactPrivate/ReactNativePrivateInterface.js"
React Native Maps Version
1.3.2
What platforms are you seeing the problem on?
Android, iOS (Apple Maps), iOS (Google Maps)
React Native Version
0.71.3
What version of Expo are you using?
SDK 48
Device(s)
Web
Additional information
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 8
- Comments: 25
Commits related to this issue
- Added patch for RN maps to work on web As shown here: https://github.com/react-native-maps/react-native-maps/issues/4641 — committed to draftbit/react-native-jigsaw by YoussefHenna a year ago
- Expo 47 (#633) * Fixed Picker crash on IOS * v46.7.8 * Added keyboard auto dismiss to Picker and DatePicker (#585) * Added keyboard auto dismiss to Picker and DatePicker * Minor change to... — committed to draftbit/react-native-jigsaw by YoussefHenna a year ago
@monholm Why was this closed? From the comments it’s pretty clear that people are having problems with this. (Yes, I’m one of them, that’s how I got here…)
For what it’s worth, I got this to work by adding a file called
postinstall.jsin my repository with this content:, adding a script in package.lock:
and then running npm install created the correct files. I’m still not able to conditionally render react native maps. For some reason, when running on web, even wrapped in a check for the platform os, the component using react native maps still gets loaded. Maybe I’m doing something wrong though.
no attention… let’s make a new issue?
On Tue, 12 Mar 2024 at 15:37, Camryn @.***> wrote:
A sound solution is hardly one that disables compatibility for web (which his solution replaces the web MapView with blank
divelements.) We need a working solution that enables cross-platform compatibility for this particular component.I am still getting the same problem.
This should be re-opened and addressed.
Bump +1
I just got this coming from the
react-nativemodule itself.:+1
Kudos to @vonkanehoffen for the sound solution.
Expo Router docs seem to suggest this approach as well:
https://docs.expo.dev/router/advanced/platform-specific-modules/#platform-specific-extensions
Props to you for that solution @cavewebs but altering
node_modulesscares me a bit 😉My solution for this is to create a module with dummy components (I only need this for testing). So:
MapView.ts
and so it still works on iOS and Android, add a native only version:
MapView.native.ts
You could even write non-native components that share the same API so this works on web I guess.
These can then be imported as normal and Metro will choose the appropriate one: