What is metro bundler in react-native? - react-native

I am learning React Native.
I can't find a proper documentation for metro bundler. So, I have few questions on it.
As the name suggest it creates a bundle.
But where is the bundle file located ?
Is this same as webpack ?
What is the use of that bundle file ?

A React Native app is a compiled app that is running some Javascript. Whenever you build and run your React Native project, a packager starts up called Metro. You’ve probably seen this output in your terminal before, letting your know the packager is running.
The packager does a few things:
Combines all your Javascript code into a single file, and translates any Javascript code that your device won’t understand (like JSX or some of the newer JS syntax).
Converts assets (e.g. PNG files) into objects that can be displayed by an Image component.
reference:
https://hackernoon.com/understanding-expo-for-react-native-7bf23054bbcd

Metro is a JavaScript bundler which takes in options, an entry file, and gives you a JavaScript file including all JavaScript files back. Every time you run a react native project, a compilation of many javascript files are done into a single file. This compilation is done by a bundler which is called Metro.
Answers to your questions:
1> Bundled file is located on the device itself on which you are building your app and is stored in different formats like in case of Android Plain bundling in which .bundle is created. Another format is of Indexed RAM bundle in which file is stored as binary file.
2> Webpack is also a similar type of module bundler which does bundling to ReactJS web platform and its modules are accessible through browser. Bundling process is while similar to metro.
3> These bundled files are indexed and stored in a particular numerical format and thus its easy at the run time to arrange JS files in order.
There are multiple functions of Metro bundler and you can read about the role of Metro in React Native here : https://medium.com/#rishabh0297/role-of-metro-bundler-in-react-native-24d178c7117e
Hope it helps.

Metro team keeps improving its documentation, now you can find some really good explanations at https://facebook.github.io/metro/docs/concepts (link updated):
Metro is a JavaScript bundler. It takes in an entry file and various
options, and gives you back a single JavaScript file that includes all
your code and its dependencies.
So yes, it is a sort of Webpack, but for React Native apps :)
But where is the bundle file located?
Once the bundler is started, you can check its contents at http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false
(like webpack, it is served from memory, so it is not being written on your project's folder).
What is the use of that bundle file ?
This file is installed in the device for its code to be executed there. Remember that when you are writing code for a React Native application, your code is not "translated" to Java / Swift / whatever. The Native Modules will send events to a Javascript thread, and the JS thread will execute your bundled React Native code.

Related

how do you get java or kotlin source from a react native apps?

Can we extract source code from an apk that built with react-native framework?. i've tried using dex2jar and apktools and cant seem to find anything related to source code
Nothing would prevent Apktool or dex2jar from working on a React Native application. What you are seeing is the majority of React Native application logic lives in compiled Javascript files and the native layer itself (libraries).
So I would put things into 4 buckets
Native Modules (Android - Java/Kotlin, iOS - ObjC/Swift)
RN Bridge (Java/C++)
JS (Virtual Machine - JavascriptCore / Hermes)
JS (Business logic)
The code written in Javascript is interpreted by either the runtime of JSC/Hermes in the VM. This is passed through an intermediate bridge layer of either Java/C++ to the low native portion of the phone. Hence giving the name of React Native.
So if you are decoding an application looking for source code - you'll stumble upon the java code of the bridge and any package that has an intermediate dependency in Java and not the true source code of the application you are probably looking for.
The business logic would more than likely be in a index.android.bundle file somewhere and that will be quite ugly visually as its minified. You'll need a JS beautifier to get anywhere with this path.

Does Hermes hide all the JS code in the JS bundle file?

I heard about Hermes, this tool for react native is supposed to make the app faster by converting the JS code into bytecode (Android).
Now my question is: Does this mean that the index.android.bundle in the APK file will contain only bytecode instead of JS code ?
That is correct. One of the features of Hermes is that it reduces TTI by moving JS compilation from runtime to app package build time.
You can verify this by inspecting the contents of your APK.

Vue Native: Error when running in browser

I've just created a new "vue native" project. I didn't change anything in the default blank app.
I managed to run it on my android device, but impossible to run it on my browser.
I run "npm start" => "metro bundler" opens.
Then I click on "Run in web browser" and I get the error below :
Again, I didn't change anything. I just want to start the default app generated automatically when starting a new project.
Anyone already faced this problem?
Thank you
"This is a known issue, and it seems running vue-native app in web is not possible at the moment, because AppEntry.js tries to import ../../App. The default packager configuration specifies .json as a valid file extension. For some reason, in web, Expo seems to be looking for App.json and ignores App.vue."
https://github.com/GeekyAnts/vue-native-core/issues/268
See the official statement from vue-native creators 2020 7th of July:
"On iOS and Android, Metro is the only component required in the JS build pipeline. We have a custom transformer (in vue-native-scripts) which Metro uses to convert .vue files into equivalent React Native code, which then effectively gets piped into the default Babel transformer used by Metro (for .js) files.
On web, though, Webpack needs to be used for intermediate transformations so that the code can run on web. Metro is used here too, but not for the transformation.
From my findings, the Expo Webpack config uses the babel-loader for handling .js files. So we'd probably need a custom Webpack loader for .vue files (or maybe some other mechanism which can do the job). My guess is that the transformer exported by vue-native-scripts would help in making a loader. But the loader needs to meet the Webpack loader API requirements and expose raw, pitch etc. as described here. We haven't worked out the details of the implementation yet.On iOS and Android, Metro is the only component required in the JS build pipeline. We have a custom transformer (in vue-native-scripts) which Metro uses to convert .vue files into equivalent React Native code, which then effectively gets piped into the default Babel transformer used by Metro (for .js) files.
On web, though, Webpack needs to be used for intermediate transformations so that the code can run on web. Metro is used here too, but not for the transformation.
From my findings, the Expo Webpack config uses the babel-loader for handling .js files. So we'd probably need a custom Webpack loader for .vue files (or maybe some other mechanism which can do the job). My guess is that the transformer exported by vue-native-scripts would help in making a loader. But the loader needs to meet the Webpack loader API requirements and expose raw, pitch etc. as described here. We haven't worked out the details of the implementation yet."
https://github.com/GeekyAnts/vue-native-core/issues/268#issuecomment-640222479
Good news that devices and on simulator running works with expo, and mostly vue-native was designed to run on mobile devices not on web :)
For the web you can have a similar codebase using vuejs.

how to add ios support for existing React Native application with only Android support?

I know it might be very basic question. But I am very new and got a codebase with only android support. I need to add iOS for it. Please help me
As you're aiming to build a cross-platform app, React Native provides two ways to organize the code and seperate it by platform: platform module or platform-specific file extensions.
As you already have an Android app, I assume it has more complexity so you might want to split the code out into separate files.
You say you have an Android app but i don't thing that at any point you specified that the app should only build for Android (you can review in the package and the project configuration). So, the following command should be enough:
react-native run-ios
If you created your react native app from a template (e.g. using npx react-native init ProjectName), it already provides an ios and android folder, so it already supports it. If the file is not there, you could follow the instructions that #Rajan shared above to recreate the ios folder.
If your problem is running the iOS application using npm run ios, and its failing to build or the javascript throws an error, the quickest thing to try is cd ios, then pod install. If this does not work, it might be because you have additional dependencies you have installed, which require specific instructions and configuration to be done in the ios folder. This is library dependent, if needed, will be explained in depth in the README.md of the library. For example, react-native-firebase has a lot of steps, and is different to the android configuration.
Sometimes it is helpful to modify these configurations in XCode instead of editing the files manually (e.g. plist, xml, xproj). You can open xcode quickly using xed ios when in the root project folder.
Note: As usual, remember to have the libraries available in the node_modules folder, npm install.
In the future, you might choose to run different javascript code based on the platform (platform-specific code). React native allows that by using file.android.js and file.ios.js. However, your IDE is likely to struggle with the 2 files, and won't be as helpful compared to file.js. Alternatively, you can import Platform and conditionally check at runtime, what your platform is.
If you used Expo, you don't have access to the native code, but will already support iOS.

React Native code hot load

App store prohibits downloading remote code with the sole exception of WebKit + JS:
3.3.2 An Application may not download or install executable code. Interpreted code may only be used in an Application if all scripts,
code and interpreters are packaged in the Application and not
downloaded. The only exception to the foregoing is scripts and code
downloaded and run by Apple's built-in WebKit framework, provided that
such scripts and code do not change the primary purpose of the
Application by providing features or functionality that are
inconsistent with the intended and advertised purpose of the
Application as submitted to the App Store.
Does this adhere to React Native? Can I host my React Native script bundle on a CDN server and fix bugs by replacing my JS implementation?
See: https://facebook.github.io/react-native/docs/embedded-app.html#add-rctrootview-to-container-view
Yes, you are allowed to hot load JS into your iOS app. This is one of the big advantages of React Native.