0x1 What is WeexCore and why we have to adapt iOS SDK to WeexCore?

WeexCore is a common layer written in C++ which plays core role in bridging Javascript(VM) and platform views. It originates from Android Weex SDK and the initial purpose was to port codes from Java to C++ to improve performance. Later we added more and more functionality to it such as layout engine, JS engine with one interface supporting V8 and JavascriptCore and so on.

For iOS, before we adapt to WeexCore, two platforms share no codes. From render commands generated by VM to platform views managed by Objective-C codes. It takes high cost for synchronizing and updating features across platforms. It is a must for us to adapt iOS to WeexCore.

At the same time, we initiated Eagle framework project which separates page templates and logic codes. Eagle framework parses templates to view hierarchy much faster than Javascript execution which highly improves page display speed. For Eagle framework to be cross-platform we need WeexCore as the internal bridge.

At first stage, we import WeexCore to iOS making use of its RenderManager, RenderObjects, RenderActions and Layout Engine part. With these classes, we input raw DOM commands and get elements with parsed styles, attributes and frames after layout. The first stage refactoring finished before 2018 double 11 festival and run well.

In later stages, we will import more functionalities of WeexCore to iOS such as multi-threading model, JS engine interface and so on.

0x2 Architectures before and after importing WeexCore

Before importing WeexCore, we get render commands from Objective-C style JavascriptCore interfaces. The commands are not flattened such as:

  1. Data of component and its descendants are returned in one big structure. WXComponentManager takes the responsibility to recursively decompose the JSON data.
  2. In styles field of one component, values related to CSS layout and other self-defined styles are mixed together. At the same time, iOS uses Yoga as its layout engine. And each WXComponent(base class of any component) manages a Yoga node. The structure sketch is as follows:

Screen Shot 2018-08-03 at 15.00.43.png

After importing WeexCore, we use shared new layout engine called WeexLayout which lies in WeexCore layer. Now Javascript engine outputs render commands which serves as input to RenderManager in WeexCore. RenderManager processes each command and create RenderObjects as required and fill in styles and attributes. Also each RenderObject extracts CSS layout properties from styles and configurates its WeexLayout node. Actually RenderObject inherites from WeexLayoutNode. RenderManager generates RenderObjects and then yields RenderActions. RenderActions are passed to platform layer as input of instance component manager(WXComponentManager), and the we create iOS platform views.

Besides, layout is now triggered under two circumstances. Firstly, any change to render object tree or CSS style updating generate a batch action which will do layout immediately. Secondly, we take advantage of iOS platform display link which triggers every 16ms and check layout. Layout actions generate view frame synchronization tasks and we simply move our UIView, UITableView, etc.

As we mentioned above, in this first stage, WeexCore has not shown its strength. In the future, it will play a far more important role as a common layer.

Screen Shot 2018-08-03 at 16.54.25.png

0x3 Staple change points

0x31 Render commands data link

Screen Shot 2018-08-03 at 16.57.39.png

Screen Shot 2018-08-03 at 16.57.48.png

In the first stage, we still use Objective-C interface of JavascriptCore and forward render commands to WeexCore using WXCoreBridge methods.

Compared with previous implementations, we do nothing and forward commands directly to WeexCore. Before adopting WeexCore’s JSEngine interface, there are some overheads in converting styles and attributes data from Objective-C containers such as NSArray & NSDictionary to Json data. By profiling, performance degradation can be accepted. After adopting JSEngine interface, not only iOS and Android share the same architecture and no more Objective-C instances are created, but also performance will be increased.

0x32 Layout

Changes to layout are the most complex part of refactoring. a) In previous implementation, each WXComponent manages its layout node(YGNode) including life cycle, properties. After refactoring, underneath RenderObjects serve as layout node and synchronize final layout results to upper WXComponent instances. b) To support fixed components, we adopted RootLayoutNode and added layout node of root component as child of RootLayoutNode. Now WeexCore handles all things and we only need to update frames of fixed views. c) For scrollable components such as scroller, list and waterfall, we created extra layout node, and break the layout chain. That means, all children nodes are added to the scroller’s independent layout node and when doing layout, we first layout from root to the scroller and then let the scroller’s independent layout node layout the children. d) We easily supported RTL in the common layer.

0x33 Other change points

a) For recycler and waterfall components, shared codes for calculating column count, width, and margin now lies in WeexCore. b) CSS styles are now consumed by underneath RenderObjects. So we provide interface methods for retrieving raw CSS style values. Methods

0x4 To be continued...

In late 2018, we adopted WeexCore on iOS and unified layout engine on two platforms. In early 2019, we will continue to enhance WeexCore and make two platforms more consistent. By the way, the Eagle framework which makes use of templating and pre-compiling to speed up page displaying and the Heron framework which serves as uniform render engine both will be pluggable to WeexCore. By WeexCore, we tremendously extends the flexibility and functionality of Weex ecological system.