Mpx 2.9 Release: Atomic CSS Support, SSR Integration, and Bundle Size Optimizations
Mpx 2.9 adds built‑in atomic‑class (utility‑first) CSS, server‑side rendering for web output, and a suite of bundle‑size optimizations—including deterministic IDs, template compression, empty‑module removal, and render‑function pruning—while splitting atomic CSS into sub‑packages for mini‑programs and outlining a roadmap for further compile‑time reductions, Vite support, and cross‑platform extensions.
Mpx, an open‑source enhanced cross‑platform mini‑program framework from Didi, has entered its sixth year. It now serves as the unified technical standard for all of Didi's mini‑program projects.
The 2.9 version introduces three core features focused on performance and bundle size: built‑in atomic‑class (utility‑first CSS) support, server‑side rendering (SSR) for web output, and extensive bundle‑size optimizations.
Atomic‑class support
Utility‑first CSS has become popular in the front‑end community (e.g., Tailwind, WindiCSS, UnoCSS). Mpx 2.9 embeds atomic‑class support, allowing developers to use classes such as flex , pt-4 , text-center , rotate-90 directly in <view> templates. Example:
<view class="container">
<view class="flex">
<view class="py-8 px-8 inline-flex mx-auto bg-white rounded-xl shadow-md">
<view class="text-center">
<view class="text-base text-black font-semibold mb-2">Erin Lindford</view>
<view class="text-gray-500 font-medium pb-3">Product Engineer</view>
<view class="mt-2 px-4 py-1 text-sm text-purple-600 font-semibold rounded-full border border-solid border-purple-200">Message</view>
</view>
</view>
</view>
</view>This produces a simple personal card without writing any custom CSS.
Benefits over traditional custom classes include:
Eliminates the need to invent and manage custom class names.
Prevents uncontrolled growth of CSS size because atomic classes are reusable.
Localizes style changes, avoiding side effects on other components.
Compared with inline styles, atomic classes also provide:
Design constraints that enforce a visual system.
Responsive utilities (media queries) unavailable in inline styles.
State variants (hover, focus, etc.) via the framework’s state variables.
Special character escaping
When using atomic classes that contain characters such as ( , ) , [ , ] , { , } , # , ! , / , . , : , , , % , \ , " , + , $ , the framework provides a default escape map:
const escapeMap = {
'(': '_pl_',
')': '_pr_',
'[': '_bl_',
']': '_br_',
'{': '_cl_',
'}': '_cr_',
'#': '_h_',
'!': '_i_',
'/': '_s_',
'.': '_d_',
':': '_c_',
',': '_2c_',
'%': '_p_',
'\\': '_q_',
'"': '_dq_',
'+': '_a_',
$: '_si_',
unknown: '_u_'
}Developers can override these rules via the escapeMap option of the @mpxjs/unocss-plugin .
Atomic‑class split‑package output
In web builds all atomic CSS is bundled into a single file, but mini‑programs have a 2 MB main‑package limit. Mpx therefore outputs atomic classes to sub‑packages based on usage frequency (controlled by the minCount option, default 2). This reduces main‑package size while keeping shared classes in the main bundle.
SSR support
Mpx now fully supports server‑side rendering for web output. It adapts the Vue SSR workflow to the mini‑program ecosystem, handling memory leaks, request‑level state isolation, and data pre‑fetching. New lifecycle hooks introduced in 2.9 are:
onAppInit : creates a fresh app instance per request (e.g., to instantiate a new Pinia store).
serverPrefetch : fetches data before rendering, similar to Vue’s API.
onSSRAppCreated : receives app , router , pinia , and context to set the route and synchronize state.
Example server‑side build configuration (webpack):
// webpack.server.config.js
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
module.exports = merge(baseConfig, {
entry: './app.mpx',
plugins: [new VueSSRServerPlugin()]
})Client‑side configuration uses VueSSRClientPlugin similarly.
SSR template example:
<!DOCTYPE html>
<html lang="en">
<head><title>Hello</title></head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>Express server integration:
const app = require('express')()
const { createBundleRenderer } = require('vue-server-renderer')
const serverBundle = require('../dist/server/vue-ssr-server-bundle.json')
const clientManifest = require('../dist/client/vue-ssr-client-manifest.json')
const template = require('fs').readFileSync('../src/index.template.html', 'utf-8')
const renderer = createBundleRenderer(serverBundle, {runInNewContext: false, template, clientManifest})
app.get('*', (req, res) => {
const context = {url: req.url}
renderer.renderToString(context, (err, html) => {
if (err) { res.status(500).end('Internal Server Error'); return }
res.end(html)
})
})
app.listen(8080)Bundle‑size optimizations
Beyond standard webpack optimizations (tree‑shaking, minification), Mpx 2.9 adds:
Deterministic module/chunk IDs replaced with incremental numeric IDs, saving hundreds of KB.
optimizeSize flag that compresses template boilerplate code (e.g., chunk loader wrappers), reducing total size by ~1.6%.
Removal of empty modules generated after extracting template, style, and JSON parts via a new CommonjsExtractDependency , saving ~0.7%.
Render‑function data‑access pruning: two‑pass AST traversal eliminates redundant property accesses, potentially shrinking render code by up to 5% when enabled via optimizerEnderRules .
Future roadmap
Planned improvements include:
Further compile‑time code injection reductions and optional lossy render optimizations.
Template/JSON name hashing with source‑map support.
Local runtime rendering enhancements, proxy‑based reactivity, Vue 3 web output.
Adaptations for Alipay 2.0, WeChat Skyline, and Hummer.
Build‑speed advances: Vite support, module‑federation distributed builds, and Rust‑based high‑performance builds.
The release thanks contributors @pagnkelly, @yandadaFreedom, and @zhuzhh, and invites the community to adopt Mpx for cross‑platform mini‑program development.
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.