How Rax Enables Runtime Rendering for Mini‑Programs: Architecture and Optimizations
This article explains the principles behind Rax's mini‑program runtime scheme, compares it with the compile‑time approach, details the self‑referencing component technique, event system, engineering design, performance tuning measures, mixed usage with custom components, and future optimization directions.
In March 2020, after supporting the compile‑time solution, Rax released a version that also supports a runtime scheme, making it the only mini‑program framework that offers both approaches.
Review of Compile‑time Scheme
The compile‑time scheme focuses on compilation, similar to Taro v2.x, converting JSX to mini‑program template languages (WXML/AXML) and adding lightweight runtime JS to bridge React and mini‑program lifecycles. Rax's compile‑time implementation follows the same principle.
Foundations of the Runtime Scheme
The runtime scheme emphasizes rendering at runtime without static compilation, removing syntax restrictions. Mini‑programs are built on Web technologies but isolate logic and view layers; data is passed from the logic layer to the view layer via the setData method.
Self‑referencing Component Rendering
Mini‑program custom components support “self‑reference”, allowing a component to include itself as a child, enabling dynamic DOM tree construction. Example component element template:
<view wx:if="{{r.tagName === 'view'}}" id="{{r.nodeId}}">
<block wx:for="{{r.children}}" wx:key="nodeId">
<element data="{{r: item}}" />
</block>
</view>
<text wx:elif="{{r.tagName === 'text'}}">
{{r.content}}
</text>When the logic layer calls setData with the following data:
{
"nodeId": "1",
"tagName": "view",
"children": [
{"nodeId": "2", "tagName": "text", "content": "我是?"},
{"nodeId": "3", "tagName": "text", "content": "rax"}
]
}The rendered view becomes:
<view>
<text>我是?</text>
<text>rax</text>
</view>This technique enables dynamic rendering despite fixed WXML templates.
Core Principle (kbone)
Rax’s runtime scheme derives from kbone, which simulates DOM/BOM APIs in the logic layer, builds a virtual DOM tree, converts it to setData payloads, and recursively renders the view using predefined templates. Basic DOM operations such as createElement, appendChild, insertBefore, and removeChild map to corresponding data structure manipulations.
Event System
The library
miniapp-render</> provides a simulated DOM/BOM API. Events are handled via an <code>EventTargetbase class; each logical node inherits from it and is identified by a unique nodeId. View‑layer components bind events (e.g., bindtap, bindtouchstart) to this nodeId. When an event fires, the handler retrieves the target node ID via event.currentTarget.dataset.nodeId and invokes the corresponding user function.
Engineering Design
The runtime reuses the Web bundle produced by Webpack. A plugin injects the simulated window and document objects from miniapp-render into the bundle, then generates a fixed mini‑program skeleton. The app loads the bundle in app.js. Each page creates its own document instance during onLoad and calls the page‑specific render function, which mounts the root component via document.createElement and appends it to document.body.
Performance Optimizations
Initial runtime performance lagged behind native mini‑programs by about 40% due to full‑bundle execution, extensive setData payloads, and recursive component rendering. Optimizations included:
Precise data updates: only changed nodes trigger setData, with batch processing at the root and path‑based partial updates, e.g.,
{"root.children.[0].children.[1].class": "active"}Direct property assignment for built‑in components, eliminating costly getAttribute calls.
Refactored miniapp-render data structures, removing redundant trees and using Map / Set for faster lookups.
Template optimizations: using template is syntax and reducing conditional checks to improve recursion performance on both Alipay and WeChat platforms.
Mixed Usage with Custom Components
Rax supports mixing built‑in components, custom mini‑program components, pages, and plugins. When a custom component is imported, its path must match the usingComponents declaration. During compilation, Babel scans JSX, caches component properties and events, and a Webpack plugin injects them into recursive templates. At runtime, the renderer checks the cache to render the custom component with its cached attributes and bound events.
Future Optimization Directions
Rax aims to provide more flexible dual‑engine usage, allowing developers to specify per‑component whether to use the compile‑time or runtime engine within a single project, further balancing performance and development efficiency.
Conclusion
The Rax mini‑program runtime scheme overcomes the syntax limitations of compile‑time solutions but introduces performance challenges. Through systematic optimizations, its performance now rivals other runtime frameworks like Taro and Remax, while its dual‑engine capability offers a compelling balance for developers choosing the best tool for their mini‑program projects.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Taobao Frontend Technology
The frontend landscape is constantly evolving, with rapid innovations across familiar languages. Like us, your understanding of the frontend is continually refreshed. Join us on Taobao, a vibrant, all‑encompassing platform, to uncover limitless potential.
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.
