facebook/react-native

Port is hard coded to 8081 on iOS, Android templates

jdmarshall opened this issue ยท 43 comments

The documentation on working around port conflict issues is no longer valid

https://facebook.github.io/react-native/docs/troubleshooting.html

Mentions the command line and the URL in AppDelegate.m (which has changed to a function call now)
but does not mention that

node_modules/react-native/React/React.xcodeproj/project.pbxproj

has 8081 hard-coded

Also, to be perfectly blunt, telling people to kill their virus scanner is negligent behavior. We need a solution that doesn't involve asking people to turn off safety features their organization mandated that they use. Especially when you have a company name attached to that advice.

Terminating the process that is using the port is one alternative that is provided, followed with instructions to use a different port which would be a better solution.

Can you edit https://github.com/facebook/react-native/blob/master/docs/Troubleshooting.md with the latest instructions and submit a PR?

I can't, because I can't get it to work. Short of searching the entire node_modules directory for instances of 8081 and changing them, because there are new spots that were hard coded after these instructions were written, and there is no obvious way to override them

react-native/local-cli/server/server.js

Takes an override, but at least most of these below seem to ignore it:

react-native/React/Base/RCTBundleURLProvider.m
react-native/Libraries/WebSocket/RCTWebSocketExecutor.m
react-native/React/React.xcodeproj/project.pbxproj

The others I could probably sort out, despite not being an Objective C programmer, but the last one seems to be new and I don't have the foggiest how to pass in the port as a parameter:

react-native/React/React.xcodeproj/project.pbxproj

shellScript = "if nc -w 5 -z localhost 8081 ; then...

These files below also seem to have port 8081 hard-coded in some places.

react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoHelpers.java
react-native/packager/react-packager/src/Server/__tests__/Server-test.js
react-native/local-cli/util/isPackagerRunning.js
react-native/Libraries/Image/__tests__/resolveAssetSource-test.js

Does this classify as a bug? Or how do i set a custom port that actually works?

Bump. This seems to be a problem with Android as well. Starting the packager on a different port with react-native start --port 8082 worked on v.0.26.* but no longer works on v.0.30.0.

This bug should be treated with with high priority, port 8081 is used by some process like McAfee.
Changing the default port should be easy and painless.

@MichaelCereda If this is a high priority issue for you, consider sending a PR to fix it.

I have some deep philosophical problems with suggesting that a feature that mostly affects new users should be fixed in a PR by those new users.

By all means, let's get esoteric feature requests to file their own PRs. But it comes off as flippant when it's a feature brand new users run into before they even decide if they want to be part of the ecosystem.

(It's especially grating when that bug is a port conflict. Is this 1996 or 2016?)

By now the fastest solution is to kill the process (in my case McAfee) and face the web like a real man.
I always find interesting those type of comments because I have hard time understand if they are a sort of life coaching aimed at the self improvement or mere trolling.

As @jdmarshall said, I think that is an high priority fix because it discourages new users to adopt react-native that is a framework that I personally love.
Submitting a PR it's possible but at the same time would require centralize the port number under one configuration file., the problem with this approach is that RN currently uses 3 different environments that should in many ways be independent from external files (that's why the port number has always been hard-coded in at least 2 places).
The only problem is my opinion that the port RN is using is the 8081 that is one of the most common ever and the risk of conflict is high.
I'll try to find a solution but suggestions from the team will be highly appreciated.

I was one of the people who suggested opening a PR back in August. I did not mean any ill intent with that suggestion. Certain small issues related to the documentation can be addressed faster by editing the file that contains incorrect information. As it happens, in this case, this may not actually be a documentation issue as I first suspected.

Let's see if we can agree on what the issue is here. There are at least two places where the port needs to be configured: the packager, and a client app (iOS or Android, or both).

The instructions for changing the port on the packager seem quite clear and I'd be surprised if the packager is ignoring this flag. So that leaves each of the platforms currently supported by React Native:

[x] Packager
[ ] iOS
[ ] Android

According to @jdmarshall, the RN template in iOS has the port hard coded to 8081. @perkola claims that the same is the case in Android. Can you both confirm that is the case? This will help me route the issue to the right people and/or get work started on a PR.

I have some deep philosophical problems with suggesting that a feature that mostly affects new users should be fixed in a PR by those new users.

I hope you understand that there are 790 issues filed in the repo right now. Every one of them is important to the user filed them, and they want to get it fixed as soon as possible.

If I'm working on the code, which issues do you think I'll fix first? They will be the ones that affect me. It's not because I don't care about this issue, it's because their are higher priority bugs for me which affect me in production.

This is an open source project and the best part is that we can fix things ourselves without having to wait for the core team to prioritise it. And you're by no means a new user since you've filed the issue since 3 months back.

I've removed some stale docs in #13687. Next step would be to update the iOS/Android projects to allow the port to be configured easily without updating the source code.

@hramos is there documentation that show how exactly to go about manually updating the ports in iOS?

No, there isn't as I removed the stale docs.

I've taken another look at this and there seems like more work is needed in the tooling. For example, react-native run-ios and react-native run-android will both attempt to launch a new packager on port 8081, even if one is already running on port 8088 (or any other port of your choosing). This can result in an error if 8081 is already in use by another process, preventing you from launching the app.

I am still facing this issue on android.

I can confirm that in some cases, MacAfee anti-virus software is force-installed on corporate machines and running on port 8081 (verify with sudo lsof -iTCP -sTCP:LISTEN -n -P | grep 8081). There are also some security restrictions which make this process un-killable even to savvy *NIX users. This makes react-native virtually unusable to users on such a machine.

@hramos It is unclear to me - when you run the "start" command, there is a --port option, but when you run let's say run-ios, there is no --port option? This error appears as a result of running run-ios, not start command.

I am facing the issue stated by @netpoetica. MacAfee is using the port 8081 and I don't have the permissions to kill it.

I posted a question in stackoverflow: https://stackoverflow.com/questions/45885418/cant-open-rn-app-either-android-or-ios-when-running-packager-on-8082/45885669#45885669 And following the answer provided by Mojtaba Izadmehr I was able to run the application on Android, but still no luck on iOS :(

Reopening this as it's something worth solving.

We don't face this issue here at Facebook, so ultimately this is something that the community will have to address. I would still like the issue to be fixed at some point, so I have added the "Good First Task" label. We typically reserve these for tasks that can be easily tackled by a newcomer. This particular issue is not straightforward to fix, but nonetheless whoever tackles this will gain a good understanding of how the packager, the run-* scripts, and the Xcode/Android Studio templates all work together. Fixing this will have a great impact on the community as it will unblock people that cannot use the default 8081 port.

@hramos This will be my last comment on this unless I actually find some time to fix this myself:

I completely understand this position, but, - and I mean this in as kind a way possible - hard-coding a port into any sort of community-facing project is the kind of thing that should be corrected as a matter of honor for a dev team. It's the kind of thing that simply should not have been done with any foresight or engineering savvy.

I think asking a newcomer to get in and understand the code base, grepping for 8081 all over the various interdependent submodules, etc, is just a recipe for failure IMHO. An experienced team member should be able to correct this with ease and the project will be more respectable for it.

FWIW - I just spent a week teaching React Native in a coding bootcamp, and due the fragility and finickiness of the project (keeping in mind, I am well aware how difficult of a feat this team is trying to conquer with this project, and much respect for that), I can say hands-down it was the most infuriating subject matter I've ever had to cover. There are enough troubles with dealing with setup of emulators, SDKs, performance (waiting for builds), and quirky bugs that arose on both Windows and Mac, requiring a real feat of Google search prowess to resolve for a class of 28, that something as simple as this was just needless extra encumbrance.

Trust me, this is an issue I'd love to see solved. All I can do right now is be transparent and let the community know that this is not being worked on internally. We get many contributions from external contributors, and this seems like something that, as you mentioned, can be corrected with ease.

Regardless of support the port being changed, on my machine I was running Apache on port 8081 and any react-native command was hanging for about 3 minutes before doing anything, and even then most didn't give an error.

Could the CLI tool check to see if 8081 is in use & if it's actually the packager or not?

@hramos: partial fixed with for android (accepted PR #15316)

I'm also encountering this issue when multiple developers are trying to work with React Native on the same local network, which was a little unexpected.
Currently having to have each developer work on a seperate network (their phone hotspots) to get around this!

DaKaZ commented

@chtrinh I just submitted PR #16172 which extends your #15316 PR by checking for and launching the packager on the requested port. It also adds the --port option to run-ios so that both environments can benefit from this. Would love any comments or suggestions and/or testing.

Thanks :)

@jdmarshall May be we can use this react-native-port-patcher

It's very convenient for me.

DaKaZ commented

@tangkunyin my PR for adding --port was merged a few weeks ago, should be in the 0.53 release :)

These are the files where I had to tweak port number to make it work on a different port

  1. node_modules/react-native/local-cli/server/server.js
  2. XCode -> [App]/Libraries/React.xcodeproj/React/Base/RCTBundleURLProvider.m
  3. XCode -> [App]/Libraries/React.xcodeproj/React/Base/RCTBridgeDelegate.m
  4. XCode -> [App]/Libraries/React.xcodeproj/React/DevSupport/RCTInspectorDevServerHelper.mm
  5. XCode -> [App]/Libraries/RCTWebSocket.xcodeproj/RCTWebSocketExecutor.m

Afterwards, running simple react-native run-ios without specifying any extra argument ran the package and app on my selected port. I am using "react-native": "0.52.0"

samjt commented

This appears to be fixed as far as I can tell in RN 0.56, at least for iOS.
You don't need to manually edit the ports in all/any of the files.

It's possible to export the port as an environmental variable for Metro to use.
export RCT_METRO_PORT=9000; react-native run-ios
followed by
react-native start --port 9000
will generate a build that uses port 9000 and then start Metro on port 9000

I'm currently running two copies of Metro bundler side by side, one for a Storybook development app and another for the actual app I'm building.

samjt commented

As a follow up, I haven't checked the Android project files, but if you see something like:
$RCT_METRO_PORT || 8081 or process.env.RCT_METRO_PORT || 8081 in the Android source files, the same thing will work there too.

Finally, if you really want to change the port permanently for all projects, you should add the line
export RCT_METRO_PORT=9000
to your .bashrc or .bash_profile file in your home folder.

Following @DaKaZ 's pull request (thanks for that btw!), I can now (finally) change the port as simply as react-native run-ios --port 8082 - I've tested it, and can confirm this works.

@samjt , I'm not sure why you wrote (6 days ago) that we need to first export the new port for this to work. My understanding was that you can export the new port if you don't want to always have to specify it in the run-ios/run-android command, but if you do specify it, it doesn't require exporting it.

samjt commented

It's probably because I was using Storybook, but i couldn't get the port argument to work with react-native run-ios

Separately, the lack of configurability is a problem to me because I often work in public networks like those at cafes, which often don't allow for peer-to-peer connections on the network. As a result my phone can't access the bundler url and always uses pre-bundled files... very slow and annoying! Android is fine since you can tunnel with adb, but idk how to do that with iOS. And I can't use something like ngrok to open a tunnel since changing it from localhost:8081 to an arbitrary URL is neither straightforward nor documented.

Right now looking into setting up a VPN solely for this purpose, but it'd be nice to have a legitimate story for my use case.

So to follow-up on this, it appears currently we can override the metro port on iOS exporting the RCT_METRO_PORT environment variable before running npm run ios, but there's no equivalent for npm run android?

Can we also override RCT_METRO_PORT when starting from XCode? I have set the environment variable in the Scheme, but it has no effect. Instead, I need to manually change the #define statements in RCTDefines.h. I am new to XCode, so I might be doing something wrong. Any hint would be much appreciated.

I took a stab at this in for Android with #23616

Closing since the original issue is already fixed (you can easily change the port on iOS by setting environmental variables).

Given the complexity of the native build systems, it's not as easy as it is in JavaScript to just change or auto-detect the port.

Looks like the Android support is being added thanks to @nhunzaker.

Helpful tip: if you encounter the error message 'No bundle URL present' in your iOS emulator, then clean your build folder (ios/build/) and maybe node_modules/ as well. I think the build needs to be completely cleaned and redone any time the port value is changed.

Should these environment variables be documented somewhere? I don't see anything in docs or repo READMEs.

Just wanted to throw out that I am hitting this still while just trying to get through my first react-native demo (in Windows/Android).

Just wanted to throw out that I am hitting this still while just trying to get through my first react-native demo (in Windows/Android).

I too am still seeing this issue. The "--port" option is seemingly ignored by the "react-native run-ios --port 9000" command, as the Metro Bundler still starts up in port 8081. The "react-native start --port 9000" command does not ignore the "--port" option. So while I can force the metro bundler to open up on a port other than 8081, it does not do so when launched as part of the overall "react-native run-ios" command.

This still doesn't solve the problem as I then have a react app installed on iOS that expects the default port, while the metro bundler is listening on the new port (if it is started by itself with the "react-native start --port 9000" command).