Unveiling MPM PageData: Architecture and Multi‑Platform Rendering
This article explains how MPM's PageData serves as the core JSON abstraction that links the visual editor with various rendering engines, detailing its structure, generation process, and parsing workflows for static H5, direct H5, and mini‑program platforms.
Preface
This is the second article in the MPM sharing series. In the previous article we introduced the basic elements of MPM, a visual page builder for marketplace scenarios, and explained how those elements are derived and designed. The elements link modules and form the foundation for architecture and flow.
MPM System Architecture
MPM consists of an editing system used by operators and a page parsing engine. The editor generates PageData, which is parsed by different engines for various client environments to render the marketplace page. Both the editor and the engine implement the four system elements.
PageData
PageData is the medium that connects the editing state and the display state. It is a JSON abstraction of a marketplace page, containing configuration data and intermediate data such as request caches. Designing PageData correctly is key to the MPM architecture.
The standard JSON structure of PageData is:
<code>{
"pageId": "",
"appType": 1,
"pageConfig": {
"basic": {
"type": 2,
"env": 2,
"bgColor": "#fff",
"createDate": "",
"customCode": null,
"customCodeIn": 0,
"expireTime": "",
"expireUrl": "",
"name": "",
"path": "",
"status": 1,
"floorSortId": "",
"floorSortType": "",
"forceLogin": 0
},
"search": {
"topShow": 0,
"topRuleId": "",
"topAd": "",
"topBtnRd": "",
"topKeywordShow": 0,
"topKeywordRuleId": "",
"bottomShow": 0,
"bottomRuleId": ""
},
"share": {
"title": "京东购物",
"desc": "多·快·好·省",
"imgUrl": "//wq.360buyimg.com/img/mpm/defaultShare.jpg"
}
},
"userInfo": {
"checkNewuser": false,
"checkVip": false,
"checkPlus": false,
"checkBind": false,
"checkFirstBuy": false
},
"componentConfig": [],
"template": {
"vueFnObj": {},
"vueHook": {},
"styleTpl": {},
"header": "",
"footer": ""
},
"dataCache": {
"userInfo": {},
"floorSortData": {},
"dsCache": {}
}
}
</code>Key fields include:
pageId: unique identifier of the marketplace page.
appType: page type (1‑activity, 2‑venue, 3‑mini‑program).
pageConfig: page‑level configuration, with sub‑objects
basic,
search, and
share.
userInfo: automatically generated user‑level checks (VIP, new user, etc.).
componentConfig: array of floor (layer) configurations used by the parsing engine.
template: contains Vue template functions, hooks, style templates, and optional header/footer HTML.
dataCache: caches data such as userInfo, floorSortData, and dsCache to avoid duplicate requests.
Generation of PageData
PageData is created by the editor and stored in a SQL table. When a page is created, a record is inserted; on save, the editor syncs the latest PageData to the database; on publish, PageData is transformed into standard JSON for the parsing engines.
The database model stores fields like page_id, page_name, page_path, page_type, page_creator, page_create_date, and page_content (the serialized componentConfig).
PageData Generation Process
Editing a page goes through load, edit, save, and publish stages.
Load
The editor fetches the current PageData from the server, which may not yet be in standard structure, and performs authentication, configuration checks, and new‑page initialization.
Edit
PageData updates in real time as the operator configures the page, with Vue watch providing instant preview.
Save
Saving submits the latest PageData to the server, updates the database, and creates a preview link. The PageData is also converted to standard JSON for the parsing engine.
Publish
Publishing triggers a final save and then runs diagnostics, RD generation, accessibility checks, and automated tests before the page becomes live.
Parsing of PageData
MPM provides different parsing engines for H5 (static and direct) and mini‑program environments. The overall flow is similar but varies per platform.
Static H5 Parsing
Static H5 generates a static HTML file that includes the Vue engine and page data. The template uses placeholders ({{...}}) that are replaced with actual data, CSS, and engine scripts.
<code><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>{{title}}</title>
<!-- 头部 JS/CSS -->
<script>{{topScript}}</script>
<style>{{topCss}}</style>
</head>
<body>
<!-- 应用容器 -->
<div class="mpm-app"></div>
<script>
// page data
window.__PAGE_DATA__ = {{pageData}}
// 渲染模板
window.__COM_TPL__ = {{template}}
// 模板扩展方法
window.__COM_FNOBJ__ = {{fnObj}}
// 组件钩子函数
window.__COM_VUEHOOK__ = {{vueHook}}
</script>
<!-- 引擎 -->
{{engineCore}}
<!-- 底部 JS -->
<script>{{bottomScript}}</script>
</body>
</html>
</code>The engine performs a preload step to fetch user identity and floor sorting data, then sorts and filters floors, registers Vue components, and finally renders each floor.
<code>function renderPage () {
__PAGE_DATA__.componentConfig.forEach(createComponent);
// ...
}
function createComponent (com) {
const comId = com.id;
// el is the floor container generated in step 2
const el = document.querySelector(`#${comId}_con>[com-root]`);
const data = utils.copy(__PAGE_DATA__[comId]); // deep copy config
data.fnObj = __COM_FNOBJ__[comId]; // render function
new Vue({
el,
data,
render: __COM_TPL__[comId],
mounted () {
__COM_VUEHOOK__[comId]['mounted']("comId]['mounted'");
}
});
}
</code>Direct H5 Parsing
Direct H5 uses a Node/Express service that reads PageData from Redis, performs the same preload, sort, and filter steps, then uses
vue-server-rendererto stream the rendered HTML to the client.
<code>import { createRenderer } from 'vue-server-renderer';
const renderer = createRenderer();
// 页面渲染入口
async function renderPage () {
// 输出页面头
await context.res.write(pageTop);
// 输出页面楼层内容
await renderApp();
// 输出页面尾
await context.res.write(pageBottom);
}
// 渲染页面主体
function renderApp () {
return Promise((resolve, reject) => {
// 创建 app 的 Vue 实例
let app = new Vue({
data: rootData,
methods: rootMethods,
render: renderFn
});
// 创建渲染流
const stream = renderer.renderToStream(app);
// 分段输出
stream.on('data', chunk => {
// ...
context.res.write(chunk);
});
stream.on('end', () => {
// ...
app.$destroy();
resolve();
});
})
}
</code>Mini‑Program Parsing
Mini‑program pages receive PageData as a JSON file, then map it to pre‑built mini‑program components that exactly match the MPM templates, rendering the page on the client.
Conclusion
After understanding the MPM workflow, it becomes clear that the three platform engines share much logic, leading to duplicated effort when iterating on features. A unified “write once, run on three platforms” approach is desirable, but achieving it requires careful design due to the system’s size and complexity.
WecTeam
WecTeam (维C团) is the front‑end technology team of JD.com’s Jingxi business unit, focusing on front‑end engineering, web performance optimization, mini‑program and app development, serverless, multi‑platform reuse, and visual building.
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.