What problems are to be solved?

In order to combine the advantages of H5 and Native App in mobile application development, Hybrid application development is usually carried out in the form of Hybrid. JSBridge is used as a two-way communication channel between JS and Native, and JS can invoke Native capabilities through JSBridge.

In the actual development, the front-end and client cooperation mode is usually directly called by the front-end after the client encapsulates the method and control UI. For the front-end code, it is cross-platform and cross-system. Multiple platforms only need to maintain a set of front-end code, and the online version is flexible and fast. However, when the business needs frequent iterations of the client and the app store review process is required, the speed of iteration advantage of the application is greatly reduced.

After iteration of client functions, it is necessary to do version control for these functions in front-end JS, because the old version of App in the hands of users does not have new functions of the client. Failure to do version control will lead to bugs, and with the increasing number of version iterations, version differentiation in JS will become more and more bloated. The same code can be filled with different versions of different apps, and the code becomes increasingly unmaintainable.

To analyze problems

In the case that H5 and Native have iterated many versions, there is no way to completely reconstruct Native using schemes such as RN and Weex, which cost too much. However, their ideas can be used for reference.

Taking RN as an example, RN uses ReactJS to execute JS logic code, describe and manage VirtualDom, and translates ReactJS into drawing instructions to Native for drawing through Bridge, and Native feeds back user events received by Native to ReactJS through Bridge.

Can we do it with JSBridge? The key to using JS to generate Native controls is that JS should pass drawing instructions to Native, and Native will feed back user events to JS. With JSBridge, we can complete the data communication between the front-end and the client. JSON is used as the data carrier, the front-end is to translate the front-end code into drawing instructions, and the user event feedback is notified to the front-end by Native through JSBridge.The advantage of this scheme is that the cost is low, the front-end and client side change code are not big, can achieve the basic client control drawing, user event callback, with a certain client control hot update ability. Disadvantages of JSBridge data transfer is not as efficient as JSCore direct parsing JS execution, in some frequently triggered change scenarios, powerless (for example, the client control follows the web page scroll, through JS to listen to the scroll and then transfer the modified value to the client)

To implement the idea

Next, I will introduce the implementation of this idea from the perspective of the front end

Data carrier

JSON, as a data carrier, can be defined as follows: Target describes the element of the operation, action describes the operation on the current object, and params describes the parameters to be carried by the current operation:

[{"target": "xxx"."action": "init"."params": {
            "key": "value",}}]Copy the code

A series of instructions for Native control operation are put in JSON array, and Native takes out the instructions and executes them after receiving them.

target

Several basic elements are defined: UICanvas, UIButton, UIInput, UIImage, UIIput, which can be understood as H5 div, button, SPAN, img, input. Complex elements can be pieced together from simple elements.

action

An action is an action on a target.

action instructions
init Initialize a base element
set Sets the properties of a base element
get Gets an attribute of a base element
delloc Destroy a base element

params

Params is the parameter required for the current operation, such as init, where params needs to pass the coordinates and width of the control.

JSON generated

Obviously, writing the above JSON array directly in JS is unreliable, difficult to read and maintain. You need an SDK tool to translate the front-end code into A JSON array so that you can write the code that generates the client-side controls in a natural object-oriented form on the front end.

For example, the following json creates a native rectangular canvas named View and adds it to the WebView coordinate (0, 0)

[{"target": "UICanvas"."action": "init"."params": {
            "name": "view"."width": 100."height": 100,}}, {"target": "view"."action": "addToWebview"."params": {}}]Copy the code

Expected OOP writing:

const view = new UICanvas({
    name: 'view'.width: 100.height: 100,
})
view.addToWebview()
view.getCode() // Get the generated JSON array, ready to pass to the client via JSBridge
Copy the code

The front-end SDK needs to implement the following two functions:

  1. Implements the same class, abstract class, interface, and method of the class as the client, and has the same inheritance and implementation structure. The main function of the method of the component class is to generate JSON.
  2. Implement a method decorator, collector, decorates each class method, automatically collects the returned JSON array into the SDK when called, and finally gives the JSON through the tail call to empty the SDK array.

For example, the addToWebview method mentioned earlier is implemented in the SDK as follows:

    /** * Add a view to the webView (which will cover the webView) */
    @collector(a)// decorator to collect the return value into the SDK's JSON array
    public addToWebView(): WebKitCode {
        return {
            target: this.instanceName, // Call instance name
            action: 'addToWebView',}}Copy the code

Perform:

view.addToWebview()
const arr = view.getCode() // [{"target": "view", "action": "addToWebview", "params": {}}]
Copy the code

OK, so you can write client-side control generation rules in the front end in object-oriented form, pass to Native via JSBridge, native parse JSON array, use real UICanvas to draw the view control on the WebView.

This is just a basic rectangle to create. On top of this rectangle you can add child views, buttons, images, text, click events, animations, and styles. Theoretically any client control can be implemented.

In practical application, I used this scheme to realize the bottom bar of a native article page. Each button can be directly bound to the events of the client, or the client can notify the front end to execute corresponding methods by itself through JSBridge, realizing the complete autonomy of the front end to the bottom bar of the client, and solving the problems of iteration cycle and version control.

extension

This scheme can also be applied to native controls. For some app controls that are frequently iterated, the client can directly preload the SDK and implementation template and generate JSON on a Shadow WebView. When invoking the control, the control can be directly generated through JSON and has a certain degree of hot update capability.

conclusion

This solution is a low-cost solution summed up after being troubled by the client version release cycle and version control for a long time. There will certainly be some shortcomings at the beginning. If you have your own ideas and thoughts, please share them in the comments section.

My name is Suhangdev, welcome to communicate with me about front-end related topics, email [email protected], if the article is helpful to you, please like and support oh, thank you!