Directory:

1. Why use hot publishing;

2. Industry status quo;

3. Release the overall design scheme;

4. Online functions and data;

5. Problems encountered during use;

6. What needs to be done afterwards;

Why hot Releases

1. Real-time limitation

As a cross-border e-commerce App, Kaola was bound to be limited by policy provisions from the very beginning, which often resulted in the need for some real-time changes. At present, these real-time requirements must be solved through the direct release of the App version, which not only has a long release cycle, but also wastes time in the review of the application market, and the user upgrade rate is not high.

2. New functions depend on upgrades

When some new function scenarios are mentioned in product planning, they must be developed through a complete iterative process. Finally, users can use the new function by releasing a new version, and the development and test cycle is long. At the same time, users must rely on upgrades if they want to use the new features. The new features cannot be made available to users of older versions.

3. Bugs cannot be hotfixed

Some of the online logic problems and crashes that occur during mobile development due to poor thinking are usually solved by repackaging and releasing the app to the market, but there are now easier fixes. Dynamic solutions can also be used to better fix bugs through hot firing. Simple and efficient.

4. High cost of multi-terminal collaboration

At present, the whole mobile market is divided into Android and ios. When requirements are proposed, both android and ios developers will be notified to conduct requirements review and function iteration. In the process of requirement communication and implementation, various communication problems always occur, resulting in inconsistent requirements implementation effects. Through dynamic solutions, both ends can share the same set of code to solve their own logic, which can save a lot of manpower.

Second, the industry status quo

Two popular launch solutions are Facebook’s React Native and Alibaba’s Weex.

Comparison of the two schemes:

Similarities:

1. Both of them have the same idea: js is converted into Virtual-DOM and then mapped to the corresponding View component of Native;

2. Follow W3C standards to achieve a unified JSEngine and DOM API, which can develop native pages and applications in the way of Web (HTML+CSS+JS);

3. Can complete three-terminal rendering and dynamic delivery of function modules;

Difference:

React Native uses its own React, while WEEX uses Vue.

2.RN supports ios and Android platforms, and the Web side needs to be supported and compatible. Weex claims to support three terminals, but there are still many compatible tasks;

3.RN will package the basic parsing part and business logic together when packaging, so js files will be relatively large, while WEEX only packages the business part, and the specific parsing process is in SDK. So the bundle is going to be small;

Usage experience: We have investigated both of the two solutions, and found that RN has higher requirements in the writing process, which is not as fast as VUE. RN is more like a new language, which provides different components for different terminals. Weex prefers these tasks to be done by native, and the three terminals are the same in weeX pages. At that time, the performance of LIST component provided by RN was not very good, while the performance of RecyclerView provided by WEEX was much better. Therefore, weeX scheme is adopted for dynamic mobile terminal. In fact, the two solutions are implemented by virtual-DOM rendering. The following describes the principles of the WEEX solution.

Principles of WEEx:

The diagram above is the schematic diagram of WEEX. First, the service functions are implemented through the upper-layer DSL language. After the implementation is completed, the whole service logic is packaged into a jsBundle, which contains the implemented functions. And code that can be recognized by the underlying jsFramework.

Once we have jsBundle, we can put it in the background system, and that’s what we need for hot release.

The next layer is what THE SDK does. After getting the jsBundle, the SDK will parse it through JScore and convert it into a virtual DOM tree. Different ends parse the virtual DOM tree in their respective SDK and render it into components of their respective ends for page display. After understanding the functions and principles of weeX, the following describes our hot release application solutions.

Iii. Overall design of dynamic scheme

The functions of the overall dynamic scheme involve front-end, back-end and mobile terminals, and the functional requirements of the three terminals are realized. The specific structure is shown as follows.

1. Mind map of the whole process

It mainly includes three parts:

Weex layer, WEEX engineering is responsible for the writing, packaging and publishing of business pages;

In the background layer, the hot publishing background is responsible for configuring the corresponding function page and providing the App with the ability to detect updates and push and deliver update packages.

App layer, the app side is responsible for detecting updates, caching bundles, and rendering displayed policies;

Here’s a look at the overall hot release process:

At the beginning, I wrote the weeX code to realize the functional requirements. Then, I used Webpack to build jsBundle and published the packaged jsBundle to my own server. Currently, I use NDP platform and NGINX server to configure CDN rules on THE NDP platform. So each JS file will have a separate static resource address. This static address and page routing information will then be configured in our hot publishing background. Users can get hot page renderings while using the App. Of course, there are also two ways on the App side. One is that users actively open the page to trigger the update interface to pull new data, and the other is to push it to the App for background update after background release. Since our overall strategy is divided into three parts, the following details what each part does.

A. Web page development and deployment process

As A client developer myself, I did not know much about the front-end development process, so I took many detours in the development process.

In fact, the front end has been around for many years, many development tools are very good, and I am currently using WebPack for packaging and building in my project.

Because WEEX DSL selection is VUE, so the specific requirements page code is recommended to use VUE to write (encountered problems can refer to the official vUE document vuejs.org/index.html, but WEEX is in the client rendering, so some VUE Chinese and Russian functions can not be used.

The code is not the focus, but the configuration of webpack packaging. Currently, I have configured two packaging schemes in package.json. Distinguishes between development and production environments. Js files can be compressed and obfuscated in production environments.

Using Webpack, you can set up some common components at the entrance of the build file to reduce the import in the Vue code:

Const App = require("${relativePath}") // Vue.component('wrapperLayout', require("components/wrapper-layout.vue")) App.el = '#root' new Vue(App)Copy the code

We have configured a general page framework, including navigation bars and network request loading effects.

Set weex-loader to vue file build:

let weexConfig = getBaseConfig()
weexConfig.output.filename = 'weex/[name].js'
weexConfig.module.loaders[1].loaders.push('weex-loader')

module.exports = [weexConfig]
Copy the code

After the build is complete, the js file for the corresponding page will be generated. Unlike Java, these JS files contain all the introduced components and methods, so there is only one JS file per page, which can be quite large. So far, we have developed complex pages with a maximum of 2-300K.

After the package is completed, all JS files and resource files will be deployed on the Negix server through the construction platform, and associated with the CDN, so that the link of the CDN can be directly used when the page is set up.

B. Resource image processing process

Resource images now learned can use five ways: local, base64, CDN, iconfont, SVG. At present, we mainly use base64 and CDN, and iconFONT is the way of front-end active page.

2. Background interface and database design

A. Backstage database table structure design

The table structure parameters for storing bundle information in the background database are as follows:

BundleId, minSupportVersion, bundleVersion, bundleModule, fileDownloadUrl, loadType, desc, Person, Time

BundleId: unique identifier for the current page;

MinSupportVersion: Indicates the minimum App version supported by the current page.

BundleVersion: The distributed version of the current bundle;

BundleModule: the module to which the bundle belongs.

FileDownLoadUrl: the download address of the bundle;

LoadType: indicates the loading mode that can be used for the current bundle page. 1. 2: network check for updates, when this is loaded, use the latest;

Desc: specifies the description of the current bundle update.

Person: update;

Time: update and upload time.

The table structure in the database is:

bundleId minSupportVersion bundleVersion bundleModule fileDownloadUrl loadType desc person time
recommendDetail 3.9 1 seeding http://gala/3.9/recommend/recommenddetail.js 1 Updated the XXX, changeLog… Zhang SAN 2017-10-16

** bundleId and minSupportVersion are used as unique identifiers **; If one of the two changes, it’s a new piece of data

** Database operations have two cases: **

** 1. Native has no changes **

The content of a certain update does not depend on the changes of WeexSdk and Native, so all previous versions are supported. Then the background interface directly queries the current data in the database according to bundleId and appVersion, and updates the bundleVersion(plus one). Replace the fileDownloadUrl with the new one.

For example, the original database stored:

bundleId minSupportVersion bundleVersion bundleModule fileDownloadUrl loadType desc person time
recommendDetail 3.9 1 seeding http://gala/3.9/recommend/recommenddetail.js 1 Updated the XXX, changeLog… Zhang SAN 2017-10-16

Then update to:

bundleId minSupportVersion bundleVersion bundleModule fileDownloadUrl loadType desc person time
recommendDetail 3.9 2 seeding http://gala/3.9/recommend/recommenddetail.js 1 Updated the XXX, changeLog… Zhang SAN 2017-10-16

Only the file and version change, everything else remains the same; In this way, both versions 3.9 and 4.0 of the App can use the new features developed this time.

** 2. Native has been modified **

A previous version had a piece of data for the current page in the database. New version Only the latest version of the updated content can be used. If all previous versions are unavailable, a new data is inserted into the database.

For example, the original database stored:

bundleId minSupportVersion bundleVersion bundleModule fileDownloadUrl loadType desc person time
recommendDetail 3.9 1 seeding http://gala/3.9/recommend/recommenddetail.js 1 Updated the XXX, changeLog… Zhang SAN 2017-10-15

Then update to:

bundleId minSupportVersion bundleVersion bundleModule fileDownloadUrl loadType desc person time
recommendDetail 3.9 1 seeding http://gala/3.9/recommend/recommenddetail.js 1 Updated the XXX, changeLog… Zhang SAN 2017-10-15
recommendDetail 4.0 1 seeding http://gala/4.0/recommend/recommenddetail.js 1 Updated the XXX, changeLog… Zhang SAN 2017-10-16

After this update, there are two messages in the database for the bundleId for Shamedetail, the first for apps between version 3.9 and version 4.0 and the second for those after version 4.0.

B. Background interface design

Interface for detecting updates in APP:

RequestParams: bundleId, appVersion;

The background interface needs to query the maximum minSupportVersion data in the database based on bundleId and appVersion.

The response:

{" bundleId ":" recommendDetail ", "minSupportVersion" : 3.9, "bundleVersion" : 1, "FileDownloadUrl" : "http://gala/3.9/recommend/recommendDetail.js", "loadType" : 1}Copy the code

For example: 1. If the current App version is 3.9,

For the first case above, the backend would return me the latest bundleVersoin for 2 shamedetail

For the second case, the backend returned me the shamedetail. Js file available for version 3.9,

2. If the current App version is 4.0,

For the first case above, the background will return me with minSupportVersion 3.9,

For the second case, the backend returned me the system-system-available files for version 4.0.

C. Configure the background management system

3. Update the display policy on the App

A. Update the overall logical architecture

Through the hot sending background, we can get the Bundle information to be displayed according to the corresponding bundleId. So how does our native page know which bundleId to request and display? Let’s take a look at the strategy of our App side. This diagram shows the architecture of our entire App side, which is divided into two parts, one is the routing strategy, the other is the detection and update strategy.

Routing strategy

The weeX page is displayed and redirected based on the routing function. This means that each WEEx page has a unique URI. For example, if A button is clicked on page A of the App to redirect to page B, which is A WEEX page, A will pass the routing information of B to the Router, which will then resolve the routing information and send its corresponding bundleId to weexVersionManager. In the WEEX version manager, the bundle is displayed in the manager. If the jump logic appears on page B, the WEEX and Native bridge will transfer the routing information to the Router for the next jump.

Display update policy

The above part is the Bundle loading and update detection part. For details, see the following flow chart, which is mainly divided into two parts: one is display policy, the other is update detection policy. According to the previous process, route the corresponding bundleId of the page to the VersionManager. After getting the bundleId, the VersionManager will first check whether there is a cache available locally. If there is a cache, it will first take the cache to load. It will publish the latest bundle request in the background, and then decide whether to refresh the current page to display it after the request comes back. If the network fails, a network error message will be sent to the user. The part on the right is the process of detecting updates. The process of detecting updates is carried out in the background and does not affect the interaction of users in the foreground. At the beginning of the detection, it will check whether there is a new bundle available in the background. After receiving the returned data, it will determine whether the current bundle has been downloaded. If it has been downloaded, it indicates that the local bundle is the latest, and it will not do other things and will not affect the use of users. If the jsBundle has not been downloaded locally, the jsBundle needs to be updated and overwritten. Then the jsBundle is downloaded and cached. Based on the loadType set in the previous protocol rules, the loadType is different. As mentioned before, loadType can be divided into current loading and secondary loading. If it is second loading, the page will be refreshed directly; if it is second loading, the latest one will be used when the user enters the second time.

Iv. Online pages and data

In the Koala AndroidApp, weeX pages in the Koala App accounted for 10%. The current online function is grass community and small koala q&A most of the page. The diagram below:

Performance: The entire page can be rendered in less than 1 second. The js download duration is 100-200ms. Normal page rendering time is about 150-300ms

Five, some experience summary

9 images can be used in the IMG tag, but the resize property is set to stretch, as follows:

<img class="comment-reply-bg" src="local: //res/bg_comment_reply" resize="stretch"/>
Copy the code

2. About class style switch:

<div class="focus-common" :class="[focusStatus?'focused-container':'focus-container']" >
Copy the code

3. Style switch:

:style="{color: focusStatus? '#999999':'#8CAA5E'}"`
Copy the code

4. The parent component calls the child’s methods and data:

Ref (id) is set in the child component. In the parent component, ref can be used to obtain the corresponding child view and call the child view method:

Parent vue: < system-system-system-system-system-system.html"detailPage"></recommendDetailPage>
this.$refs.detailPage.setData(this.$refs.detailPage[0].recommendDetail)
Copy the code

5. Child callback to parent:

ShowGoBack (event) {this$emit('showgoback',event); }, // When the parent uses the child component, the method is declared in HTML and the method <bridgeWebview :loadUrl= is called in JS"url" class="webview_style" @showgoback="showGoBack"></bridgeWebview>

showGoBack(event) {
    console.log("event.canGoBack2:"+event.canGoBack);
},
Copy the code

6. Text display problem

The content in the text tag cannot be wrapped on a line, otherwise a line break will appear on the mobile phone. The second line in the following code displays two lines. Such as:

1. <text >hello world</text> 

2. <text >hello world
    </text>
Copy the code

6. What still needs to be done afterwards

1. Three-terminal construction to improve efficiency At present, our Kaola mobile terminal has also carried out further research and implementation on three-terminal universality. It took some time to build the underlying interfaces and components, as well as communicate, because the underlying support was different between ios and Android. After that, the main purpose is to improve the co-construction framework of the bottom layer, so that the business of the upper layer can be common in the three ends and improve the development efficiency.

2. Component WEEX hot release So far my weeX development is at the page level, and I will make some attempts at the component level in the future. And pull out these common components and pack them into NPM packages that can be used across multiple projects.