Design of MPX Partial Runtime Capability Enhancement for Mini‑Program Development
The article describes MPX’s partial runtime capability‑enhancement design, which adds modern web‑framework features such as props, default slots and event forwarding to Didi’s recompilation‑based mini‑program framework by enabling on‑demand runtime rendering for selected components, generating minimal base templates, respecting the native dual‑thread event model, and exploring server‑component‑inspired mixed rendering while keeping performance overhead low.
MPX is an open‑source, enhanced cross‑platform mini‑program framework released by Didi in 2018. After six years of development it has become the internal standard for all Didi mini‑programs, providing a unified technical baseline.
The article focuses on the design of MPX’s partial runtime capability‑enhancement solution, aiming to bring modern web‑framework features (such as props passing, default slots and event forwarding) to the mini‑program environment.
Framework Landscape
Recompilation‑type frameworks (e.g., MPX) use the mini‑program DSL as source and compile directly to platform‑compliant code.
Runtime‑type frameworks (e.g., Taro @3.x) allow developers to write Vue/React DSLs, inject a runtime layer, and polyfill DOM/BOM APIs that are unavailable in the logical thread.
Because of these different design philosophies, the pain points and optimization directions differ. Recompilation frameworks focus on enhancing mini‑program capabilities while staying close to modern web APIs; runtime frameworks mainly solve compatibility between web standards and the mini‑program platform.
MPX Runtime Enhancement Strategy
MPX adopts a minimal‑component‑granularity, on‑demand approach: only the components that need runtime features enable the extra runtime rendering path.
The overall solution is divided into compile‑time and runtime parts.
Compile‑time responsibilities
Render function enhancement
On‑demand generation of the base template
Injection of glue code
Runtime responsibilities
propertiesToComputed conversion
vDOM tree generation & view rendering
Component instance lifecycle management
Event delegation & dispatch
Render Function Example
global.currentInject = {
moduleId: "m3f28ff60",
render: function () {
this._c("message", this.message);
({ tap: [["onViewTapBubble", 'b', "__mpx_event__"]] });
this._i(this._c("navigatorList", this.navigatorList), function (item, index) {
({ tap: [["jumpTo", item]] });
item.name;
});
this._r();
}
}During the initial render, the render function collects reactive data, builds a vDOM tree and calls setData to update the view. Subsequent data changes trigger a re‑execution of the render function, producing a new vDOM tree, diffing it against the previous tree, and sending only the changed parts to the view layer.
mpx‑custom‑element Container Component
This built‑in component serves two purposes:
It acts as the base container that receives the composed tree data generated by the runtime and renders the actual component hierarchy.
It bypasses the mini‑program template recursion limitation by providing an extra rendering context.
Base Template Generation
All dynamic components share a common base template ( mpx‑custom‑element.wxml ). During compilation, only the components and attributes actually used are collected and injected, keeping the template size minimal.
<template is="tmpl_0_container" wx:if="{{r && r.nodeType}}" data="{{ i: r }}"></template>
<template name="mpx_tmpl">
<element r="{{r}}" wx:if="{{r}}"></element>
</template>
<template name="tmpl_0_block">
<block wx:for="{{i.children}}" wx:key="index">
<template is="tmpl_1_container" data="{{i:item}}" />
</block>
</template>
<template name="tmpl_0_view">
<view class="{{i.data.class}}" bind:tap="__invoke" data-eventconfigs="{{i.data.dataEventconfigs}}" style="{{i.data.style}}" data-mpxuid="{{i.data.uid}}">
<block wx:for="{{i.children}}" wx:key="index">
<template is="tmpl_1_container" data="{{i:item}}" />
</block>
</view>
</template>
...Event System
Mini‑programs use a dual‑thread architecture (view layer + logic layer). Events are declared in the view layer and are the only communication channel to the logic layer. MPX respects this native model and does not implement a separate vDOM‑based event system. Instead, special event lifecycles (e.g., catch , capture-bind ) are collected during template compilation and injected into the base template.
<view bindtap="__invoke" bindtouchstart="__invoke" bindtouchmove="__invoke" bindtouchend="__invoke" bindtouchcancel="__invoke" bindlongpress="__invoke"></view>Performance Considerations
Runtime rendering can increase data transfer because the entire vDOM tree must be sent from the logic thread to the view thread. MPX mitigates this by:
Enabling runtime features only for selected components, allowing the rest of the page to use the traditional compile‑time path.
Generating the base template on demand, including only the required component definitions, attributes and event bindings.
Server Components Inspiration
The article also explores the possibility of applying the Server Components concept to mini‑programs. By executing the render function on the server to obtain a vDOM tree (and optionally inlining style rules), the client can receive a lightweight description of the UI and let the runtime render it locally.
View Rendering Flow
1. The compiler transforms the template into an executable render function. 2. The render function runs (either on the device or on a server) and produces a vDOM tree. 3. The vDOM tree drives the base template ( mpx‑custom‑element.wxml ) to render the final view.
Style Rules
In the Server Components scenario, style rules are no longer static files; they are transmitted as inline styles and merged into the composed tree during render‑function execution.
Component Logic
Component lifecycle, props, state and event handling remain on the client side because they depend on the mini‑program runtime. Server‑only components perform pure rendering without state or lifecycle.
Mixed Rendering of Server and Client Components
MPX can render a mixture of runtime‑enabled components and native mini‑program components. Native components are registered as dependencies of the base template, allowing seamless integration.
Conclusion
MPX continues to evolve as a high‑performance, developer‑friendly cross‑platform mini‑program framework. The partial runtime capability‑enhancement design enables modern web‑like development experiences while keeping performance overhead low.
Didi Tech
Official Didi technology account
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.