preface

The main development language of small programs is JavaScript, although there are similarities with web development but there are certain differences

  • The web development rendering thread and script thread are mutually exclusive, why does a long script run cause the page to become unresponsive
  • In applets, the logic layer and the rendering layer are separated, and the two programs run at the same time. The interface of rendering layer is rendered by WebView; The logical layer uses JSCore to run JavaScript code
  • Web development is mainly faced with browser and mobile browser WebView
  • The development of small programs is faced with the wechat client of iOS and Android, so the development needs to pay attention to the version number of wechat client and the basic library version number supported by the API of small programs

The differences between rendering non-native components and script execution environments are as follows

Runtime environment Logic layer Rendering layer
Android V8 Chromium Custom kernel
iOS JSCore WKWebView
Applets developer tools NWJS Chrome WebView

Applets host environment

In the preface, it is mentioned that the host environment of the small program is wechat client, so it can complete many functions that ordinary web pages cannot complete with the help of the ability provided by the host environment

Render layer and logic layer

First, let’s briefly understand the running environment of the small program. The running environment of small programs is divided into the rendering layer and the logical layer, in which WXML templates and WXSS styles work in the rendering layer, and JS scripts work in the logical layer.

The rendering layer and logic layer of the small program are managed by two threads respectively: the interface of the rendering layer uses WebView to render; The logic layer uses JsCore thread to run JS script. A small program has multiple interfaces, so there are multiple WebView threads in the rendering layer. The communication of the two threads will be transferred through the wechat client, and the network request sent by the logical layer will also be forwarded through the Native. The communication model of the small program is shown in the following figure.

View and logical communication

In multi-WebView mode, each WebView has a separate JSContext. How do views and logic communicate? The two-thread life cycle is shown in the figure below.

Contrast this with the browser two-threaded model

  • More secure, because wechat mini programs prevent developers from using some of the functions provided by some browsers, such as DOM manipulation, dynamic script execution and so on
  • Instead of waiting for the main browser thread to download and parse HTML, JS scripts will block, affecting view rendering and causing a blank screen
  • The disadvantage is that if the two threads communicate frequently, the operation setDate update view, especially serious performance consumption, such as drag, scroll, etc

The overall architecture

After the event operation on the View layer, the data will be transmitted to the Native system layer through WeixinJSBridge. The Native system layer decides whether to use Native processing and then passes it on to the logic layer for the user’s logical code processing. After processing, the logical layer sends the data back to the View layer through WeixinJSBridge. View renders updates the View, as shown below.

Compilation principle

The code run by the simulator of wechat opener tool is the page that can be seen only after local preprocessing and local compilation. The code run by the wechat client is extra compiled by the server. Code that recognizes and runs a small program only after compilation. Let’s take a look at the basic structure of the applets file

  • .wxmlPage structure
  • .wxssThe page style
  • .jsPage logic
  • .jsonPage configurations are based on the principle of convention over Configuration

Next, we open the small program developer tool, click wechat Developer Tool >> Debug >> Debug wechat developer tool in the upper left corner, see the following interface (official website component demo)

The rendering layer and the logic layer are two WebViews. The first corresponding WebView is the rendering layer. Each page has a WebView, while the logic layer has only one AppService.

And then let’s move on to what’s in a WebView? Open the WebView and find the iframe tag is empty, but we want to see what to do, open the Debug panel (Console) and type

The first step is to find all webViews
document.getElementsByTagName('webview')
// The second step is to find the first render layer page and open it with the developer command
document.getElementsByTagName('webview') [0].showDevTools(true.null)
Copy the code

At this point we will see the following window, this page is our render layer page structure.

Since you can see each render layer, you can certainly see the logic layer code, which you can type in the Developer tools consoledocumentThe following page is displayed

Next, let’s take a look at the basic library file used by wechat mini program. If you type openVendor() in the Developer tools console, you can bring up the app-related directory, which contains several important files

  • wccThe compiler takes care of thatwxmlCompiled intojsfile
  • wcscThe compiler takes care of thatwxssFile compiled intojsfile
  • xxx.wxvpkgIs different versions of the small program base library, mainly contains the small program base libraryWAServiceWAWebviewThis piece of follow-up analysis.

The role of WCC

1. Create a new file named Compiler.js and write the following code

const fs = require("fs");
const miniprogramCompiler = require("miniprogram-compiler");

const path = require("path");
let JsCompiler = miniprogramCompiler.wxmlToJs(path.join(__dirname));
let cssCompiler = miniprogramCompiler.wxssToJs(path.join(__dirname));
fs.writeFileSync("wxml.js", JsCompiler);
fs.writeFileSync("wxcss.js", cssCompiler);
Copy the code

Run NPM install miniprogram-compiler. 3. Run Node Compiler. js to generate two JS files WXML and WXCSS in the same directory

<view class="box">
  <text class="box-text">{{ text }}</text>
</view>
Copy the code

5. Create a new index. HTML file and import the file wxml.js

<script src="./wxml.js"></script>
<script>
  const res = $gwx("index.wxml");
  const virtualTree = res({
    text: 'the data data'
  });
  console.log(virtualTree);
</script>
Copy the code

Opening the index.html console in a browser outputs Virtual DOM-like objects

{
  "tag":"wx-page"."children": [{"tag":"wx-view"."attr": {"class":"box"},
    "children": [{"tag":"wx-text"."attr": {"class":"box-text" },
        "children": ["The data data"]."raw": {},"generics":{}
    }],
    "raw": {},"generics"] : {}}}Copy the code

What WCC does is:

  • Perform WCC compiler WXML to generate the relevant page registration code and record the attributes and values of the tag (generate JS files)
  • The file body is a $GWX () function that takes two argumentspath(page WXML path) andglobal(Top-level object)

The role of WCSC

  • WCSC compiles WXSS to get a JS file
  • Add dimension unit RPX conversion, which is adaptive to screen width
  • Provide the setCssToHead method to add the transformed CSS content to the header

xxx.wxvpkg

As mentioned above, if you type openVendor into the developer tool, you’ll see a lot of.wxvpkg files. This is the basic library for apet. It consists of two main parts: WAService and WAWebview

  • WAWebview: Applets view layer base library, provides view layer base capabilities
  • WAService: A small program logic layer foundation library that provides logic layer foundation capabilities

The version of the basic library of wechat small program is constantly updated. Currently, the highest version of my local library is 2.14.1.wxvpkg. We can use unwxapkg to decompress 2.14.1.wxvpkg. The decompressed directory is

├─ WaAutoService.js ├─ WaAutoWebView.js ├─ Wagamesubcontext.js ├─ WagamevConsole.html ├─ WagFXEmsc.js ├ ─ ─ WAGfxEmsc. Wasm ├ ─ ─ WAPageFrame. HTML ├ ─ ─ WAPerf. Js ├ ─ ─ WARemoteDebug. Js ├ ─ ─ WAService. Js ├ ─ ─ WAServiceMainContext. Js ├─ Wasourcemap.js ├─ WasubContext.js ├─ WavConsole.js ├─ WAVersion WAWidget. Js └ ─ ─ WAWorker. JsCopy the code

Ignoring the other files, let’s take a look at the source code overview of the two base files referenced by WebView: WAWebview and WAService

Among them, the most important parts of WAWebview are:

  • Foundation: Base module (publish and subscribe, communication bridge ready event)
  • WeixinJSBridge: Message communication module (JS and native communication) Webview and Service have the same set
  • exparser: component system module, which implements a set of custom component models, such as wX-View
  • __virtualDOM__: virtual Dom module
  • __webViewSDK__: WebView SDK module
  • Reporter: Log reporting module (exceptions and performance statistics)

Among them, the most important parts of WAService are:

  • Foundation: Basic module
  • WeixinJSBridge: Message communication module (JS and native communication) Webview and Service have the same set
  • WeixinNativeBuffer: native buffer
  • WeixinWorker: the Worker thread
  • JSContext: JS Engine Context
  • Protect: object protected by JS
  • __subContextEngine__: Provides methods such as App, Page, Component, Behavior, getApp, and getCurrentPages

Foundation module

The base module provides environment variables env, publish and subscribe EventEmitter, configuration/base library/communication bridge Ready events.

Exparser module

The component organization framework of wechat small program is built into the basic library of small programs, which provides basic support for various components of small programs. All components within the applets, both built-in and custom, are managed by the Exparser organization. Exparser’s component model is highly similar to ShadowDOM in the WebComponents standard. Exparser maintains the node tree information of the entire page, including node attributes, event bindings, etc. It is a simplified version of Shadow DOM implementation.

Virtual DOM module

Generates a WX-Element object, similar to virtual-dom

WeixinJSBridge module

Provides message communication mechanism between VIEW layer JS and Native and between view layer and logic layer, as shown in the following methods:

First render flow

With the body structure and functions above, we should have a general understanding of the applet, so let’s string them together to look at the first rendering process

  • Open the wechat developer tool
  • Click on the upper left corner to debug wechat developer tools
  • Debug panel inputdocument.getElementsByTagName('webview')[0].showDevTools(true)

The last labeled code in the figure above

var decodeName = decodeURI("./pages/index/index.wxml");
var generateFunc = $gwx(decodeName);
if (generateFunc) {
    var CE = (typeof __global === 'object')? (window.CustomEvent || __global.CustomEvent) : window.CustomEvent;
    document.dispatchEvent(new CE("generateFuncReady", {
        detail: {
            generateFunc: generateFunc
        }
    })) __global.timing.addPoint('PAGEFRAME_GENERATE_FUNC_READY'.Date.now())
} else {
    document.body.innerText = decodeName + " not found"console.error(decodeName + " not found")};Copy the code

So the initial rendering process is as follows

  • Use $GWX to create a virtual DOM-like node tree
  • Create a CustomEvent window.customevent (CE)
  • Dispatch custom event document.dispatchEvent
  • Listen for this event in WAWebview and notify the JS logical layer view via WeixinJSBridge that it is ready
  c = function() {
    setTimeout(function() {!function() {
            var e = arguments;
            r(function() {
              WeixinJSBridge.publish.apply(WeixinJSBridge, o(e))
            })
        }("GenerateFuncReady"}, {}),20)}document.addEventListener("generateFuncReady", c)
Copy the code
  • Finally, the JS logical layer gives the data to the Webview view layer for the first rendering

Communication principle

The communication between the logic layer and the rendering layer of the small program will be transferred by Native (wechat client), and the network request sent by the logic layer will also be forwarded by Native.

View layer components:

Some of the built-in components (map, video, etc.) take advantage of the capabilities provided by the client natively. How does that communicate? IOS uses the messageHandlers feature of WKWebView, while Android injects a native method into the Window object of WebView, which is encapsulated into a compatibility layer such as WeiXinJSBridge. Two main methods, invoke and on, are provided.

Logical layer interface:

The iOS platform injects a global native method into the JavaScripCore framework, while the Android side is consistent with the rendering layer. Whether the view layer (part of the component) or the logical layer, the developer is indirectly invoking the capabilities of the client’s native layer.

Write in the last

Finally, recommend a full set of TS tutorials. Recent TS in ascension, collect a set of very good tutorial, free to share with XDM www.yidengxuetang.com/pub-page/in…