The author of this article ： Duan Jiashun
With React Native Technology is widely used in business , Some of the more important functions have also been adopted React Native In order to realize , This is for React Native The opening speed of the page puts forward higher requirements , Because the opening speed is one of the important reasons that affect the user jump out rate .
about React Native Turn on speed optimization , The common solution in the industry is preheating + Split base package , Reduce container initialization time and base library load time .
Yes React Native Unpacking can be done by means of official tools , But the official capabilities are JS Internal split load , If we need to preheat the container , The official loading scheme cannot be used , And we need to transform from the original logic of the client to multi-step loading .
We need to be right about React Native To transform the logic of , You need to be right about React Native The initialization logic is understood .
The picture above is a general process , Here we will give a brief explanation of the key steps .
- RCTBridge After instantiation , Will be ready first of all JS Running threads and native modules .
- Then you create a JSExcutor , It's the actuator JS Whether the execution environment is client or remote debugging （ Android can be a custom-made actuator , such as V8）.
- Load source code （ bundle ）, This may be loaded locally depending on the source , Or maybe through url Load from the remote end .
- Due to initialization JS The actuator and code are triggered in parallel , Here we need a fence to synchronize the two results , After that, it starts to put the code into the actuator to execute （ JS Code runs ）.
- After that , The client will listen for vertical synchronization signals （ The function of this signal is when the page changes , Need to refresh the page again ）.
- here RootView received JS Notification of load completion , Start trigger RunApp Logic , The logic is to start the front end app The corresponding application in the registry .
The whole process is quite long , But the division of labor is quite clear , The place of this unpacking is also very clear .
The green box in the above figure is the point of our transformation , From the point of view of implementation simplicity and current requirements , Design the loading code as serial loading , If further optimization is needed , The loading process can also be designed concurrently .
Here we take an abstraction of the loading capability , Loading a piece of code is defined as a
SourceLoader, So a unpacking bridge It's like having a loader list , Corresponding to bridge The properties on are very simple .
@property (nonatomic, strong) NSArray<id<RCTBridgeSourceLoaderProtocol>> *preloadSourceLoaders; // Preloaded loader - (void)preloadSourceWithCompletion:(void(^)(NSError *error))completion; // Trigger preload loader @property (nonatomic, strong) NSArray<id<RCTBridgeSourceLoaderProtocol>> *sourceLoaders; // Non preload loader - (void)loadSourceWithCompletion:(void(^)(NSError *error))completion; // Trigger non preloader - (void)loadAllSourcesWithCompletion:(void(^)(NSError *error))completion; // Load the preload code first , Reloading non preloaded code
One thing to note here is , We need to start a vertical sync monitor , For performance , It takes to warm up the container to load into the real view before it opens , So here's a tag for the loader , Monitoring can only be turned on after loading into the loader .
After this transformation , our React Native It already supports multi package distributed loading . We can put some basic functions of the JS Code is packaged inside the application , Also reduce some packet size .
Preheat the container
Only subcontract loading can not have a great impact on the loading speed , And the real optimization point is preheating the container . Preheating can do a lot of preparatory work first , Only the business code and rendering pages will be triggered when the business load is in progress .
Limited by the limitations of mobile phone performance , And some of Apple's official strategies , It's unlikely that we'll use this capability without limitation , So here, press 3 In terms of preheating .
Warm up trigger time
At present, the timing of preheating trigger mainly includes the following 3 A little bit
- Cold start
- Hot start
- After container reuse
After these timing triggers , Put it off for a while （5 second ）, To create a warm-up instance . The reason for the delay is that these timing rates are probably doing something CPU Intensive task , If you add the non mandatory task of creating a preheating container at this time , On the contrary, it may affect some performance of the main service .
Preheat the container and destroy it
At present, the main timing of destruction is as follows 2 individual
- Memory warning
The purpose of entering the background destruction is to reduce the memory of the background operation , Although this memory accounts for a small proportion , But Apple's strategy for running in the background is still strict , So we try to minimize the impact of existence .
The scene of preheating
because React Native This capability is not responsible for the main scenarios in our business , Maybe most users will not use React Native , And we do the same warm-up function for all users , It's not the best way . At present, we have no ability to analyze the user scene with intelligent analysis such as machine learning , So this time, I will make a simple classification of some scenes ：
- 3 I haven't used it in days React Native Ability , It is considered that the user will not use this capability in the future
- 3 There are no records destroyed due to memory warnings in days
In the current application cycle ：
- Preload failed 3 Time , Then preload is no longer enabled for that cycle
The key point of container preheating is when it does not affect other user experience , Try to increase the hit rate of preheating as much as possible , At present, some strategies are relatively simple , In the future, if you want to optimize , You need to go deep into business scenarios .
When the unpacking and preheating capabilities are turned on , Mall page bread size from whole package 1.1M Reduced to 856K, Page open time is in iOS In the 450ms Reduced to 200ms about , In Android, by 4500ms Reduced to 2500ms , The optimization effect of both ends is very obvious , It shows that our optimization scheme is very effective .
this React Native The optimization is divided into two parts: unpacking and preheating , They are independent of each other's abilities , And separately AB control , Maximum possible stability . The following will go deep into the business scenarios to do some optimization strategies .
This article was published from Netease cloud music big front-end team , This article is not allowed to be reproduced in any form without authorization . We recruit front end all year round 、iOS、Android, If you're going to change jobs , And just like cloud music , Then join us grp.music-fe(at)corp.netease.com！