Start with the jsBridge functionality

H5 page is carried by WebView and needs to realize communication between JS and native. Common functions are shown in the figure below:



Such as:


// Open a new container to hold H5
this.state.jsBridge.openWebView({   
 'action': 'https://XXX.XXX.com'.'login': true
})Copy the code

/ / destroyed the webview this. State. JsBridge. QuitAction ()Copy the code

/ / control the client at the top of the back button - triggered the callback function enclosing state. JsBridge. HandleBackAction ("openCancelPayModal", window.openCancelPayModal, true);Copy the code

So the whole communication flow looks something like this



The client will inject the jsBridge object into the Window object, and any invocation of the jsBridge event method (such as obtaining the login state) will be intercepted and processed by the client-specific interceptor.

JsBrige communication model optimization

When js triggers a jsBridge object to trigger a method, it will actually go to the interceptor of the client and native response, this process is to send a message to the client. The client calls back the front-end callback and returns the data to the H5 page. Based on this message sending mechanism, the communication model can be further optimized.




Advantages:

1. The front-end and client side do not need to maintain much jsBridge method, only need to maintain the short chain of functions, such as:

// Open a new container and require the user to be logged in to this.state.jsbridge. emit({name:'page1Event',
    action: 'XXX/openWebView',
    globle: false,
    params: {
        login: true}})Copy the code

Action refers to the short chain of functions, and the EMIT method is the bridge for sending messages in general.

The function used to receive the returned message was passed as callback in the old communication model. The new communication model no longer requires tedious callback passing, but uses generic functions to receive, such as:

// The generic top-level method receives the client message window.onjsBridgeEvent =function (json) { console.log(json) }Copy the code

Ps: Globle is used to process global messages and is disabled by default to avoid performance waste. Enabling globle requires processing for page name names that require page event names to be unique (for example: Page A is configured in TAB, and page A can be opened again in other tabs. At this time, there are two pages of page A. If the event name of the page is the same, the global message will be processed by the two pages of PAGE A, but we only want the message to be placed on the top of the container to receive separately.


2. Meet more interaction scenarios



Webview3 sends a message to inform the client to destroy WebView2, so the communication model based on message sending can be implemented.

Currently open all webViews can receive client global messages, such as: logout, collective destruction and other functions of the realization.


Communication principle

JsBridge injection, client interceptor was mentioned earlier.

android

Android calls js code:

1. Pass the loadURL of the WebView


EvaluateJavascript via WebView

JsBridge injection and interceptor

1. Use addJavascriptInterface () in WebView to map objects


2. Intercept the URL via the WebViewClient shouldOverrideUrlLoading () callback


3. Use WebChromeClient onJsAlert(), onJsConfirm(), onJsPrompt () to call back and intercept JS dialog boxes Alert(), Confirm(), prompt () messages

ios

use
WebViewJavaScriptBridge

function setupWebViewJavascriptBridge(callback) {
	if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
	if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
	window.WVJBCallbacks = [callback];
	var WVJBIframe = document.createElement('iframe');
	WVJBIframe.style.display = 'none';
	WVJBIframe.src = 'https://__bridge_loaded__';
	document.documentElement.appendChild(WVJBIframe);
	setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}Copy the code

To understand what this code does, click here

WebViewJavascriptBridge is a bridge object provided by ios, but it is not provided at the beginning of the container layer initialization, so the code continues down, Until WVJBCallbacks (which store functions that need to be called back) and wvjbScheme ://__BRIDGE_LOADED__ are executed.

Wvjbscheme ://__BRIDGE_LOADED__ the purpose of this protocol is to create a WebViewJavascriptBridge.

Line 127: github.com/marcuswesti…



At this point the JsBridge object is provided for front-end use.

Next is to invoke ios capabilities, such as client real-name authentication:

this.state.jsBridge.callHandler("realNameAuthentication");Copy the code

CallHandler is an object in jsBridge. The _doSend method under callHandler is used to notify the client for processing.







Messagingifame. SRC = CUSTOM_PROTOCOL_SCHEME + ‘://’ + QUEUE_HAS_MESSAGE; To:

messagingIframe.src = https + ‘://’ + “__wvjb_queue_message__”; Here __wvjb_queue_message__ is used to trigger the ios interceptor for processing.

Essentially, it will still be intercepted by an interceptor, but ios UI WebView and WK WebView interceptors will be different:

The UI webview: shouldStartLoadWithRequest


WK webview: a decidePolicyForNavigationAction


Webview performance optimization

Webview rendering process



(from: Meituan technical team tech.meituan.com/2017/06/09/…).


From the process of user use, roughly as follows:

1. A new window opens

2. The screen is blank

3. The basic skeleton of the page is rendered but there is no data

4. Data acquisition is complete, and overall page rendering is completed

Part of the reason for this slowness is that a WebView does not load a URL the way a browser loads a URL; there is an initialization process for a Webview.

webview init



To improve the init time, a common practice is:

When the app starts, it initializes a hidden Webview waiting to be used. When the user clicks on the URL that needs to be loaded, the webView is directly used to load, thus reducing the initialization time of WebView init. The downside is extra memory overhead.


Webview cache usage

To speed up H5 loading, webView cache mode is used.

Take Android, for example:

LOAD_CACHE_ONLY: does not use network, only reads locally cached data,


LOAD_DEFAULT: cache-control determines whether to fetch data from the network.


LOAD_CACHE_NORMAL: has been deprecated in API level 17. Starting from API level 11, the LOAD_DEFAULT mode is used.


LOAD_NO_CACHE: does not use cache, only gets data from the network,


LOAD_CACHE_ELSE_NETWORK, as long as it is locally available, regardless of expiration, or no-cache, uses the data in the cache.


If a page’s cache-control is no-cache, under mode LOAD_DEFAULT, data will be fetched from the network anyway. If there is no network, an error page will appear. In LOAD_CACHE_ELSE_NETWORK mode, caching is used whenever there is a local cache, regardless of whether there is a network. It is obtained from the network only when there is no local cache. If a page’s cache-control is max-age=60, locally cached data is used in both modes.

To improve the rendering speed of H5 in WebView, just front-end support is not enough, but also need the client to use a reasonable caching mode, click here for details.

Wechat applet communication model

Rendering and logic are not executed in the same environment. The logic layer is in the pure JS environment, and the rendering layer is handed over to WebView, so WXML and WXSS are in the rendering layer. The communication of these two threads will be transferred through wechat client, and the network request sent by the logic layer is also forwarded through Native.



Understanding the Render layer

On Android, a native method is injected into the Window object of the WebView, which is eventually encapsulated into a compatibility layer such as WeiXinJSBridge, which mainly provides two methods: invoke and on. The developer inserts a native component. Typically, the component is inserted into the DOM tree at runtime, and the client interface is called to tell the client where to render a native interface. When subsequent developers update component properties, they also invoke the update interface provided by the client to update parts of the native interface.

Understanding logical layer

Js execution environment provided by wechat, because the control is customized, so this sandbox environment can not have a browser interface, only provide JS execution environment.

Js execution environment: the built-in JavaScriptCore framework is used in iOS, and the JsCore environment provided by Tencent X5 kernel is used in Android.

Why not use Web rendering?

If pure Web technology is used to render applets, performance problems are inevitable in complex business scenarios. Since both UI rendering and JS scripts are executed in a single thread, it is easy for JS logical tasks to preempt UI resources.


Reference for this article:

Meituan technical team: tech.meituan.com/2017/06/09/…

51 nb:mp.weixin.qq.com/s/bjkeh7gk-…

Tencent Bugly: blog.csdn.net/Tencent_Bug…