require('react-native-device-info') import is too long and synchronous
See original GitHub issueDescription
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:
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:
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:
- Created 5 years ago
- Reactions:2
- Comments:7 (2 by maintainers)
Top GitHub Comments
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 themqt_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:
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.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).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