In the field of small program technology, there are several enigmas: WECHAT’s WXS, Alipay’s SJS, Baidu’s Filter.

Many developers don’t understand why these language scripting wheels were created, and many don’t even know they exist.

They were created to solve performance problems on several platforms, both large and small, but they were designed to be difficult to use and the documentation was vague.

Uni-app supports compiling WXS, SJS and Filter into these three small program platforms, and implements WXS parsing in APP and H5. Why do these things? It’s also for performance.

The SwiperAction component in the Uni-UI library, for example, is a list item swiping to the left to pull out several pressing linkage menu buttons. This smooth hand-to-hand animation is realized by the WXS mechanism.

Why did wechat create WXS

WXS (WeiXin Script) is a set of scripting language created by wechat. Its official statement is: “WXS is a different language from JavaScript and has its own syntax, which is not consistent with JavaScript”.

So why did wechat break away from JavaScript and create a separate language? This should start from the low-level logic of the micro channel small program (running environment).

The running environment of small programs is divided into logical layer and view layer, which are managed by two threads respectively, among which:

  • The WXML template and WXSS styles work in the view layer, and the interface is rendered using a WebView
  • JavaScript code works at the logical level, running in JsCore or V8

The applet provides a data transfer and event system between the view layer and the logical layer. This separation has obvious benefits:

  • The logic is separated from the view, and even if the business logic computation is very busy, it does not block the rendering and user interaction on the view layer

But there’s also a clear downside:

  • The WEBView layer cannot run JS, and the logical layer JS cannot directly modify the page DOM, data update and event system can only rely on inter-thread communication, but the cost of cross-thread communication is very high, especially in the scenario that requires frequent communication

What are the scenarios that require frequent communication? The most common example is when the user is constantly interacting, touching, scrolling, etc. Let’s take the slide menu as an example. Suppose that A element is slid on the page and B element is required to follow the move. The response process of A touchmove operation is as follows:

  1. Touchmove events are passed from the Webview layer to the logical layer, and will be transferred by the wechat client (Native) in the middle
  2. The logical layer processes the Touchmove event, calculates the position to be moved, and then passes it to the view layer through setData. In the middle, the wechat client (Native) will also do the transit

A touchmove response needs to go through two complete back and forth communication among view layer, Native layer and logical layer, which is time-consuming and costly, and the user interaction will be delayed.

In addition to scrolling and dragging interactions, formatting data in a for loop causes frequent communication between the logical layer and the view layer.

In fact, this kind of communication loss problem has a long history in the industry. React Native and WEEX both have similar problems. Weex provides Bindingx to solve them.

But for small programs, these kinds of problems are easier to solve. Because in fact, the WebView, the view layer, does have a JS environment, but it was not open to developers in the past.

If js in the view layer directly handles the scrolling or dragging interaction, directly handles the data format, can avoid a lot of communication loss.

But for small program platform, a large number of open WebView JS writing, contrary to its original intention, such as developers will directly operate the DOM, affecting performance experience. So the applet platform proposes a new specification that limits the ability of javascript to run in webViews. This is the origin of WXS, SJS, filter.

Essentially, WXS, SJS, and Filter are restricted js that run in the WebView layer. It didn’t really invent a new language.

WXS features and application scenarios

WXS has the following features:

  • WXS is JS that can be run in the WebView layer
  • WXS cannot directly modify service data, only the current component can be setclassandstyle, or format the data. To modify the data at the logical layer, pass the parameters to the logical layer via callMethod
  • WXS is restricted JavaScript that can perform simple logical operations
  • WXS can listen for Touch events and handle scroll and drag interactions

Therefore, the application scenarios of WXS can be obtained, which mainly include:

  • Scenarios where users interact frequently and only need to change component styles (such as layout positions) without changing data content, such as slide menus, index lists, scrolling gradiens, and so on
  • Data formatting, such as text, date formatting, or internationalization. Filters that implement the Vue framework can be simulated with WXS. Here is an example of capitalizing the first letter with WXS:
<wxs module="m1"// capitalize = capitalizefunction(value) {
    if(! value)return ' '
    value = value.toString()
    return value.charAt(0).toUpperCase() + value.slice(1)
  }
  module.exports = {
    capitalize: capitalize
  }
</wxs>
<view class="content">
  <view class="text-area"> <! --> <text class= "" --> <text class=""title">{{m1.capitalize(title)}}</text>
  </view>
</view>
Copy the code

How does Uni-app support WXS

Uni-app follows the Vue single file Component (SFC) specification. Components/styles/scripts are written in a.vue file, but wechat applet is multi-file separated (WXML/WXSS/JS/JSON), so the main work on wechat is to extend the Vue-template-compiler. Template /style/script nodes are parses and correctly generated into the corresponding WXML/WXSS /js file. The detailed compilation work is as follows:

Tips – 1: about<wxs>Label refactoring into<script lang="wxs">Introduction:

Because the < WXS > tag in the. Vue file and the embedded WXS code are not available in the mainstream front-end development tools (VScode /HBuilderX, etc.), syntax hint, code highlighting, and formatting are not available.

Tips-2: In view of Vue’s custom tag specification, we recommend that the<wxs>(<script lang="wxs">) andtemplatePeers to write

The detailed work of the compiler’s parsing extension is not detailed here, but the sample code generated by WXS is given to give you an intuitive understanding:

createFilterTag (filterTag, {
    content,
    attrs
  }) {
    content = content.trim()
    if(content) {// write WXS code directly inside the < WXS > tagreturn` <${filterTag} module="${attrs.module}">
        ${content}
        </${filterTag}>`
    } else if(attrs.src) {// connect to the.wxs filereturn` <${filterTag} src="${attrs.src}" module="${attrs.module}"></${filterTag}> `}}Copy the code

In the case that the compilation is correct, the wechat small program will correctly parse and execute the WXS script when running, and the framework Runtime does not need to intervene.

Examples of implementation based on WXS performance improvement experience

The following GIF shows an example of the SwipeAction component implemented with THE help of WXS. Swiping to the left of a list item pulls up a couple of pinched menu buttons, which are natural for hand and rebound animations.

Here is a simple implementation of the main ideas:

  1. Reference the WXS file in vUE and bind the Touch event
<template>
  <view class="uni-swipe_content"> <! -- Slidable menu item container, bound to touch event --> <view :data-position="pos" class="move-hock"
      @touchstart="swipe.touchstart" @touchmove="swipe.touchmove" @touchend="swipe.touchend" @change="change">
      <view class="uni-swipe_box">
        <slot />
      </view>
      <view class="uni-swipe_button-group move-hock"> <! -- After sliding, the right extruding linkage menu button --> < View V-for ="(item,index) in options" :data-button="btn" :key="index"  class="button-hock">
        {{ item.text }}
        </view>
      </view>
    </view>
  </view>
</template>
<script module="swipe" lang="wxs" src="./index.wxs"></script>
Copy the code
  1. In the WXS file, handle the Touch event logic and move the element position through translateX
functionTouchstart (e, ins) {var pageX = e.pouches [0].pagex; . }functiontouchmove(e, ownerInstance) { var instance = e.instance; var pageX = e.touches[0].pageX; Var x = math.max (-instance.getstate ().position[1].width, math.min ((value), 0)); Instance.setstyle ({transform:'translateX(' + x + 'px)'}) / / cycle var btnIns = ownerInstance extrusion type linkage on the right side menu. SelectAllComponents ('.button-hock');
  for(var i = 0; i < btnIns.length; i++) { ... BtnIns [I].setstyle ({transform:'translateX(' + (arr[i - 1] + value * (arr[i - 1] / position[1].width)) + 'px)'})... }}functiontouchend(e, ownerInstance) { var instance = e.instance; Var state = instance.getstate () // Move (state.left, -40, instance, ownerInstance)}Copy the code

See Github for the full source code for this example

In this code, responding to gestures and moving menus is done directly at the view level. And without the traditional WXS writing, the implementation of this function will be difficult.

  • First, the view layer receives touch events and passes them to the logical layer.
  • Js in the logical layer responds to touch events to judge the movement distance;
  • The view layer is notified to update the location of interface elements.

In the continuous dragging process, the view layer and the logical layer communicate with each other constantly, and can not be smoothly followed by the hand.

While we understand how WXS works, to be honest, WXS is pretty hard to use, and to this day, most developers still don’t use it. It is more appropriate for some framework authors to encapsulate it. The Uni-APP provides the Uni-UI component library, which does just that, by referring to the Uni UI swiperAction component in the same way as the standard Vue component, you get a smooth scrolling menu.

More platform compatibility

Uni-app is also a small program engine on the app side. In order to achieve smooth dragging on the app side, it is also implemented and compatible with WXS.

In fact, there is no communication breakdown between the logical layer and the view layer in H5 platform, but for the sake of platform compatibility, Uni-app has also implemented WXS mechanism in H5 terminal.

In this way, the WXS code can be simultaneously run in the APP side, H5 side and wechat small program side in uni-App.

The maturity of Filter Filter of Baidu miniprogram and SJS of Alipay miniprogram is still relatively low. At present, they can only handle basic data format filtering and cannot respond to interactive events such as Touch.

As for headlines and QQ applets, wXS-like mechanisms are not yet supported.

We look forward to seeing other small program platforms complete this important feature as soon as possible to improve the experience.

At present, Uni-app also supports the Filter Filter of Baidu small program and SJS of Alipay small program independently written. These two scripts cannot cross multiple terminals and only support their own platforms. The uni-app compiler will compile and distribute the WXS/Filter/SJS scripts according to the target platform, as shown below. The sample code must be compiled conditional

<! -- App/H5/ wechat small program platform call WXS script --> <script module="utils" lang="wxs" src="./utils.wxs"></script> <! -- Baidu small program platform call filter.js script --> <script module="utils" lang="filter" src="./utils.filter.js"></script> <! -- Alipay small program platform call SJS script --> <script module="utils" lang="sjs" src="./utils.sjs"></script>
Copy the code

subsequent

Using JS running in the view layer to solve communication congestion, many people may not realize. I hope this article will help you to solve the riddle of WXS.

In fact, small program performance and experience optimization, there is still a lot of space. The DCloud team has been working in this area for six years and is aware of both the advantages of the small program technology architecture and the current problems. We will continue to share these problems and solutions to contribute to the development of the small program industry.

This article covers the Uni-UI swiperAction component, the code is open source at github.com/dcloudio/un… , uni-App framework code is open source at github.com/dcloudio/un… You are welcome to star or submit pr.