Inside Weex iOS: How the SDK Bridges JavaScript and Native for High‑Performance UI
This article explores the Weex SDK architecture on iOS, detailing its cross‑platform workflow, the division of JS, bridge, and native layers, the registration of modules and components, and the role of WXSDKInstance in loading and rendering JS bundles.
About Weex
Weex is a cross‑platform dynamic page solution that lets developers write native‑level experiences using front‑end syntax, similar to React Native. It follows the "Write Once, Run Everywhere" principle, allowing the same code to run on multiple platforms.
The workflow involves converting Weex files on the server into a JS bundle, which the client downloads and executes via the Weex SDK's JavaScript engine. The JS‑Native bridge then issues commands for UI rendering, data storage, network communication, device functions, and user interactions.
Weex Framework
The source code (e.g., version 0.16.1) is organized into three parts: the JS side, the bridge side, and the pure native side.
JS Side
The main file native-bundle-main.js provides a set of basic JS methods, acting as a library that is loaded into memory when the Weex SDK initializes. The JS bundle is split into a small core library and business code, reducing download size and improving load speed.
Bridge Side
The bridge facilitates communication between JS and native code using a global JSContext. During SDK initialization, methods are injected into the context, such as:
- (void)registerCallNative:(WXJSCallNative)callNative {
JSValue* (^callNativeBlock)(JSValue *, JSValue *, JSValue *) = ^JSValue*(JSValue *instance, JSValue *tasks, JSValue *callback){
NSString *instanceId = [instance toString];
NSArray *tasksArray = [tasks toArray];
NSString *callbackId = [callback toString];
return [JSValue valueWithInt32:(int32_t)callNative(instanceId, tasksArray, callbackId) inContext:[JSContext currentContext]];
};
_jsContext[@"callNative"] = callNativeBlock;
}Native code can also invoke JS methods via invokeMethod:withArguments::
- (JSValue *)callJSMethod:(NSString *)method args:(NSArray *)args {
return [[_jsContext globalObject] invokeMethod:method withArguments:args];
}Pure Native Side
This layer handles business logic such as JS bundle requests, UI rendering, performance statistics, and more. It is divided into three sub‑layers: Interface, Function, and Basic.
The Interface layer exposes APIs to developers, allowing SDK initialization, component and module registration, and controller creation via WXSDKInstance. The Basic layer provides utilities like network wrappers, event definitions, and a C‑based layout engine (Yoga). The Function layer includes modules such as Monitor and DevTool.
Modules, components, and handlers are registered as plugins during SDK initialization:
+ (void)registerDefaults {
[self _registerDefaultComponents];
[self _registerDefaultModules];
[self _registerDefaultHandlers];
}Component registration maps native UI elements to JS tags, e.g.:
[self registerComponent:@"container" withClass:NSClassFromString(@"WXDivComponent") withProperties:nil];
[self registerComponent:@"div" withClass:NSClassFromString(@"WXComponent") withProperties:nil];
[self registerComponent:@"text" withClass:NSClassFromString(@"WXTextComponent") withProperties:nil];Module
Modules expose native capabilities to JS. Registration uses macros that generate methods prefixed with wx_export_method_, storing method names in WXInvocationConfig for later lookup.
#define WX_EXPORT_METHOD(method) WX_EXPORT_METHOD_INTERNAL(method, wx_export_method_)
#define WX_EXPORT_METHOD_INTERNAL(method, token) \
+ (NSString *)WX_CONCAT_WRAPPER(token, __LINE__) { \
return NSStringFromSelector(method); \
}During runtime, the SDK scans for these generated methods, extracts the original selector name, and populates async or sync method dictionaries.
Examples of built‑in modules include WXDomModule (DOM parsing), WXNavigatorModule (UI navigation), WXStreamModule (network requests), WXAnimationModule (animations), and many others providing storage, clipboard, WebSocket, and more.
Component
Components correspond to UIKit elements (e.g., UIView, UIImageView) and maintain a lifecycle similar to UIViewController. They are created with style, attributes, and events, and can be updated after view loading via updateStyles or updateAttributes.
JS calls components through bridge methods like callNativeComponent and callUpdateAttrs, which generate a WXComponentMethod and invoke it via NSInvocation. The WXComponentManager schedules components and handles rendering.
Component layout uses Facebook Yoga's box model, defining margin, border, padding, and content edges to compute frames.
WXSDKInstance
The WXSDKInstance is the entry point for a Weex page. It downloads the JS bundle, passes it to the JS framework for parsing, and triggers rendering via WXDomModule. Each instance owns its own WXComponentManager.
Key callbacks include onCreate() (after bundle download and root view creation), renderFinish() (after first‑screen DOM parsing), onFailed() (load failure), and onJSRuntimeException() (JS errors), allowing developers to customize behavior.
Tencent TDS Service
TDS Service offers client and web front‑end developers and operators an intelligent low‑code platform, cross‑platform development framework, universal release platform, runtime container engine, monitoring and analysis platform, and a security‑privacy compliance suite.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
