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
setDatamethod.
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
elementtemplate:
<code><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>
</code>When the logic layer calls
setDatawith the following data:
<code>{
"nodeId": "1",
"tagName": "view",
"children": [
{"nodeId": "2", "tagName": "text", "content": "我是?"},
{"nodeId": "3", "tagName": "text", "content": "rax"}
]
}
</code>The rendered view becomes:
<code><view>
<text>我是?</text>
<text>rax</text>
</view>
</code>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
setDatapayloads, and recursively renders the view using predefined templates. Basic DOM operations such as
createElement,
appendChild,
insertBefore, and
removeChildmap 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.nodeIdand invokes the corresponding user function.
Engineering Design
The runtime reuses the Web bundle produced by Webpack. A plugin injects the simulated
windowand
documentobjects from
miniapp-renderinto the bundle, then generates a fixed mini‑program skeleton. The app loads the bundle in
app.js. Each page creates its own
documentinstance during
onLoadand calls the page‑specific
renderfunction, which mounts the root component via
document.createElementand appends it to
document.body.
Performance Optimizations
Initial runtime performance lagged behind native mini‑programs by about 40% due to full‑bundle execution, extensive
setDatapayloads, 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.,
<code>{"root.children.[0].children.[1].class": "active"}</code>Direct property assignment for built‑in components, eliminating costly
getAttributecalls.
Refactored
miniapp-renderdata structures, removing redundant trees and using
Map/
Setfor faster lookups.
Template optimizations: using
template issyntax 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
usingComponentsdeclaration. 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.
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.