The background,

1. Why Weex

Under the environment of rapid development of the company, App update and iteration are rapid and frequent. The technical team can produce a medium-sized App in two weeks on average, but the App team only has 6 people (3 for iOS and 3 for Android). On the premise of ensuring efficiency and quality, Relying solely on Native abilities is a stumbling process — we urgently need to improve team efficiency, hoping that one person can complete the workload of 2 to 3 people.

First, access to Web pages, one page ADAPTS to both ends;

Second, cross-platform development frameworks such as Weex, React Native, Flutter and Chameleon are selected. The mainstream frameworks are compared as follows:

Compare the content of

React Native

Flutter

Weex

To fit the difficulty

general

general

easy

Access to features

Suitable for developing whole App

Suitable for developing whole App

Fit for a single page

Maintenance difficulty

general

general

easy

Development of language

React

Dart

Vue, Rax

Frame size

The heavier

heavy

The lighter

The Bundle size

larger

Don’t need

smaller

community

rich

Since the new show

imperfect

Support terminal

Android, iOS,

Android, iOS, Web, etc

Android, iOS, Web

engine

JSCore, V8

Flutter Engine

JSCore, V8

After comparison, Weex was selected for the following reasons:

  1. Weex has a low cost, and single-page support is more in line with project planning.
  1. Vue framework, fit the big front-end environment of the team;
  1. Weex undertook taobao, Feizhu and other apps a large number of pages, giving the outside world sufficient confidence.

2. Weex with the Web

Although Web pages are easy to use and have lower maintenance costs, compared with Weex, the size of the Web package of the same page is larger than that of Weex. As a result, Web pages cannot provide pure Native experience, and the page loading speed is difficult to maximize, and the blank screen may occur on some devices. Weex has the following advantages that a team in pursuit of perfection would love.

Basic principles of Weex

Weex supports two front-end frameworks, Vue and Rax. The front-end team uses Vue for daily development. To reduce the cost of getting started, we choose Vue framework for Weex development. The Weex working process is as follows:

Weex WE file ————– front-end (we source)
↓ (Conversion) —————— Front end (construction process)
JS Bundle —————– front-end (JS Bundle code)
↓ (Deployment) —————— Server or local
JS bundle on server or local —- server or local
↓ (Compilation) —————— Client (JS engine)
Virtual DOM tree ————— client (Weex JS Framework)
↓ (Rendering) —————— Client (rendering engine)
Native view ————— client (rendering engine)
From the website

In addition to the front-end page preparation, Weex can be divided into

DOM
Render
JSBridge
DOM
JSBundle
Render
Render
Component

<text>

TextComponent. JSBridge
JS
Native
The Module to complete

Iii. Client system architecture

Based on Native and with the help of front-end, the architecture evolves into a large front-end. The overall structure is shown in the following figure. We hope that App, as a terminal, can provide container capabilities, do a good job in the underlying services, and perfectly integrate Weex, Web and other cross-platform technologies.

4. Practice and solutions

The following lists some important and common problems and their solutions throughout the Weex page life cycle.

  1. Page to page communication
  1. routing

Weex navigator only supports simple online resources, but does not support loading of local files, and cannot meet dynamic presentation mode and complex parameter transfer. Therefore, it needs to implement a complete set of page hopping rules by itself.

In a lot of use

Web, Weex

unified
convenience
The decoupling
Can be configured to change
routing

Scheme :/ Web /open? BundleUrl = XXX // Open the Weex page Scheme :/ Weex /open? BundleUrl = XXX // Open native page Scheme :/native/open? Url = XXX // Note: This form of routing can not only complete the intra-app hop service, but also perfectly support inter-app hopCopy the code

Example of launching a page redirect in Weex:

navigator.openUrl({
  url: 'scheme://weex/open',
  params: {
    bundleUrl: '/dist/about.js',
    name: 'Here are the parameters for the next page'},}) // Note: The next page only needs to declare an attribute in data with the same name as the parameter to receive the specific parameter.Copy the code

  1. Reverse the value

When we consider reverse value transmission, there are two scenarios. One is that the Weex page reversely transmits values to the Weex page, and the other is that the Native page reversely transmits values to the Weex page. We can use Weex based W3C specification

BroadcastChannel

  • When the page jumps
    WXModuleKeepAliveCallback

    Pass in the next page and execute the callback when appropriate. This is easy for iOS clients to do, but because Android needs to serialize the parameters into memory as it passes values between pages, and then deserialize them out of memory on the corresponding page, a new object is generated and the callback cannot be done.

  • We tried to draw lessons from BroadcastChannel implementation, through the Weex project global JSContext object to trigger broadcast to complete the reverse value transmission, but in the end nothing.

We chose to use it

fireGlobalEvent

1.Weex added event listener const globalEvent = weex.requiremodule ('globalEvent');
globalEvent.addEventListener("eventName", (e) => { // ... }); 2. The native page send events weexInstance. FireGlobalEventCallback ("eventName", params); // Android


[weexInstance fireGlobalEvent:seventName params:params]; // iOSCopy the code

The weexInstance in the code can be understood as an instance object of a page, and the process needs to get the last one on the page that sends the listening

Weex
weexInstance
—-

needListen

navigator.openUrl({
  url: 'scheme://weex/open',
  params: {
    bundleUrl: '/dist/about.js',
    needListen: true,}})Copy the code

2. Configure the page configuration file

Install the Mounted navigation bar on the Weex page. If the Weex page is mounted, add the following code to the Mounted method:

created () {
    navigator.setTitle('Navigation bar title')
    navigator.setItems([{
      title: 'button',})}Copy the code

This unengineered and standardized approach causes great interference in later maintenance, cross-project migration, and architecture upgrade.

We optimized and upgraded the Weex page by referring to the design ideas of small programs. We added a CONFIGURATION file in JSON format for each Weex page that requires special configuration. The configuration file includes the configuration of the navigation bar, the page-level configuration, and the jump configuration, and made the configuration engineering and standardized.

For example, if I add a configuration file to the About page, the json file has the following class:

{
    "navigationBarTitle": "Navigation bar title"."navigationItems": [{
        "title": "Button"}}]Copy the code

The about.js and about.json files are in the same directory:

Then a complete page opening steps are as follows:

After the extension, the configuration file becomes richer. Previously troublesome jump processing and pop-up boxes can be realized through the configuration file. The following are some common attributes:

1. Some attributes

attribute

type

The default value

describe

backgroundColor

HexColor

Configuration of the same Project

Window background color

navigationBarBackgroundColor

HexColor

Configuration of the same Project

Background color of navigation bar

navigationBarHidden

Bool

false

Hide navigation

navigationBarTitle

String



Navigation bar title

navigationBarTitleColor

HexColor

Configuration of the same Project

Navigation bar title color

2. IOS special form

To Present the page on an iOS client, you can set the following attributes:

present

Bool

false

The Present page

presentWithNavigationBar

Bool

false

Present page with a navigation bar

transition

Map

false

Render as a transition and specify an animation expression for the transition (default background alpha from 0 to 1)

Priority: Transition > presentWithNavigationBar > present

In Transition, you need to define an animation expression, and Native needs to parse the expression and perform animation according to the expression.

3. Set navigation buttons

navigationItems

Array

[]

Contains an array of button styles

Use fireEvent to complete the callback of button events.

Button style description:

{
     "type": "TEXT", / /"TEXT"."IMG"."TEXT_IMG"Will pass"title": "Title"// Text header or"image": "Refresh"// Is the image address. The image address supports both local and network images"textColor": "FFFFFF", // Hexadecimal, default is white, can not be transmitted"backgroundColor": "", // hexadecimal, default transparent color, can not be transmitted"borderColor": "", // Hexadecimal, default no border, no transmission"borderWidth": 1, // Default no border, no transmission"cornerRadius": 1, // Default no rounded corners, can not pass"font": 16, // Default 16-point font, can not be transmitted"position": 0, // Default 0, no transmission, 0- left display, 1- right display"imagePosition": 0, // 0- picture on left, text on right, default, 1- picture on right, text on left, 2- Picture on top, text on bottom,Copy the code

4. Customize the navigation bar

For example, to meet the requirements of navigation bar segmentation:

navigationBarTitleComponent

String

There is no

Name of the corresponding custom Component

Component is implemented native and exposes apis to interact with Weex

3. Shadow handling

Weex is iOS friendly, but Android doesn’t show shadows. The documentation explicitly addresses this problem, but the Android SDK provides a way to do it. Maybe ali’s engineers tried to fix it, but it didn’t work out. The obvious point is that if the item in the list uses a shadow, the slide of the list leaves the shadow where it was originally drawn. Android students have been trying to solve this problem, but it hasn’t worked out as well. The final downgrading solution was to use images instead of shadows. Here’s Weex’s official note:

Currently, only iOS supports the box-shadow attribute, but Android does not support it. You can use images instead.
Only one shadow effect can be set for each element. Multiple shadows cannot be applied to an element at the same time.

4. Network request

Weex provides

Stream

Therefore, we provide our own network request module, Weex side calls the method provided by Native, and determines the request through parameters, some optional parameters:

parameter

type

mandatory

describe

path

String

is

Requested path

method

String

no

The request mode is’ GET ‘by default, and’ POST ‘and’ DELETE ‘are supported

params

Map

no

Request the required parameters

timeout

Number

no

Request timeout

customHost

String

no

Customize the Host of the request

callback

Function

is

The requested callback

Example request:

// 1. Obtain native Module const nativeStream = weex.requireModule('nativeStream') // 2. Set basic parameters const options = {path:'/....'Method:'POST',
  params: {
    id: '123'Nativestream. fetch(options, (res) => {if (res.code === 0) {
    succesCallback(res)
    return
  }
  failCallback(res)
}Copy the code

5. Image loading

The loading of the <image> tag image requires the client to provide a handler. Currently, it supports remote linking and packaging of the generated Bundle resources, but does not directly support album images and images generated by taking photos. Its Base64 support provides a way for us to display photo albums. The following figure shows the process of selecting, photographing, and displaying photos in Weex:

From the above figure, we can know that a simple picture display process is not simple, among which the most critical is the choice of the scheme in the fifth step. Uploading pictures first is the most convenient solution for programmers, but it affects user experience. Pictures should be uploaded when they need to be uploaded, rather than interfering with business due to technical gap.

Switching to Base64 can improve the user experience, but has a performance impact. On iOS, the time required to convert a 1M image to Base64 is more than 45ms, and the time consumed in steps 6 and 7 is about 30ms, which increases with the image size in multiples.

To sum up, we design a localization scheme to generate a unique ID for each image added, and Native is responsible for image storage and loading.

6. Refresh components

The

components provided by Weex are simple in form and have interaction bugs. Therefore, we implement a set of refresh components by ourselves. Properties are used to determine whether the display is refreshed or not, and corresponding interfaces are provided to realize the interaction between Weex and Native.

1. The attribute

attribute

type

mandatory

describe

showRefresh

Bool

no

Whether to add drop-down refresh

showLoading

Bool

no

Whether to add a pull-up refresh

refreshAtCreated

Bool

no

Whether to automatically refresh the display at the first time

2. The event

  • Refresh event: Triggered when

    , ,

    is pulled down to complete, this event from native callback to Weex.
  • Loading event: Triggered when

    , ,

    is pulled up, this event is called back to Weex from native.
<list ref="list"
      c
      :show-refresh="true"
      class="list"
      @refresh="refreshList"
      @loading="loadMoreList">
 
</list>Copy the code
  • BeginRefresh event: the start of the drop-down refresh, called by Weex.
  • BeginLoading event: starts a pull-up refresh, which is called by Weex.
  • EndRefresh event: End the drop-down refresh, called by Weex.
  • EndLoading event: Ends the pull-up. This event is called by Weex.
this.$refs.list.beginRefresh()
this.$refs.list.endRefresh()Copy the code

3. RefreshAtCreated properties

If you do not use this property, you need to manually invoke the refresh method in the Created or Mounted function to trigger the drop-down refresh. However, on some Android devices, a blank screen appears. Weex explains:

Unlike browsers, Weex’s rendering process is asynchronous, and the rendered results are all views in the native system, which cannot be directly accessed by javascript. Therefore, on Weex, the Mounted life cycle of a Vue is triggered when the virtual-dom (VNode in a Vue) of the current component is completed. In this case, the corresponding native view may not have been rendered.

7. Screenshots

Weex will generate a unique ID for each component when rendering. In JavaScript, ref is more intuitive. Although Weex does not have a real DOM, it still supports the use of REF. The specific approach is as follows:

// 1"poster"></div> // 2. Fetching this element is a Map const poster = this.$refs.poster // 3. Obtain the Map from the Map of saveViewShot({ref: poster. Ref}) // 4. Component // iOS WXComponent * Component = [weexInstance componentForRef:ref]; // Android WXComponent component = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(mWXSDKInstance.getInstanceId(), ref); // 5. Get the View and proceedCopy the code

8. Elegant popovers

This is a very simple popbox requirement where the view gets bigger and bigger and then it goes full screen. First, the Weex page layout starts from the bottom of the navigation bar by default. Second, the route hop mode does not support this popup mode. By default, the Weex page is pushed from right to left.

To implement the function of the popbox, we need four steps:

1. Native defines the PopView component

1. Set up the Weex page and layout the page based on PopView

2. Display the page in full screen and hide the navigation bar

3. Perform the animation

After the PopView component is defined natively, Weex pages can be laid out like this:

<template>
  <pop-view class="pop-view"</pop-view> </template>Copy the code

Combined with the configuration file proposed in point 3, we put the control of steps 2 and 3 into the configuration file, and finally write the configuration file as follows:

{
  navigationBarHidden: true// Hide the navigation bar transition: {property:'scale'Duration: 2, // Animation time, in seconds},// Transition display, and specify popView display animation}Copy the code

This is just the simplest example; more complex animations require client support.

B: Yes, Sir

The above summarizes the Weex access process, as well as the basic problems encountered in practice, shows that Weex in the team has been smooth and increasingly standardized, but more in-depth performance optimization, hot update, we need to continue to move forward, the following is the next article will cover the knowledge point:

  • Hot update
  • Resource preloading
  • Make the configuration file dynamic
  • Weex resource packaging is automatically added to the terminal warehouse

Add the official account of the Academy of Sciences

Mp.weixin.qq.com/s/LxdQ6Eq2R…