把小程序代码跨端输出到 Web 和原生应用(Mpx)

Mpx 是滴滴开源的增强型跨端小程序框架,用 JavaScript 写成,能把一套类 Vue 语法的源码编译输出到微信、支付宝、百度、字节等多个小程序平台,也可输出 Web 与 React Native。这篇文章梳理它的主要功能、安装与跑通步骤、关键配置项、产物位置,以及真实 Issue 里暴露的坑,帮读者判断它是否适合自己手上的多端项目。

小程序团队常遇到的情况是这样:同一套业务要在微信、支付宝、百度、字节、QQ、京东这些平台各维护一份代码。模板语法有差异,基础组件有差异,API 调用方式也有差异,多维护一份就多一轮回归。

Mpx 是滴滴开源的增强型跨端小程序框架,用 JavaScript 写成,把一套类 Vue 语法的源码编译输出到各小程序平台、Web 和 React Native。

业内多数小程序框架把 Web MVVM 框架迁到小程序中运行,Mpx 选择以小程序原生语法和技术能力为基础做扩展与增强,再在增强语法之上完成同构跨平台输出。这样做的一个结果是最终 dist 代码可读性较强,排查问题时可以对着产物看。

Mpx 跨端编译输出的小程序、Web 与 React Native 三类目标

输入侧是 .mpx 单文件组件,里面写 template、script 和 style 三段,语法接近微信小程序的增强写法。输出侧按编译目标分三类:小程序平台拿到编译产物加运行时,Web 平台同样拿到编译产物加运行时,React Native 只拿到 RN JS 与资源产物,原生工程由开发者自备。

主要功能

  • 跨端编译输出。目标分三类:小程序用 wx / ali / swan / qq / tt / jd 等 mode;Web 用 web;React Native 用 ios / android / harmony。小程序与 Web 场景下 Mpx 同时负责编译产物和运行时,RN 场景只输出 RN JS 与资源。
  • 数据响应。提供赋值响应、watch 与 computed。示例代码里 computed 的 reversedTitle 会跟着 title 一起更新。
  • 增强模板语法。在原生模板基础上支持动态组件(<component is="...">)、类名与样式绑定(wx:class / wx:style)、内联事件函数、双向绑定(wx:model)以及 wx:ref。
  • 编译构建。基于 webpack5,支持持久化缓存,兼容 webpack 生态,兼容原生小程序,npm 场景下的分包输出也有支持。
  • 状态管理。按 Vuex 规范实现,支持多实例 Store。
  • TypeScript 支持。基于 ThisType 实现类型推导。
  • 原子类与 SSR。支持原子类写法,也支持服务端渲染。
  • RN 链路上的持续补齐。近期版本陆续加入了 UnoCSS 原子类 preset、Camera 组件、WXML <template> 编译支持等能力。

框架运行时压缩加 gzip 后约 14KB,这是官方给出的体积数字。I18n 国际化、单元测试与 E2E 测试也在支持列表里。

安装与依赖

官方推荐从脚手架开始,全局装一次工具:

npm i -g @mpxjs/cli

构建基于 webpack5,项目本身跑在 Node.js 上。仓库里没有说明支持的最低 Node 版本,也没有列出需要额外安装的系统依赖。框架运行时核心在 @mpxjs/core 包,构建相关能力在 @mpxjs/webpack-plugin 包,这两个是项目里最主要的依赖。

最短能跑通的用法

# 安装 mpx 脚手架工具
npm i -g @mpxjs/cli

# 初始化项目
mpx create mpx-project

# 进入项目目录
cd mpx-project

# 安装依赖
npm i

# development
npm run serve

# production
npm run build

创建项目时如果选了支持 React Native 的模板,脚本会多出几组:

npm run serve:ios
npm run serve:android
npm run serve:harmony

npm run build:ios
npm run build:android
npm run build:harmony

脚手架生成的脚本名以你实际拿到的项目为准,仓库没有逐一列出所有模板对应的脚本清单。

关键参数

  • mode:编译目标。小程序取值有 wx / ali / swan / qq / tt / jd,Web 是 web,React Native 是 ios / android / harmony。
  • srcMode:声明源码原本按哪个平台的语法写。例如 new MpxWebpackPlugin({ mode: 'tt', srcMode: 'wx' }) 表示把用微信语法写的源码编译成头条小程序。
  • transRpx:把 px 转成 rpx 的配置,子字段有 mode、comment、designWidth。
  • rnConfig.defaultBoxSizing:RN 业务节点的默认盒模型,可对齐为 content-box,减少固定宽高叠加 padding 与 border 时的跨端布局差异。
  • rnConfig.allowFontScaling:控制 RN 侧字体是否跟随系统缩放。
  • rnConfig.customBuiltInComponents:用微信基础标签名替换或扩展 RN 侧的内建组件实现。
  • plugin.perf.enable 与 probes:开启 @mpxjs/perf 运行时测速探针,可以按 framework 与 user 分组。

RN 链路还有一个文件维度的兜底逻辑:android 或 harmony 目标没有命中对应平台文件时,会自动回退查找 .ios 文件。常见做法是先写一份 index.ios.mpx 作为通用实现,再补 .android.mpx 与 .harmony.mpx 处理平台差异。

结果在哪里看

小程序场景,用对应平台的开发者工具打开项目文件夹下 dist 里对应平台的目录,就能预览效果。

React Native 场景,产物通常输出到 dist/react-native/,也可能按项目内 RN 容器工程的约定目录摆放。这部分产物要交给 iOS / Android / Harmony 各自的容器工程去消费,Mpx 不负责原生工程的创建、打包、签名和发布。

开发模式下终端会持续输出编译状态,样式改动引起的报错也出现在这里。跑 npm run serve 时留意终端,比只看开发者工具更容易定位问题。

实际使用中的坑

  • QQ 小程序里使用 <editor> 组件会直接编译失败,报 <editor> is not supported in qq environment。当时 QQ 平台实际上已经能用这个组件,属于框架适配没有跟上。该 Issue 已解决。
  • 频繁修改样式调试时,预览控制台会报 Cannot read property 'call' of undefined,组件显示不出来,切换最新基础库也一样,需要重新执行一次 npm run serve 才能恢复。该 Issue 已解决。
  • WebStorm 2022.3 上安装 Mpx 插件会提示版本不兼容,插件当时最高支持 222.*,而 IDE 需要 223.*。该 Issue 已解决。
  • 开启 i18n 之后,项目里原有的 wxs 代码不能正确执行,报 TypeError: Cannot read property 'getTimeFromIndexLast' of undefined。该 Issue 已解决。
  • 希望支持 windicss 的 Feature Request 目前仍是待解决状态,仓库没有给出排期。

这些坑集中在平台适配、构建缓存与工具链兼容三类,遇到同类现象时可以先看终端报错,再决定是清缓存重编还是提 Issue。

和同类放在一起看

项目适合谁部署方式主要限制什么情况下选它更合适项目地址
Mpx同时要投微信、支付宝、字节等多个小程序平台,还希望顺带出 Web 或 RN 版本的团队全局安装 @mpxjs/cli 后创建项目,按 mode 编译RN 输出只生成 JS 与资源,原生工程创建、打包、签名、发布要自备容器工程;部分平台组件适配依赖框架跟进一套代码要覆盖多个小程序平台,并希望保留接近原生小程序的调试确定性didi/mpx
ecomfe/okam需要一套小程序开发框架、对框架自带能力要求不复杂的团队仓库没有说明未逐一核实想换一套小程序开发框架时的参照对象ecomfe/okam
OnsenUI/OnsenUI做 HTML5 与 Hybrid 移动端 App、不涉及小程序编译的团队仓库没有说明面向移动端 Web 与 Hybrid App 的 UI 框架与 SDK,不产出小程序编译产物目标只是移动端 Web 或 Hybrid App,不需要跨小程序平台OnsenUI/OnsenUI

okam 和 Mpx 在「一套代码跑小程序」这件事上有重叠,但它不覆盖 Mpx 的 Web 与 React Native 输出链路,两者的交集只在多平台小程序编译这一段。OnsenUI 面向的是移动端 Web 与 Hybrid App,跟 Mpx 要解决的问题不是同一件事,放在这里只是给做同类选型的读者一个参照。

如果你的目标只是做一个微信小程序,或者团队现有框架已经跑得顺、没有多端诉求,Mpx 的增强语法带来的学习与迁移成本就不划算。如果目标只是移动端 Web 或 Hybrid App、完全不碰小程序编译,OnsenUI 这类直接面向 HTML5 的方案不用背 webpack5 与多平台编译链路,链路更短。

适合谁

手上有多端发布任务、且第一优先级是小程序平台的团队,适合把 Mpx 纳入选型。它同时覆盖微信、支付宝、百度、字节、QQ、京东,并且保留了对原生小程序组件库与统计工具的兼容,原生项目可以渐进迁移。已经有一套微信小程序代码、想扩到其他平台的项目,用 srcMode 声明源语法再改编译目标,改动量比重写小。

只做单平台小程序的项目不需要引入它。不打算碰小程序的纯 Web 或纯 App 项目也不需要。团队如果没有熟悉 webpack 构建链路的成员,遇到构建期报错时的排查成本会偏高,这一点在动手前值得先评估。仓库地址在 https://github.com/didi/mpx,许可证是 Apache License 2.0,主要语言为 JavaScript。

焚评:这个项目的量化评分

本项目的选题来自 焚.com(一个按公开公式给 GitHub 项目打分的站)。焚评当前总分 9.1 分(满分 10)。下表是各维度的得分:

评分维度得分
热度动量(权重 25%)8.2 / 10
开发活跃(权重 25%)10.0 / 10
社区响应(权重 15%)8.5 / 10
文档质量(权重 15%)10.0 / 10
发布节奏(权重 10%)8.2 / 10
风险控制(权重 10%)10.0 / 10

评分口径、权重与计算方式见焚.com 的评分方法页;数据随 GitHub 指标刷新,具体数值以焚.com 当前页面为准。本文正文为诀.com 独立撰写,评分数据由焚.com 授权引用。

内容核验说明

Mpx 的实用价值在于把跨端选型的判断材料摆齐:编译目标、关键配置、产物位置,以及仓库 Issue 里暴露的平台适配与构建缓存问题。适合要在多个小程序平台之间取舍、并可能顺带出 Web 或 RN 的团队先读一遍再决定是否动手。体积、评分等数字来自官方与焚.com 公开披露,诀.com 未独立验证;文中做法也未见实测复现记录。

运行时约 14KB、功能清单与配置项来自项目官方公开说明,焚评 9.1 分及各维度得分由焚.com 按公开公式给出,诀.com 均未独立验证。文中 Issue 状态引自仓库报告。全文无实测或复现记录,结果不保证在他人项目中复现。

项目来源与说明

开源项目:didi(didi)

本文由诀.com 编辑基于该项目的公开信息独立撰写,属原创解读,不是对项目文档的翻译或转载;文中提到的功能与参数以官方仓库为准,代码与文档版权归原作者所有。

查看项目仓库