question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

require('react-native-device-info') import is too long and synchronous

See original GitHub issue

Description

At the moment, the first require('react-native-device-info') call takes around 200-600ms on Android emulator (in a non-minified debug mode, depending on a configuration and luck). Below is the treemap (produced by an internal tool) of require() timings (how long each require(modulename) takes). All this happens synchronously:

screen shot 2018-10-09 at 7 28 29 pm

Since your project initialization takes a lion share of the time, I have to open this issue.

I took some time to look into the code, and as far as I can see, the only potentially heavy thing that is happening in react-native-device-info/index.js file is this call to its appropriate native module:

var RNDeviceInfo = NativeModules.RNDeviceInfo;

if (!RNDeviceInfo && Platform.OS === 'web') {
  RNDeviceInfo = require('./web');
}

I’ve checked out the RN docs to see what can happen synchronously there, and specifically, the getConstants() method drew my attention:

An optional method called getConstants returns the constant values exposed to JavaScript. Its implementation is not required but is very useful to key pre-defined values that need to be communicated from JavaScript to Java in sync.

That correlates with what I see in RNDeviceModule.getConstants() method, it looks quite heavy indeed:

https://github.com/rebeccahughes/react-native-device-info/blob/master/android/src/main/java/com/learnium/RNDeviceInfo/RNDeviceModule.java#L230

tl;dr

I suggest rewriting the native classes, so they provide every property on demand. Values caching can be trivially done on the JavaScript side.

I need to know what you think before I start implementing that in a pull request. Thanks in advance.

Use Case

Any project that imports react-native-device-info will benefit from this, since such a performance fix will get rid of a long synchronous pause during the first require('react-native-device-info'). Start-up time of RN apps that use the project should significantly improve (at least on Android).

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:2
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

6reactions
rotemmizcommented, Dec 23, 2018

Hey @machour, The main culprit in both iOS and Android is the way react-native-device-info gets a hold of the webview user agent string.

On Android WebSettings.getDefaultUserAgent(this.reactContext) takes 200-500ms, depending on the device CPU. This blocks the mqt_native_modules thread from doing any other native module processing during that time.

On iOS, [[UIWebView alloc] initWithFrame:CGRectZero]; takes ~200ms on a Simulator (Core i7 MacBook Pro 2016), blocking the main thread!!

The main thing to discuss here, is if collecting this user agent is even relevant. Both iOS and Android network implementations on React Native do not use this user agent. RN apps are usually not using webviews. Is there a reason to identify with that user agent anywhere? If there is, where?

If you think there is still a good reason to keep it, these are the options I can think of:

  1. Android has a default user agent string (actually used in this repo as a fallback), it is much faster, and supplies data about the device OS (and usually device name as well, something like Dalvik/2.1.0 (Linux; U; Android 8.1.0; Android SDK built for x86_64 Build/OSM1.180201.023)). On iOS, we can build something out of the data already provided by the library.
  2. getUserAgent() can return either default values, or the suggested above, and another, async function can be introduced: `getWebviewUserAgent(), which will only trigger a webview creation lazily (and probably cache the result as well).
0reactions
mikehardycommented, Aug 30, 2019

All of the init and constants setting is purged on v3 and the information is all fetched dynamically with Promises, will release as soon as it’s all checked

Read more comments on GitHub >

github_iconTop Results From Across the Web

require('react-native-device-info') import is too long ... - GitHub
Any project that imports react-native-device-info will benefit from this, since such a performance fix will get rid of a long synchronous pause ...
Read more >
Invariant Violation: Calling synchronous methods on native ...
This is temporary fix. This is working perfectly on my side. you have to edit this file.
Read more >
Example to Get Device Information in React Native
You will see how to access the device information using different ways (Sync, Async, Constant, Hook) in React Native using React Native Device...
Read more >
react-native-device-info | Yarn - Package Manager
Fast, reliable, and secure dependency management.
Read more >
React Native Libraries for “Native Features” - Bits and Pieces
To use the API, first, you need to import it like this. import DeviceInfo from 'react-native-device-info';import { getUniqueId, getManufacturer } ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found