Author: Zhang Weidong

0.33 history

In March 2017, in order to solve the performance and user experience problems of the mall, the cloud music technology team formed a four-person ReactNative development team: I am responsible for RN front-end development, android and iOS developers are responsible for embedding RN Native SDK in cloud music App, and a Java developer is responsible for platform deployment.

After the mall RN application went online, other teams expressed interest in trying, but at that time there was no scaffolding for RN project development, project creation was carried out through original copy, lack of ForWeb support, and RN preloading was only connected to the iOS side.

For various reasons, the development efficiency of RN is low. The musician business was originally interested in using RN to develop new applications, but changed to H5 in the middle of development.

From March 2017 to September 2019, the RN version was always 0.33, with half of the core development team lost, no maintenance of the deployment platform, lack of scaffolding and forWeb support for project development, and a total of 2.5 RN applications (mall, musician and three-way speaker) were online.

Stirring history

Time rolls on and new technologies emerge. Two and a half years is like a lifetime for front-end development. If nothing goes wrong, RN will lie in the dust of history. This embarrassing situation, until the member of the cashier arrival rate optimization project was broken.

The member cashier page is the following picture, which is the cloud music member purchase page, the importance is self-evident. This page started as an H5 page developed for React server rendering.

In order to enable users to purchase members more smoothly and improve user experience and arrival rate, the whole technical team adopted web general optimization technology combined with cloud music’s own technical facilities and spent a month to optimize the H5 page, increasing the arrival rate from 72% to 89%, an increase of 17 percentage points. The comparison with competing products is as follows (in seconds).

Arrival rate calculation formula = cash desk visible buried point/client click buried point

Although the optimization results are encouraging, there are several problems:

  1. The arrival rate target is not achieved. The original technical team set at least 90% of the above, missing by one percentage point.
  2. Poor ROI. H5 optimization took nearly a month to develop the front and back end with a lot of manpower. If we optimize other pages, the automation degree of the current scheme is low, and a lot of manual operation is still needed.
  3. The arrival rate of 0.33 RN is 93%. We have counted the arrival rate of mall RN version without any optimization, easily breaking 90.

There are three options in front of the team:

  1. More resources were invested in H5 page optimization, and more than 90% of the tasks were completed. However, such a scheme costs a lot of manpower and resources, and is not useful for optimizing other pages. It is a one-shot deal.
  2. Reset the checkout page on RN version 0.33. This would have met the goal, but the RN infrastructure would still be three years old.
  3. Complete RN infrastructure, upgrade to the latest version 0.6, realize the three-terminal scheme, and build a complete RN development system. On this basis, the cashier desk was reset based on version 0.6, and RN’s entire technology stack was upgraded with this project. Although this scheme has great benefits, it has a long time span, great difficulties and high complexity.

After intense discussion and painful decisions, the team decided to aim higher than just achieving the arrival rate goal, but to rebuild the entire RN technology system to pave the way for future development and solve the performance and experience problems of the entire front-end development once and for all.

Automatic deployment

Old deployment platform

The original RN deployment platform does not implement automatic deployment. To publish an RN application, you need to do the following

Executing compatibility Scripts

In order to support earlier versions such as iOS8, you need to manually modify the local node_modules source code.

    sed -i -e 's/function normalizePrefix(moduleName: string)/const normalizePrefix = function(moduleName: string)/g' ./node_modules/react-native/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js

    sed -i -e 's/function normalizePrefix(moduleName: string)/const normalizePrefix = function(moduleName: string)/g' ./node_modules/react-native/Libraries/Utilities/UIManager.js

    sed -i -e 's/function handleError(e, isFatal)/var handleError = function(e, isFatal)/g' ./node_modules/react-native/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js

Copy the code
Executing the packaging script

Execute release.test.sh (test) and release.sh (online) locally. The release script calls the iOS and Android packaging scripts, and then prints out the corresponding bundles.

Since both bundles have the same name, they are prone to mis-uploads and are carefully uploaded.

Upload and publish platform

Fill in the relevant information here and click Publish.

It can be seen that the above three steps have the risk of local pollution, and the operation is tedious, so it is easy to miss steps and fill in mistakes.

Automatic deployment Process

In view of the above manual deployment defects, we reorganize and design the entire automatic deployment process

Git clone -> Dependent installation -> Automatic script execution -> Compression -> Upload file server -> Save version information -> PublishCopy the code

Then a new RN deployment platform was developed, replacing Java with Node

The new RN deployment platform automatically handles compatibility, packaging, uploading, and publishing, supports multiple environments, and completes the entire process with one-click deployment.

Dual-end preloading

RN loading process

  • The APP starts the RN container, which requests the JSBundle from the server, and then performs a preliminary rendering.
  • After the RN page is initialized, send a request to the server for dynamic data to do the rest of the rendering logic

As you can see from the figure above, JSBundle requests are a performance bottleneck in the entire process. If you load the JSBundle in advance (triggered during App initialization) and then open the RN application, the App will directly load the resource bundle locally, greatly improving user experience and performance.

RN Offline package platform

Based on the above reasons, we designed RN offline package service platform to deliver JSBundle. Offline package service is closely related to build and deployment. We integrated the two platforms and automatically generated offline package during the build and deployment phase to reduce the deployment work of developers.

Below is the flowchart of RN automatic deployment platform and offline package service platform

The main process is as follows:

  1. The RN automatic deployment platform first builds the full package, uploads it to the CDN, and then notifies the offline package service platform
  2. After receiving the full packet information, the offline packet service platform uses the DIFF algorithm to calculate the travelling packet, store the relevant information, and publish the differential packet.
  3. When the APP starts, it accesses the offline package service. According to the returned information, it can read the local cache or fetch the corresponding full package or differential package remotely.

0.33 upgrade 0.6

The upgrade consists of two parts: RN Native SDK upgrade and RN application upgrade.

RN Native SDK refers to rN-related Native code (iOS and Android source code) integrated in cloud music App. Since 0.33 and 0.6 are not compatible at the same time, we adopt a maintenance-only policy for the old version.

RN applications refer to business applications such as shopping malls and speakers, and can also be equivalent to Jsbundles. App upgrade must be completed before SDK upgrade, otherwise 0.6 SDK will load 0.3 App, resulting in App crash. Therefore, all applications must be upgraded at the same time

Upgrade Problems

Depend on the problem

RN 0.3 uses the React 15.3 version and RN 0.6 uses 16.8. In addition to React dependencies, there are other dependencies that need to be upgraded. We created a scaffold based on the comparison of version differences provided by the authorities, read the information in package.json, compare one by one, and then modify the corresponding version.

Waste components

RN0.6 removed two components: Listview and Navigator-ios.

In this case, if we were to rewrite with a new component such as FlatList, we would not only have to understand the original business logic, but also modify the source code and retest it. So in this case, the team’s solution was to leave the existing code unchanged and extract the corresponding components from older versions. Finally, we released @Music/Rn-deprecated -navigator-ios and @Music/Rn-deprecated – ListView

Grammar is compatible with

RN syntax is not only written differently on 0.6 and 0.33, it is also not backward compatible. As a result, the 0.33 JSBundle running on the 0.6 RN Native SDK will crash directly, as illustrated in the background below.

In 0.33, an Image was used to contain a View for the background Image. In 0.6, it was changed to ImageBackground with different properties.

It is not clear how much of the syntax needs to be compatible with changes other than the background diagram syntax. In the face of such unclear scope and tight time for change, manual method is not only inefficient but also uncontrollable. So we took an automated approach and launched mrN-Codemod, the industry’s first RN Codemod framework

Its main process is as follows:

  1. Use the framework to read 0.33 source code first
  2. Convert the 0.33 source code into an AST tree.
  3. Perform operations on the 0.33 AST tree to convert it into the 0.6 AST tree.
  4. Regenerate the 0.6 AST tree source code.

The framework deals with 12 translation rules

Once the framework is complete, all RN applications are upgraded in one day, not only ensuring accuracy, reducing labor costs and time, but also providing extensions for future upgrades.

Three side solution

After the above upgrade was completed, the team began to invest in the research of the 3-terminal solution, which was mainly investigated in three ways: direct transformation, bridge mode, and underlying construction.

Direct conversion

RN and React are just renderer-level syntax differences, so if you can translate RN’s syntax directly into React syntax, you can run RN on the browser.

For example, convert RN’s View to React’s div, RN’s click event onPress to React’s onClick, etc.

The disadvantages of this scheme are:

  1. It’s too much work. The inside of the RNView.Text.ImageThere are many basic components.
  2. There is no one-to-one correspondence. Such asViewThere’s one in thereonStartShouldSetResponderThe React method can’t find the corresponding event.

The bridge model

For RN applications, first find a tripartite framework that supports ForWeb, and then convert RN DSL to a DSL of a third-party framework to achieve the ultimate goal.

Taro and ReactXP are representative in this regard.

Taro implemented his own DSL based on the RN specification, customizing functions and events.

Actxp three-terminal support was very good, but there were so few components that it had to be abandoned.

The underlying construct

According to the definition of RN elements and components, the whole RN API is implemented from the bottom up with Web-related features. This is the React-native WEB. This scheme is also the mainstream mode of the industry.

We have encapsulated and extended this library, added unsupported components, fixed some bugs, and formed @music/ React-native -web-suffix.

New development process

On the basis of the three-terminal solution, we developed rN-CLI scaffolding, RN-util common tool library, RN-Template project initialization template and other supporting tools, forming a complete set of RN development infrastructure. The current new development process is as follows

Rn-cli scaffolding is called when initialized. Rn-template is built with android, ios, and Web development containers and some common engineering configurations, combining RN-util (request processing, environment determination, common protocol) and a three-end component library.

RN reconstruction results of cashier desk

After the above efforts, the cashier desk has been reconstructed in VERSION 0.6 of RN, and the arrival rate has increased from 89% of H5 (optimized) to 99%.

The status quo

As the RN version improves and the infrastructure improves, more and more front-end developers are adopting the RN stack in their new projects.

Currently, more than 10 RN applications have been launched, such as:

The future planning

At present, RN technology has become the key development direction of the big front end, and there is a special person to take charge of it. The subsequent specific planning focuses on performance, efficiency and monitoring, aiming to build the first echelon in the industry.

There are several projects under way

Native RPC

The main purpose of this project is to connect RN bridge and JS Bridge, so that a set of data communication mechanism can support both RN and Web.

The previous bridge had two main problems:

  1. Inconsistent usage. You need to write two sets of syntax to support RN and Web.
  2. Inconsistent support. There are protocols that Web does not have and vice versa.

Therefore, in view of the above situation, the big front end unified the APIS at both ends and reconstructed the underlying protocol to support the above functions. Here is an example.

// Check whether net.nefetch is supported,
mnb.checkSupport({
    module: 'net'.method: 'nefetch'
}).then(res= >{})/* Manually add method */
mnb.addMethod({
    schema: 'page.info'.name: 'getPageInfo'
});

*/ is called after /* is added
mnb.getPageInfo().then((result) = > {
    // ...
}).catch((e) = > {
    // ...
});

Copy the code

RN and the Web are written the same way, so developers no longer have to worry about compatibility.

RN unpacking

RN apps perform well on most mainstream devices, but lag on some low-end Android devices. In order to solve this problem, the special unpacking project was launched, which was mainly divided into two parts.

  1. Unpacking. Split the current complete JSBundle into base packages and business packages and load them separately.
  2. Container preloading. Preheating the RN container at App startup can greatly reduce container startup time and speed up loading.

other

In addition to the above special RN market monitoring, RN resource package directional delivery, document specifications and other special is in full swing.

conclusion

Are you curious about the real experience of RN in cloud Music App? If so, please upgrade the version of Cloud music App to the latest version for experience.

This article is published from netease Cloud Music big front end team, the article is prohibited to be reproduced in any form without authorization. Grp.music – Fe (at) Corp.Netease.com We recruit front-end, iOS and Android all year long. If you are ready to change your job and you like cloud music, join us!