Frontend Development 19 min read

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.

Didi Tech
Didi Tech
Didi Tech
Design of MPX Partial Runtime Capability Enhancement for Mini‑Program Development

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.

frontend developmentcomponent architecturemini-programMPXRuntime EnhancementVDOM
Didi Tech
Written by

Didi Tech

Official Didi technology account

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.