Weex Practice

It has also been a year since the Shangzhuangdaren store has been connected to weex. During this period, some articles have been published one after another:

"Android" Detailed and comprehensive access process based on vue2.0Weex (Android perspective)

"Front-end" weex page parameters

"Big front-end" in weex, native initiative to send events to JS solution implementation

Weex three-terminal implementation of Pager component (ViewPager) - Ben Ren Notes

Record the points that need special attention in the process of team weex practice

Here is a detailed summary, hoping to bring you some reference. Our team is also relatively small, the magnitude of the app is not large, and there are many things that are not good enough, and I hope God will give me some advice.

1. What is Weex

Weex is a set of simple and easy-to-use cross-platform development solutions that can build high-performance and scalable native applications with web development experience. In order to achieve this, Weex cooperates with Vue, uses Vue as the upper framework, and follows the W3C standard implementation With a unified JSEngine and DOM API, you can even use other frameworks to drive Weex to create three-terminal consistent native applications.

The preface quotes the definition of Weex's official website , and we have actually experienced these in the process of practice. Here are a few keywords extracted:

image

Students who have not been in contact with weex, if you want to see the effect first, you can visit the online to edit and browse, and download the playground playground on the App side to scan the code to browse the effect.

image

It can be seen that Weex can use Vue to write an app page like a web page through a DSL designed by itself. The entire page is divided into three sections, template, style, , scriptand draws on the mature MVVM idea.

As will be mentioned later, in theory, it is also possible to horizontally support the use of React, angular and other frameworks to write pages. Ali's open-source Rax is based on the React standard and supports rendering on Weex. For details, see the previous question and answer on Zhihu How to treat Ali's open-source Rax framework?

Playground is integrated Weex SDK, and after scanning the code, it is compiled JS Bundle, and then parsed through the JS Framework layer, output in Json format Visual Dom, and then JS-Native Bridgerendered into a Native interface through , and Js-Native event delivery through Bridge. The following is the architecture diagram given by the official website:

image

Through breakpoint debugging, you can see that the rendering instructions passed by JSFramework to the SDK are like this, and the SDK will render the corresponding Native components according to different types and parameters.

image

In traditional App, Native UI can directly obtain Device Power, while in Weex App, Native UI and Device Power are connected through JavaScript, as shown in the figure (picture from weex official website):

image

Before starting to access, you need to know about the page structure of Weex. For details, you can check the Weex page structure of Weex official website . For the convenience of reading, the following direct quotation:

Weex page structure

Interface display, logic processing, device capability use, life cycle management and other parts.

Dom model

Weex pages manage the interface in a way similar to HTML DOM. First, the page will be decomposed into a DOM tree, and each DOM node represents a relatively independent unit of native view. Then different view units are combined together through a tree structure to form a complete page.

components

Weex supports content-based components such as text, image, and video, as well as container-based components such as div, list, and scroller, as well as various special components such as slider, input, textarea, and switch. The interface of Weex is constructed by these components in the form of DOM tree.

layout system

The components in the Weex page will be arranged according to certain layout specifications. We provide three layout models in CSS: box model, flexbox and absolute/relative/fixed/adsorbed layout.

Function

Weex provides a very rich system function API, including pop-up storage, network, navigation, pop-up dialog and toast, etc. Developers can import and call these client-side function APIs by obtaining a native module on the Weex page.

The life cycle

Each Weex page has its own life cycle, and the page will go through the whole process from the beginning of creation to the last destruction. This is through the creation and destruction of Weex pages, and is defined and implemented by SDK in routing.

Weex has good scalability. It can expand the network, pictures, storage, UT, components, interfaces, etc. according to its own App and business needs. Even if the components provided by weex have problems, they can be directly rewritten and replaced.

image

For the access of a new technology, we will first consider the advantages and disadvantages of this technology, and what benefits it can bring to the team and business; then consider the cost of access, including the learning cost of team members, the cost of modifying the project, and the time. Cost; development experience, performance monitoring, disaster recovery, etc. After considering these, OK, we started to decide to access Weex.

image

2. The Daren store accesses Weex

Daren Store is currently a relatively small application, with 46 pages in one year. At present, it is relatively stable as a whole, and all subsequent pages will also be developed using weex.

image

Because the benefits Weex brings to us are obvious:

  • 3 people/day -> 1 person/day
  • Get rid of App update restrictions to a large extent
  • Native experience

In the process of access, we have done a lot of things in various aspects, including scaffolding, configuration distribution, jump rules, relative addresses, preloading, downgrading, error monitoring, building component libraries, page parameters, and so on. The process is described in detail below. If you have a better method, you are very welcome to discuss and exchange.

(1) Front end

The first thing to do is to build a Weex project, which can be regarded as a front-end project. Weex also provides scaffolding tools.

The scaffolding family bucket recommended by weex:

  • weex-toolkit: Used to initialize the project, compile, run, and debug all tools.
  • weexpack: It is used to package JSBundle, which is actually the packaging of Webpack.
  • playground: An App on the shelves, this can be used to display the actual page on the mobile phone in real time by scanning the code.
  • code snippets: This is an online playground.
  • weex devtools: It is a debugging tool for weex front-end and native development engineers.
  • weex-loader: A loader for Webpack, for Android and iOS platforms, for compiling single-file components in .vue format

Daren Store did not use the scaffolding provided by weex, but our front-end classmates defined a project structure suitable for our business. The following is part of the Weex project structure of Daren Store. Each page has a folder, which contains html, js, vue: html文件: h5 page of access to weex js文件: entry file compiled by vue文件webpack: edit page of weex

image

The following is an example of the development environment, so the imported js does not have a version number, and there will be a version number in the path of the official environment

In the HTML example , /dist/weex.js is introduced weex-vue-renderand extended, including registering modules and registering new custom components. weex-vue-renderIt can be understood as the SDK of weex in H5. See HTML Extensions for details

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
  </head>
  <body>
    <div id="weex"></div>
	<!-- entry -->
	<script src="//assets.showjoy.net/joyf2e/vendor/weex-extend/dist/weex.js" type="text/javascript"></script>
	<script src="./register-weex.min.js" type="text/javascript"></script>
  </body>
</html>

The Js example #weex is in the corresponding html, <div id="weex"></div>and vue will hang on this div after rendering.

import weexComponent from './register-weex.vue';
weexComponent.el = '#weex';
export default new Vue(weexComponent);

Vue example

<template>
  <div class="wrapper">
  <div>
</template>
<style scoped>
  .wrapper {
    background-color: #fff;
    flex: 1;
  }
</style>
<script>
</script>

When building, two sets of webpackConfig are defined, which are used to compile JS for h5 and Native respectively. The reason why we need to compile separately is due to the requirements of weex. The following is from Weex's official website . We have implemented remote builds on Jenkins.

Compilation environment differences

To use Vue.js in Weex, the running platforms you need to pay attention to are Android and iOS in addition to the Web, and there are some differences in the development and compilation environment. There are two different ways to compile Vue project source files into object files for web and native platforms:

  • For the web platform, like normal Vue 2.X projects, you can use any officially recommended way to compile source files, such as Webpack + vue-loader or Browserify + vueify.
  • For Android and iOS platforms, we provide the weex-loader tool to support compiling single-file components in .vue format; that is, currently only Webpack + weex-loader can be used to generate native js bundles.

image

(2) Native access

Please directly refer to the official website to integrate Weex into existing applications , SDK dependencies, initialization, and rendering have been explained.

In the final analysis, the final rendering result is returned View. In theory, the view can be placed anywhere on the page according to business requirements.我们达人店,都是整个页面的形式来引入weex。

On the Android side, we put weex access into a custom WeexFragment. In addition, create a new WeexActivity and reference WeexFragment. This makes it more flexible to use.

On the iOS side, we put weex access into a custom WeexViewController.

(3) Jump rules

When Native renders the weex page, it needs to pass in the constructed js bundle, that is, a js file. However, no matter whether it is the daily writing method of Native or the customary method of the front end, it will not directly jump to a js file. Therefore, considering that it conforms to the daily writing method of the front end, when jumping, jump to the url uniformly, as shown in the following figure:

image

Whether it is weex, native, or webview, the jumps are all urls, and then match is performed according to certain rules. According to the match result, it is decided whether to use weex, native or webview to open.

  • To achieve the jump in weex, native, and webview are all urls, two points need to be done here:
    • 1. The jump needs to call the unified openUrl, the a tag href in the weex can directly write the target url, and then intercept the jump of the a tag on the Native side;
    • 2. The jump in the webview is intercepted, and each url must be matched with the rules
  • Define the rules, a built-in copy of the App, and can be dynamically issued
    • 1. The corresponding relationship between the url and the original native page, the page can be defined according to the router design in the original App.
    • 2. The correspondence between url and weex js, hideTitleBar: whether to hide the native titlebar; v: support the minimum App version, if not, downgrade; page: the page name, as the local preloaded file name; h5: h5 url; url: js path; md5: md5 of js file, used for integrity check

Example of the correspondence between url and Native page

		 [
			    {
			        "page":"chat",
			        "url":"(.*)//shop.m.showjoy.net/shop/chat\?type=1",
			        "v":"1.7.0"
			    },
			    {
			        "page":"main",
			        "url":"(.*)//shop.m.showjoy.net/shop/seller_home",
			        "v":"1.12.0"
			    }
	]

Example of correspondence between url and weex page

[
	{
	"hideTitleBar": "",
	"v": "1.7.0",
	"page": "order",
	"h5": "http://shop.m.showjoy.com/u/trade.html",
	"url": "http://cdn1.showjoy.com/assets/f2e/showjoy-assets/shop-weex-m/0.8.1/order-list-weex/order-list-weex.weex.min.js",
	"md5": "8b3268ef136291f2e9b8bd776e625c6b"
	},
	{
	"hideTitleBar": "",
	"v": "1.7.0",
	"page": "shoporder",
	"h5": "http://shop.m.showjoy.com/user/tradePage",
	"url": "http://cdn1.showjoy.com/assets/f2e/showjoy-assets/shop-weex-m/0.1.1/shop-order-weex/shop-order-weex.weex.min.js",
	"md5": "ca818a24588509bfe083cd4b99855841"
	}
]

(4) Configuration platform

For the configuration of jump rules, we have made our own configuration platform, providing different configurations for full, pre-release and offline. parameter:

  • appType: 1 for android 2 for iOS
  • preTest: true means pre-issued false means full volume
  • appVersion: The version number of the app

The platform will deliver the js page configuration that the current App supports rendering according to the three parameters.

image

(5) Support relative addresses

According to the usual front-end writing method, the jump and a label are basically relative addresses, so there is no need to do special processing for offline and online environments. as follows:

image

When we started to intervene, the version was probably around 0.8. At that time, relative addresses were not supported by default, and we had already started to do it ourselves. Relative addresses are supported by default since weex sdk 0.9.4, but through testing and source code viewing, the host it takes is the host of the js bundle, as shown in the figure:

image

And we put the js bundle on the cdn, the domain name of the daily page is shop.m.showjoy.com, the two are inconsistent, so on the Native side, we rewritten URIAdapter(Android) and WXURLRewriteProtocol(iOS), and processed the url, If it is a relative address, plus the daily h5 page host, the request is the same. This supports relative addresses. Andoird

//这里还可以配置其他的adapter,比如image,storage等
WXSDKEngine.initialize(application,
                new InitConfig.Builder()
                        .setURIAdapter(new SHCustomURIAdapter())
                        .build());

iOS

[WXSDKEngine registerHandler:[WXSJNetworkDefaultlmpl new] withProtocol:@protocol(WXURLRewriteProtocol)];

When implementing, rewrite the rewrite interface, we will configure different hosts according to offline, online, pre-delivery and other environments, and also support Native protocols, such as: sms://, weixin://dl/privacy

PS : The jump of the A tag, the implementation of the Native SDK is to call the openURL interface of the Module "event". However, there is no Module registered for "event" by default, so you need to register the event yourself, or re-implement the a tag yourself. Processing of a tag jump in sdk

image

Custom event module.

image

(6) Preloading scheme

As shown in the figure, the package is captured during local development. Although the loaded js bundle is not large, the duration is also very short. But in order to make the speed even further, we still do a preloading scheme.

image

The scheme is designed as follows:

  • 1) After each update of the configuration file, traverse, check the md5 of the pagename.js file
  • 2) If there is a file consistent with md5 locally, skip it, otherwise download it
  • 3) After the download is complete, the save format is pagename.js. If it already exists, it will be overwritten. Check md5 to ensure the integrity of the file:
    • If the same, record the last modification time of the file;
    • If it is different, delete the downloaded file, download it again, and repeat the verification process.
  • 4) Every time the specified page is opened:
    • First check whether there is a corresponding page file locally
      • If it does not exist, use the remote url in the configuration directly
      • If it exists, check whether the modification time of the record is consistent with the last modification time of the file (this is for the purpose 防篡改of not directly calculating md5 for verification, considering that the calculation of md5 takes time)
        • Load it up
        • If it is inconsistent, use the remote url in the configuration

(7) Native-JS communication

1. JS calls Native
  • Weex provides Module extension interface, developers can register Module by themselves, and Module defines the interface;image
2. Native calls JS
  • The Module interface can set a Callback. After the interface implementation is processed, the Callback can be called directly to call back JS.

  • WXSDKInstance.fireEvent is at the element level, fireEvent is a member function of instance, and elementRef needs to be passed.

    image

  • WXSDKInstance.fireGlobalEventCallback is at page level and needs to pass instanceID

    image

(8) Error monitoring

*Native side can be processed through the onException method in the interface IWXRenderListener, including render error, js exception, network error, etc.

  • Weex layer, custom loge interface to implement error monitoring

(9) Page parameters

About page reference, our team Nanyang classmates wrote an article (Weex page reference) [https://juejin.im/post/5992db27518825244249e2db], for the convenience of reading, I will repeat it here.

1. Forward parameters: x.com/a.html jumps to x.com/b.html?age=12 When native rendering, in addition to the incoming JS Bundle, there are also options parameters, we put the parameters behind the url All are stored in options, and then passed to the weex page.

[_instance renderWithURL:[NSURL URLWithString:mstrURL] options:[self SHWeexOptionsWithH5URL:mstrH5URL withURL:mstrURL] data:nil];

This parameter can be obtained when writing weex weex.config.age.

In order to obtain the uniformity of parameters, the same is true for H5 pages. When opening a url, first get the parameters behind the url and store them in window.weex.config.

for (let key in urlParamObj) {
  window.weex.config[key] = encodeURIComponent(urlParamObj[key]);
}

2. Reverse parameter transfer: x.com/b.html returns to x.com/a.html, and brings back the parameter age=2. This is to achieve a function similar to onActivityResult in Android, and the parameter can be returned to the previous one page. To achieve such a function, the implementation of iOS Native only needs to add a Delegate.

To achieve this effect in weex, there is no method that can be used directly. The following is the solution we currently take.

  • First define the Module, add the setResult interface, and then call weex. The parameter is in the form of kv. The implementation of the interface is to store the data locally first;

    image

  • Go back to the previous page, when resume/willappear, get the stored kv, and pass the data to the weex page through fireGlobalEventCallback. , and remove the data.

    image

  • Monitor and process on the weex page

    image

(10) Downgrade plan

The so-called downgrade means that the rendering of the current new page fails, or the current App version is not new enough to support the new page, so the h5 page will be accessed. Here we distinguish two cases:

  • 1. Rendering failure: Consistently jump to the h5 page
  • 2. Version control:
    • New page: downgrade to access the h5 page if the App version that cannot support the new page
    • Modification of the old page: App versions that cannot support the new page will access the old pageimage

(11) Screen adaptation

Screen adaptation has always been an unavoidable topic in mobile development. In the world of Weex, a default screen size is defined to adapt to various screen sizes of iOS and Android. The weex framework has done adaptation work for different screens at the bottom layer. The specific calculation formula is:实际高宽 = 代码高宽 * (屏幕宽度 / 750)

image

At present, the visual draft we designed is 375, and we only need to get the value x2 when we develop it. There is a common place where the required calculation is encountered, which is described in detail here.

image

When using List and scroll, the height needs to be set, and this height needs to be calculated according to different pages. The above picture is an example. The first thing that comes to mind is: list height = screen height - titlebarHeight

Weex can get the height of the mobile phone screen in the form of $getConfig().env.deviceHeightsum $getConfig().env.deviceWidthbut in fact this is inaccurate, because the total height of Android Native is actually the full screen height available for display, not necessarily the height of the physical screen, because there is a status bar , virtual button bar, Smartbar and other additional display elements introduced by Android fragmentation, the actual full screen height is likely to be smaller than the physical screen height. So the real container height needs to be passed in from the outside,

List actual height = ContainerHeight - titleBar height literal * conversion ratio ratio conversion ratio ratio = this.$getConfig().env.deviceWidth / 750

ps: The incoming ContainerHeight is passed in through the Module interface

list的字面量高度 = list实际高度 / 转换比例ratio = ContainnerHeight / ratio - titleBar的高度字面量

In addition, weex is also provided this.$getConfig().env.scale, which can be used to calculate dp2px if necessary.

3. Some problems and solutions we encountered

1) Android's weex sdk 0.13.1, when the initial value of the input component is empty, the event @input cannot be triggered when pasting设置初始值,点击时,如果初始值与placeholder一致,就清空

2) Text is truncated in iOS9.x system在iOS9.x系统中不支持line-height,被强行绘制,存在兼容性问题,暂时不要使用font-size和line-height相同大小

3) Dynamic binding of classvue的写法 :class={'header': true} weex的写法 :class=“[true ? 'header' : '']"

4) Animation animation is invalid in H5 page of iOS 8 and below对于webkit不兼容的css样式(transform)进行兼容

5) iOS device elements cannot be arranged horizontally when the scroller scrolls horizontally需要给scroller设置样式 flex-deriction: row,这样可以确保三端显示一致。

6) Js Date conversion time, Android 8 hours differencedateConfigTimeZone(timeValue, offset) { const date = new Date(timeValue); // UTC时间 (1970-1-1至今毫秒数 + 本地时间与GMT分钟差) const utc = date.getTime() + (date.getTimezoneOffset() * 60 * 1000); // 返回 (UTC时间 + 时区差) return new Date(utc + (60 * 60 * 1000 * offset)); }

4. What we are still doing

(1) weex component library

After a year of practice, we have also accumulated some basic components and business components, such as description, import, example, preview, qrcode, etc. as shown in the figure.

image

Take a look at the directory structure of the spon-ui component library project.

|- spon-ui
||-- build
||-- docs
||-- examples
||-- packages
|||--- weex-field
||||---- index.js
||||---- field.vue
||||---- example.vue
||||---- readme.md
||||---- package.json
||-- src
  • Some script execution files are stored in the build for project debugging and publishing.
  • The script for document debugging is stored in docs, and a document debugging server is generated.
  • The scripts for component debugging are stored in examples, and a component debugging server is generated. (without storing component examples)
  • packages hold the actual components, along with their documentation and examples.
  • src holds the public methods that the component can use.

For details, please refer to our front-end classmate Nanyang's "big front-end" UI component engineering practice in Shang Zhuangdaren Store

(2) Others

  • Cookie support
  • HttpDNS access
  • Image supports cropping, webp
  • performance monitoring, doing
  • Incremental update, doing it

The above is our summary of the year, and I hope it can be a reference for you. Discussing the gaps in the communication is welcome.

Thanks to all members of the team, the above is the result of our joint efforts.

@Javin, Senior iOS, github , blog

@Li He, senior iOS, github

@Luyuan , senior Android, github , blog

@mickey, front-end goddess, welcome to follow Weibo

@南阳, the front-end god, welcome to follow Weibo , the output of technical articles is high,

@luffy, head of mobile, github , blog

Thanks for the help provided by the following great articles: (I have read a lot of articles, if not added, please let me know)

Weex official website

Weex github

Rax official website

NetEase Yanxuan App to experience Weex development

Weex layout engine powered by FlexBox algorithm

Those things that Weex events deliver

Ingenious JS Framework in Weex

The most complete weex step on the earth strategy - from a lot of practice and precipitation


Author: Shangzhuang Product Technology Journal Read
Link : https://juejin.im/post/5a2a730cf265da431f4afd35
Source: Nuggets The
copyright belongs to the author. For commercial reprints, please contact the author for authorization, and for non-commercial reprints, please indicate the source.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325350567&siteId=291194637