foreword
This article mainly introduces the introduction of react-native (hereinafter referred to as RN), and the similarities and differences between it and the front end
The article does not involve the specific implementation of the function
Choose the advantage
Let's talk about why many people choose to use RN, the difference between its corresponding features and ordinary Web
- Front-end resources, ecological exchange
Because the languages used are JS and react, it can be switched seamlessly for the front end, and he can also use various front-end packages
On the JS side, Android and iOS are the same set of code
- Hot update
Many reasons for choosing to use RN is that there are hot updates
Briefly explain the hot update. When running the APP, we can replace the js layer in real time through the received notification. After the replacement is completed, the APP generally needs to be restarted. At this time, the user can be asked, or it can be reloaded at the next restart. Enter new JS code
This can ensure that the js environment used by the user can be newer. If it is an update of the native APP, the user needs to go to the app store to download it again.
- native support
RN interacts with native through bridging, and integrates into native APP at page level
Many of his components, methods call native methods/components, which have better performance than webview
Horizontal comparison of cross-end frames
A simple comparison of RN and Flutter
surroundings
无论是RN Flutter
,都需要Android 和IOS 的开发环境,也就是JDK
、 Android SDK
、 Xcode
, The difference is that:
- RN requires npm, node,
react-native-cli
and other configurations. -
Flutter
flutter sdk
8ef6473a34894a391a14200ea12735d7---和Android Studio
/VSCode
上的Dart
与Flutter
。
For the front end, the RN environment is relatively friendly
Implementation principle
On Android and IOS , Flutter and React Native both require a native platform by default
Activity
/ ViewController
support, and it belongs to a "single page application" at the native level, ** and the biggest difference between them is actually the UI construction:
- RN:
React Native is a set of UI frameworks. By default, React Native will load JS files under Activity
, then run it in JavaScriptCore
to parse the Bundle file layout, and finally stack a series of native The control is rendered.
To put it simply, the page layout is configured by writing JS code, and then React Native will finally parse and render it into a native control , such as <View>
label corresponding to ViewGroup/UIView
, <ScrollView>
corresponding to the label ScrollView/UIScrollView
, <Image>
label corresponding to ImageView/UIImageView
and so on.
- Flutter:
The vast majority of Flutter Widget
are platform-independent, the developer develops the app based on Framework
, while Framework
runs on Engine
, by Engine
for adaptation and cross-platform support. This cross-platform support process is actually to "dataize" the Widget
in the Flutter UI, and then draw it directly to the screen through the Engine
on the Skia
.
Similar to front-end canvas drawing
This section is from the article: https://www.jianshu.com/p/da80214720eb
shortcoming
RN:
- It is not fully compatible with W3C specifications. For example, in W3C, you can easily set the size and thickness of the rounded corners, and the border is implemented and dashed, but on the client side, this is more difficult to implement. Therefore, these technologies can only support the W3C standards to a limited extent.
- js running performance bottleneck.
- The performance bottleneck of data communication.
Flutter:
- Unable to dynamically update.
- Memory and package size usage.
- The cost of learning is high and the ecology is insufficient.
js runtime environment
When using RN, JS code will run on two different environments:
- In most cases, RN uses JavaScriptCore , the JavaScript engine used by Safari. But on iOS JavaScriptCore doesn't use just-in-time compilation technology (JIT), because in iOS apps don't have permission to write and execute memory pages (and therefore cannot generate code dynamically).
- When debugging with Chrome, all JavaScript code runs in Chrome and communicates with native code via WebSocket. The operating environment at this time is the V8 engine .
So when we start debugging, there will be some differences from the official running environment
RN has built in Babel
converter. Therefore, we do not need to configure many grammars babel
. The grammar environment can be used directly and you can see the specific configuration here .
timer
There are timers for animations in RN: InteractionManager
A big reason why native apps feel smooth is to avoid heavy lifting during interactions and animations.
In RN, it is limited because we only have one thread of JavaScript execution. So there InteractionManager
to make sure all interactions and animations are handled before doing the heavy lifting.
InteractionManager.runAfterInteractions(() => {
// ...需要长时间同步执行的任务...
});
Compared to several other timers:
-
requestAnimationFrame()
: code used to execute the animation to control the view over a period of time -
setImmediate/setTimeout/setInterval()
: Execute code later. Note that this may delay the animation currently in progress. -
runAfterInteractions()
: Execute the code later, without delaying the currently running animation.
Hermes engine
Hermes is a new open source JavaScript engine optimized for RN applications. For many applications, enabling the Hermes engine can optimize startup time, reduce memory usage and space usage.
Features of Hermes
- Precompiled bytecode (the engine loads binary code more efficiently than running JS scripts)
- No JIT compiler (reduced engine size, optimized memory footprint, but the performance of running JS scripts directly is worse than V8 and JSC)
- Garbage collection strategy for mobile
Optimization principle
The traditional JavaScript engine usually completes the code execution in the mode of the above figure. In the compilation stage, only babel escape and minify compression are completed. The product is still a JavaScript script. The tasks of interpretation and execution need to be completed at runtime (such as the V8 engine, which will also be executed at runtime). The obvious disadvantage is that it needs to be interpreted and executed at runtime, and even requires system resources to perform compilation tasks.
The Hermes engine uses the aot compilation method to prepend the interpretation and compilation process to the compilation stage, and only complete the execution of the machine code at runtime, which greatly improves the operating efficiency.
native ui components
One advantage of RN is that it can insert native components to improve the performance of APP. If we want to use ---1399288d6b09d19651108ad59c875a7a js
in ImageView
, then we need these steps:
- Create a subclass of
ViewManager
. - Implement the
createViewInstance
method. - Property setters for exported views: use the
@ReactProp
(or@ReactPropGroup
) annotation. - Register this view management class in the application package
createViewManagers
. - Implement JavaScript modules.
The above is the addition of Android, relatively speaking, iOS will be simpler:
- First create a subclass of
RCTViewManager
. - Added
RCT_EXPORT_MODULE()
macro tag. - Implement the
-(UIView *)view
method.
// RNTMapManager.m
#import <MapKit/MapKit.h>
#import <React/RCTViewManager.h>
@interface RNTMapManager : RCTViewManager
@end
@implementation RNTMapManager
RCT_EXPORT_MODULE(RNTMap)
- (UIView *)view
{
return [[MKMapView alloc] init];
}
@end
In JS use:
// MapView.js
import { requireNativeComponent } from 'react-native';
// requireNativeComponent 自动把'RNTMap'解析为'RNTMapManager'
export default requireNativeComponent('RNTMap');
// MyApp.js
import MapView from './MapView.js';
...
render() {
return <MapView style={{ flex: 1 }} />;
}
This is a simple display, about passing a value is to judge more attributes
In addition to native components, js can also pass values to the mobile terminal, add listening events (including promise callbacks), and the corresponding mobile terminals can also
This forms a complete communication system at both ends
Link native library
The above picture is react-native-splash-screen
library install
and link
When we use the three-party native library, we need to do a function of link
All the libraries we ship with RN are in the Libraries folder in the repository. Some of them are pure Javascript code, you just need to import them to use. In addition, some libraries are implemented based on some native code. You must add these files to your application, otherwise the application will generate errors when you use these libraries.
And link is an alternative to manually linking dependencies in a project.
Manual linking is a very troublesome thing, and the solutions for Android and iOS are still different. For details, please refer to
status quo
Fortunately, but if the RN library we use is above 0.60
, we don't need to use the link
instruction
In Android, it will automatically link, and in iOS, you can use cocoapods
to download the native package
cocoapods
Briefly,CocoaPods
is a dependency manager forSwift
andObjective-C
Cocoa projects.
By analogy, it can be seen asnpm
.
When using cocoapods, you will need the file Podfile
, which can be compared to package.json
pod install
( npm install
) 下载, 下载完毕Pods
文件下, lock
文件:
Podfile.lock
, Manifest.lock
two copies
Just a word, if there is no circumvention tool pod download will become very troublesome and often get stuck
route management
There are two commonly used routing management in RN: one is React Navigation
, the other is react-native-navigation
The difference between the two is that the former is through JS code, through the combination of monorepo
, and through the optimization of react-native-screens
and react-native-reanimated v2
and other libraries, and finally form the final native native experience
As for why most of them are placed on the js side, and what are their benefits, I will explain them in the hot update section below
The latter uses a native container as a routing interface, such as <ScreenContainer>
or <Screen>
, which brings native performance, features and experience, but when we use this library or integrate another library will cause some trouble
How is it different from the front end?
The routing in the APP will have a concept stack (stack) , which is the biggest difference from the web
Here is a picture to introduce:
When we go to a new page, the previous page will not be destroyed (in most cases), he is adding a new page to the stack, so in APP, we must always be careful about memory leaks
Hot update
This is one of the most commonly used and one of the biggest advantages in RN - hot update
Hot update plan
Generally there are three options:
- react-native-pushy
The code hot update service launched by ReactNative Chinese website, the free stage is suitable for small applications, mild update requirements, and you need to charge if you exceed it. - react-native-code-push + AppCenter
Completely free, domestic speed may be slow, suitable for individual developers - react-native-code-push + code-push-server
Suitable for companies to build their own hot update server
Notes on hot updates:
- Apple App allows the use of hot updates Apple's developer agreement , in order not to affect the user experience, it is stipulated that silent updates must be used. Google Play cannot use silent updates, and a pop-up box must inform the user that the app has an update. China's android market must use silent updates (if the pop-up box prompts, the app will be rejected by the reason of "please upload the latest version of the binary application package").
- react-native-code-push only updates resource files, not java and Objective C, so when npm upgrades the version of the dependent package, if the localized implementation used by the dependent package, you must change the application version number at this time, and then recompile the app Publish to the app store.
Generally speaking, the process of mobile phone hot update:
Among them, detection, download, restart, etc. are all APIs provided by the npm package react-native-code-push
There is still room for further optimization of hot updates, such as: if the bundle packaged at one time is too large, and it is subpackaged, this article will not analyze it in depth.
APP update
As we mentioned above, after the native component is updated, you need to download the APP again, so how to update it conveniently?
Here is an article I wrote before, the principle is as follows:
Click here for the original text
The above hot update and APP update also have corresponding implementations on electron
. For students on the web side, this is a worthwhile reference.
other differences
There are many details in the APP that are different from the Web, here are a few points
debug solution
People who have developed H5 should be familiar with vconsole
. There is also a component in RN vconsole
for debugging, printing console, viewing requests, displaying various information, etc.
I also packaged an RN vconsole
plugin before: react-native-vconsole , which combines the advantages of multiple plugins
Action on physical keys
A unique feature on Android machines, he is a physical key
The user can directly click the physical key to go back. When returning to the most home page, a prompt needs to be displayed 再按一次退出
This requires a special adaptation to it:
BackHandler.addEventListener('hardwareBackPress', this.handleBackPress)
handleBackPress = () => {
if (//如果是第一个页面) {
const timestamp = new Date().valueOf()
if (timestamp - firstClick > 2000) {
firstClick = timestamp
ToastAndroid.show('再按一次退出', ToastAndroid.SHORT)
return true // 返回 true,意思是阻止默认操作
}
}
return false
}
Immersive status bar
There will be a scene like the status bar on the mobile phone, which is a very visual function
As you can see in the above figure, in the display of the signal and the battery, this part is the status bar in RN. We use this API to control:
<StatusBar barStyle="dark-content" backgroundColor="#ecf0f1" />
Of course, in order to adapt to various situations (in the APP, the status bar needs to be modified when the page enters, leaves, and other small functions change), sometimes some pages need a transparent status bar, and some special settings are also required.
Many times this component is not used directly, and needs to be packaged to adapt to most pages
version change
There are several versions in RN that are big breaking changes
- 0.59-0.60 upgrade
There are a lot of breaking changes directly in these two versions
The biggest change on the iOS side is that the package has become CocoaPods (already mentioned above)
This makes our package dependencies also need corresponding upgrades (more than 50% of package upgrades are expected), so the scope of impact is basically the entire project
On the Android side, the way of link has changed, and the other is the modification of the configuration of build.gradle
, settings.gradle
, AndroidX
Here is an introduction to the official upgrade tool: https://react-native-community.github.io/upgrade-helper/
He can compare the corresponding versions and display the changes in them
- 0.68 upgrade
The other is the upgrade from 0.67 to 0.68. In this version change, RN has made four adjustments:
- JavaScript Interface (JSI) - Updates for Communication
- Fabric - new rendering system
- Turbo Modules - Enhancements to Native modules
- CodeGen - Static Type Checker
Because this is a very low-level modification, it may cause changes to all existing components, and the scope of impact almost covers the global
new architecture
Here we will talk about what exactly is the update in 0.68
JavaScript Interface (JSI)
The original architecture I have mentioned above, some problems with him:
At present, RN uses Bridge Module
communication (which also requires data conversion and decoding), and the messages sent are asynchronous in nature, that is to say, if it is an operation with high immediacy, such as dragging and dropping, there will be errors. frame situation
In the new architecture, Bridge will be replaced by a module called JavaScript Interface, which is a lightweight general-purpose layer written in C++, which can be used by JavaScript Engine to execute directly or call native.
principle
In JSI, Native methods are exposed to JS through C++ Host Objects, and JS can hold references to these objects and use these references to directly call the corresponding methods.
A simple example is
This is similar to how JS code in the web can hold a reference to any DOM element and call methods on it:
const container = document.createElement(‘div’);
If you have experience with electron
, the original communication mode is the same as the communication between the main process and the rendering process in electron
Fabric
In the old architecture, the RN layout was asynchronous, which resulted in layout "jitter" when rendering nested RN views in the host view.
The new architecture, like JSI, adopts a cross-platform solution and shares the core C++ implementation.
The simple explanation is the UI version of JSI.
Of course there are some other advantages:
- With the ability to multi-prioritize and synchronize events, renderers can prioritize user interactions to ensure their actions are processed in a timely manner.
- The React Suspense integration allows you to write request data code in React more intuitively.
- Allows you to use React Concurrent interruptible rendering in RN.
- Easier to implement server-side rendering for RN.
Turbo Modules
In the previous architecture all Native Modules used by JS (such as bluetooth, geolocation, file storage, etc.) had to be initialized before the app was opened, which meant that even if the user didn't need a certain module, it still had to be at startup to initialize.
Turbo Modules are basically enhancements to these old Native modules, as mentioned earlier, now JS will be able to hold references to these modules, so the JS code can only load the corresponding modules when needed, which can significantly improve the Shorten the startup time of RN applications .
CodeGen
Codegen is mainly a static type checker used to ensure that JS code and C++ JSI can communicate normally . By using typed JS as a reference source, CodeGen will define interfaces that can be used by Turbo modules and Fabric. In addition, Codegen will be used during construction. Generate Native code to reduce runtime overhead.
skia
Now RN has also learned the Flutter
skia
rendering of ---95d165c38d33b3809903bb81804b109f---, but it is still in the stage of alpha release
这是一个值得期待的方向, 目前该库支持Image
、 Text
、 Shader
、 Effects
、 Shapes
, Animations
and other operations
shortcoming
At present, the disadvantages of RN:
- The problem of the old library The current RN ecological environment is really good, but there are also many old warehouses, which are not only compatible with the RN version, but also need customization and lack of maintenance for various business needs, and cannot be repaired in time if there are issues
- performance
The performance of RN is indeed much better than webview, but it is also worse than native. In very complex scenarios, native pages/components need to be used - controls
RN currently uses the antd version of the component library the most. It can support many scenarios, but it also lacks personnel maintenance. - Compatible with a lot of RN upgrade issues mentioned above, in fact, RN has not yet reached the official version
1.0.0
, so many of his APIs will have break changes
Summarize
There are other problems in the article that are not explained in detail in the article, such as Android packaging and signatures, iOS listing, commonly used code and image optimization methods, font solutions,
The startup screen, the problem of the long list, etc., but these are also the details, and the comparison of the main body is basically mentioned.
In general, the current situation of RN is still very good, and the competition with flutter
is not worthwhile in the future, as a front-end to expand the direction of the mobile terminal RN
is the best choice
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。