Skip to content
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

Metro bundler not starting when running run-android / run-ios command on linux #28807

Closed
archfz opened this issue May 2, 2020 · 19 comments
Closed
Labels
Needs: Triage 🔍 Platform: Android Android applications. Platform: iOS iOS applications. Stale There has been a lack of activity on this issue and it may be closed soon. Tech: Bundler 📦 This issue is related to the bundler (Metro, Haul, etc) used.

Comments

@archfz
Copy link

archfz commented May 2, 2020

Description

When running the react-native run-android command it tells me that the JS server (metro bundler) is starting, but in fact it does not and the application in the emulator fails to start as of this issue. Runningreact-native start separately resolves the issue. I think this issue might apply for run-ios as well although this needs to be confirmed.

React Native version:

react-native: 0.62.2
@react-native-community/cli: 4.8.0
node: 12 // this version does not matter
system: ubuntu 18.04 // this does not matter as well

Steps To Reproduce

Any project with those versions on linux should fail starting the JS server when running react-native run-android.

Expected Results

  1. When running react-native run-android the bundler should be started if it's not started already in a separate terminal window.
  2. When running react-native run-android and there is an issue with the JS bundler the primary process should display errors why the JS bundler failed starting.

Related issues

#25509
#28281

Snack, code example, screenshot, or link to a repository:

I have debugged the issue extensively since none of the related issue provided any solution for my case. I have found several problems with the linux implementation and I will lay them out here. I have also worked out a hacky temporary solution for the fix.

Temporary solution

To hot fix this problem we can leverage the --terminal parameter on run-android command. This is very hacky but it works

  1. Add the following in your package.json:
  "scripts": {
    "android-linux": "react-native run-android --terminal \"$PWD/shgnome\""
  }
  1. Create a new file called shgnome the modified terminal runner in your project root with this content:
#!/bin/bash
# @TODO: Remove once issue is fixed in react-native.
set -e
# Remove all params and leave only the path to the script.
script=$(echo "$@" | awk '{print $2}')
gnome-terminal -- "$script"
  1. Run chmod u+x ./shgnome.
  2. Run npm run android-linux.

Actual issues

  1. The first issue is in the function runAndroid in file @react-native-community/cli-platform-android/build/runAndroid/index.js. The call startServerInNewWindow return value is completely ignored and thus any potential errors are swallowed. This is why I was not getting any errors in the primary process and this is why this issue survives so long. I suggest that if stderr is set than it should be printed or thrown, but this depends also on the other fixes required.
     try {
        startServerInNewWindow(args.port, args.terminal, config.reactNativePath);
      } catch (error) {
        _cliTools().logger.warn(`Failed to automatically start the packager server. Please run "react-native start" manually. Error details: ${error.message}`);
      }
  1. The process invoked for the metro bundler is react-native/scripts/launchPackager.command. This file does not have the -e cmd flag and thus it does not exit with proper error code if things fail in it's process. This was also influencing the 1. issue since if the flag is set then we get proper error message in the primary process (run-android) that the JS bundler failed to start and why it failed.
#!/bin/bash
# Set terminal title
echo -en "\\033]0;Metro\\a"
clear

THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)

# shellcheck source=/dev/null
. "$THIS_DIR/packager.sh"

if [[ -z "$CI" ]]; then
  echo "Process terminated. Press <enter> to close the window"
  read -r
fi
  1. The startServerInNewWindow function in @react-native-community spawns the launchPackager.command process in an sh shell, while in fact the launchPackager.command explicitly says that it require bash. Because that shellscript was written for bash when it runs with sh it fails due to syntax differences. This failure is not printed to the console of the primary process and is not detected because of issue 2. For this I would suggest letting the shellscript decide in what to run itself and just be called directly as the hot-fix shows. But I am not sure why sh was enforced there and so input is required for this. Note that the code below is modified in the catch case when the terminal is not set with my proposed solution. The try block is the old one as you can see has the sh. I would also suggest not doing the fallback as such and rather if --terminal is set and it does not work just throw an error to the user. The current fallback implementation is unnecessary slower in cases where the the --terminal is not set and it's bad developer experience if the --terminal is set but in fact it doesn't work.
if (process.platform === 'linux') {
    try {
      return _execa().default.sync(terminal, ['-e', `sh ${launchPackagerScript}`], { ...procConfig,
        detached: true
      });
    } catch (error) {
      // By default, the child shell process will be attached to the parent
      return _execa().default(`gnome-terminal -- ${launchPackagerScript}`, {
        ...procConfig,
        shell: true,
        detached: true,
        stdio: 'pipe'
      });
    }
  }
  1. There are two flows on linux: 1 if the --terminal is given then the process is opened separately but if it is not it won't be separate and will be blocking. I am not sure what the implementation was intended there, but even if I applied the fix to change sh to bash it was blocking the primary process and it also wasn't displaying the JS bundler process`s stdout since it is not implemented as such. My solution for this was to use gnome-terminal as can be seen above: this allows to open a separate window and set the blunder to be a separate process.

I would also suggest having tests for the metro bundler auto start.

@react-native-bot react-native-bot added Platform: Android Android applications. Platform: iOS iOS applications. Tech: Bundler 📦 This issue is related to the bundler (Metro, Haul, etc) used. labels May 2, 2020
@ThallyssonKlein
Copy link

Do you know how to run the solution in konsole instead gnome-terminal?

@archfz
Copy link
Author

archfz commented May 11, 2020

@ThallyssonKlein The hacky solution should be the same you just need to change in the shgnome the command base. I haven't used konsole so you should investigate how you launch the terminal with that running a script.

@ThallyssonKlein
Copy link

If I use konsole -e "$script" it works, but the main terminal keep waiting some response and the app not open

@archfz
Copy link
Author

archfz commented May 11, 2020

@ThallyssonKlein Maybe the konsole is blocking, so try putting the process in background konsole -e "$script" &

@ThallyssonKlein
Copy link

The same error happened

@fabOnReact
Copy link
Contributor

My solution for this was to use gnome-terminal as can be seen above: this allows to open a separate window and set the blunder to be a separate process.

Does this have something to do with the fact that when I build with xcode and no yarn server is running, a terminal window is opened and in that terminal the yarn server starts

while this does not happen with gnome-terminal ... I have to separately start one session with yarn server ..

Yet there are many issues so we don't know where to start... 😢

you really know very well the react-native scripts ... for sure this issue made me waste a lot of time before I noticed the server was not running. Thanks

@stale
Copy link

stale bot commented Aug 29, 2020

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Aug 29, 2020
@archfz
Copy link
Author

archfz commented Aug 29, 2020

Up.

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Aug 29, 2020
@pke
Copy link

pke commented Sep 9, 2020

This is still an issue. Please some contributor prevent this ticket from going stale.

@whatdtech
Copy link

Reinstalling android studio with a new emulator or changing the app name in app.json , build.gradle and android manifest.xml solved the issue.

@mostafabrazi
Copy link

mostafabrazi commented Nov 16, 2020

Confirmed the workaround of @archfz, it worked just fine.
Or simply using this command in package.json :

"scripts": {
        "run-android": "gnome-terminal -e \"react-native start\" && react-native run-android",
  },

Screenshot from 2020-11-16 13-38-42

@nitaigao
Copy link

nitaigao commented Dec 4, 2020

Setting export REACT_TERMINAL='tilix' and then running npx react-native run-android spawns metro bundler using the chosen terminal automatically for me.

Source: https://github.com/react-native-community/cli/blob/master/packages/tools/src/getDefaultUserTerminal.ts#L6

@ThallyssonKlein
Copy link

@nitaigao It doesn't work here (Kde Neon (Ubuntu 20.04))

@fabOnReact
Copy link
Contributor

@airtonix
Copy link

airtonix commented Apr 2, 2021

works here in Fedora 33:

...
    "android": "TERM=gnome-terminal react-native run-android",
...

You'll probably want to laucn htop and filter on emulator then f9 kill signal 9 all the instances that have launched without your knowledge.

@Nox04
Copy link

Nox04 commented May 11, 2021

For KDE users:
"android:linux": "konsole --hold --new-tab -e $SHELL -c \"yarn start\" & react-native run-android"

@scousino
Copy link

still experiencing this issue on 0.66

@github-actions
Copy link

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Apr 27, 2023
@github-actions
Copy link

github-actions bot commented May 4, 2023

This issue was closed because it has been stalled for 7 days with no activity.

@github-actions github-actions bot closed this as completed May 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Triage 🔍 Platform: Android Android applications. Platform: iOS iOS applications. Stale There has been a lack of activity on this issue and it may be closed soon. Tech: Bundler 📦 This issue is related to the bundler (Metro, Haul, etc) used.
Projects
None yet
Development

No branches or pull requests