本周要跟大家推荐的开源项目,是一款致力提高小程序开发体验和效率的增强型小程序框架 —— Mpx ,它在内部支撑了多款小程序,开源以来也得到外部关注与应用,本次的2.0更新也是亮点众多。
Mpx 是一款致力于提高小程序开发体验和效率的增强型小程序框架,目前在滴滴公司内部支撑了包括滴滴出行小程序,滴滴出行广场小程序,青桔单车,黑马电单车,小桔养车,小桔加油在内的小程序生态;自去年 11 月开源以来,Mpx 也吸纳了众多外部开发者的加入,基于 Mpx 开发了开走吧,好免街,花忆等小程序。
长期以来,Mpx 优秀的开发体验和强大的稳定性得到了内外开发者的一致认可和好评,这非常符合 Mpx 的设计初衷。但是在各大厂商陆续推出自己的小程序平台,且各家的技术标准都不统一的今天,单纯地提高某一个平台的开发体验已经不能满足广大小程序开发者们的诉求,一套代码在多小程序平台运行已经成为一个现实上的刚需。
为了解决这个小程序开发的痛点,Mpx 发布了 2.0 版本,适配了目前业内已经发布的所有小程序平台 ( 微信、支付宝、百度、头条、qq ),并且提供了直接将现有微信小程序编译输出到其他平台运行的能力。
Mpx 2.0 版本新增的主要特性主要包含:
完整支持了目前业内已发布的所有小程序平台 ( 微信、支付宝、百度、QQ、头条 );
Mpx 小程序跨平台开发,支持将已有的 Mpx 微信项目编译输出到其他已支持的小程序平台中运行。点击查看详情;
小程序原生组件跨平台编译,支持将已有的微信原生组件编译输出到其他已支持的小程序平台中运行;
深度分包优化,编译过程中进行精准分包资源判断,所有分包 only 的资源(组件、js、外部样式、外部模板、wxs,图像媒体等)都会精确输出到分包目录中;
render函数中完整支持 wxs 模块,关于 render 函数。点击查看详情;
支持了模板引入,内联 wxs,自定义 tabbar,独立分包,workers,云开发等原生能力,进一步完善原生兼容性。
同业内主流的小程序跨端框架相比,Mpx 更专注于小程序开发本身,在小程序开发中具备以下优势:
基于小程序自身的技术标准进行增强,没有进行过重的 DSL 转换,开发时遇到的坑会更少;
完全兼容原生小程序技术规范,0成本迁移原生小程序项目;
跨平台开发以跨小程序平台为目标,大部分差异抹平工作在编译阶段进行,大大减少运行时适配层增加的包体积;
支持业内微信小程序组件库(如 vant、iView 等)直接转换到其他小程序平台运行;
非常重视小程序性能,提供了深度的 setData 和包体积优化。
关于 Mpx 更详细的介绍可以查看官方文档和这篇文章。
1.跨平台开发
作为 2.0 版本的核心能力,Mpx 的跨平台开发能力允许用户直接将已有小程序项目编译输出到其他已支持的小程序平台中运行。微信小程序作为小程序概念的提出者,有着最广泛的生态覆盖,因此我们优先支持了将微信小程序编译为其他平台小程序的能力。
基于这个能力,用户不仅能跨平台编译微信 Mpx 项目,甚至能够将微信的原生自定义组件也编译到其他小程序平台进行运行,这意味着我们的跨平台项目能够直接使用一些社区内已有的 UI 组件库生态 ( 如 vant、iView 等),极大地提高了跨平台开发的适用范围。
设计理念
Mpx 框架的核心设计理念在于增强,增强是指在小程序已有的原生能力基础上做加法,拓展小程序的开发能力,提高小程序的开发体验和效率。这个设计理念使 Mpx 给开发者带来了更强的确定性和可预期性,更低的学习上手和调试成本。基于这个理念,Mpx 在不同的小程序平台中进行了差异性的增强适配,并参考各个平台的模板指令风格提供了不同的增强模板指令集,让用户在各小程序平台中都可以以增强的方式去最大限度地使用平台自有的原生能力。
我们在对 Mpx 提供跨平台能力的支持时也遵循了增强的核心设计理念。简单来讲,Mpx 的跨平台能力是在多平台能力的基础上,在编译和运行时增加了一层转换层,将源平台的代码转换为目标平台的代码之后,再按照既有的目标平台的处理逻辑进行增强,同时我们也提供了一套完善的条件编译机制,让用户自行实现少数框架无法转换的部分。
Mpx 跨平台开发流程示意图
Mpx 跨平台能力设计思路明显区别于业内已有的其他小程序跨平台框架,主要差异在于:
Mpx 以小程序本身的 DSL 作为基准,而没有使用 web 框架 ( React、Vue) 的 DSL;
Mpx 主要通过编译和运行时转换的方式处理平台差异,没有提供额外的差异抹平层(基础组件库等)。
之所以采用这种设计,主要基于以下原因:
Mpx 主要以跨小程序平台为目标,目前各大小程序平台的技术规范具有一定相似性,绝大部分平台差异能够通过编译和运行时手段抹平,同时省去的差异抹平层也能够进一步减少框架运行时体积;
使用小程序本身的 DSL 作为基准允许用户直接在已有项目中使用跨平台能力,对于原生小程序项目或组件也能够使用该能力进行跨平台输出;
结合完善的条件编译支持,该方案能够在满足用户跨平台需求的同时仍然允许用户最大限度地使用各个小程序平台提供的能力,完全延续了 Mpx 增强的核心设计理念。
使用方法
Mpx 跨平台开发的使用方式非常简单,用户只需在 MpxWebpackPlugin 创建时传入 mode 和 srcMode 参数指定源平台和目标平台,当 srcMode 和 mode 不一致时,框架会读取相应的配置对项目进行编译和运行时转换。
差异抹平
目前各大厂商的小程序技术规范在宏观层面上大致保持一致,但是技术细节方面存在很多差异,大致划分为以下几个部分:
模板语法/基础组件差异
json 配置差异
wxs 语法差异
页面/组件对象差异
api 调用差异
webview bridge 差异
其中,对于模板语法/基础组件、json 配置和 wxs 中的静态差异,我们主要通过编译手段进行转换处理,对于这部分差异中无法转换的部分会在编译阶段报错指出;而对于页面/组件对象、api 调用和 webview bridge 中 js 运行时的差异,我们主要通过运行时手段进行处理,对应无发转换部分也会在运行时中报错指出。
值得注意的是,我们在跨平台转换中做的工作不仅是对可转换的技术标准进行转换映射,对于一些目标平台中不存在的能力,我们也尽可能地通过编译和运行时手段提供了模拟和支持,最大限度地减少用户在跨平台开发中需要付出的额外工作量。以差异性最大但现实场景也最多的微信转支付宝为例,Mpx 模拟提供了许多微信中支持但支付宝中未支持的能力:
组件自定义事件
组件间关系
获取子组件实例
observers/property observer
内联 wxs
对于原生自定义组件的跨平台转换,我们会对其进行简单的运行时注入,使其能够使用 Mpx 框架提供的运行时转换能力。
条件编译
对于框架无法抹平的差异部分,会在编译和运行时报错指出,对于这部分错误,我们提供了完善的条件编译机制让用户能够自行编写目标平台的 patch 进行修复,该能力也能用于实现具有平台差异性的业务逻辑。
上文中提到 Mpx 通过读取用户传入的 mode 和 srcMode 来决定是否以及如何对项目进行转换,mode 和 srcMode 分别代表整个项目构建的目标平台和源平台,条件编译能够让用户在项目中创建声明了自身平台属性 ( localSrcMode ) 的文件和代码块。在项目构建中,框架会优先加载带有 localSrcMode 声明且 localSrcMode 与项目目标平台匹配 ( localSrcMode===mode ) 的文件和代码块,这部分文件和代码块需要完全依照自身声明的平台标准进行编写,Mpx 不会对其进行任何编译和运行时的跨平台转换。
Mpx 提供了三种维度的条件编译,分别是文件维度,区块维度和代码维度,用户可以根据差异范围和自身需要自行选择使用。
2.性能优化
Mpx 框架专注于小程序开发,在性能优化方面我们做过很多尝试和努力,主要集中在两个方面:
运行时的setData优化
编译构建时的包体积优化
setData 优化
数据响应是 Mpx 运行时增强的核心能力,该能力让用户在小程序开发中能够像 Vue 中一样使用 watch 和 computed 特性,并且用直接赋值的方式操作数据驱动视图更新,而不需要手动调用 setData 方法,换言之框架接管了小程序中的 setData 调用。
通过各大小程序平台的设计原理和性能优化建议可以得知,setData 对于小程序的性能表现非常重要,而 setData 优化的两大方向在于:
尽可能减少 setData 调用的频次
尽可能减少单次 setData 传输的数据
为了实现 setData 的优化,我们在模板编译过程中对于每个组件的模板都生成了一个渲染函数 ( render function ),该函数模拟模板的渲染逻辑,在每次执行时访问当次渲染所需的数据,并将当次访问过的数据路径记录下来作为函数返回值返回。
在运行时,框架会在每个组件创建时创建一个 render watcher,该 watcher 追踪渲染函数,当渲染依赖数据发生变更时异步执行渲染函数,在 render watcher 回调中得到渲染函数返回的数据路径,基于这些路径与上一次的缓存数据进行 diff 比对,过滤掉未发生变化的数据后得到最小必要数据,最后调用 setData 将最小必要数据发送到真实的小程序渲染层更新视图。
基于这个机制,当数据发生变更时,只有当前渲染依赖的那部分数据发生变更才会异步地触发 render watcher 的执行,而每次执行后也只有实际发生变更的那部分数据会被 setData 发送到渲染层。这样用户就能自由地根据业务需求来操作数据,无需关注 setData 的调用优化,框架能够自动进行程序上最优的 setData 调用,在提升用户开发体验的同时也提升了程序性能。
在 1.x 版本中,渲染函数内无法执行 wxs 的逻辑,对于含有 wxs 的组件有可能降级到全量设置数据的模式,在 2.0 版本中,我们将 wxs 模块转译处理为 js 可执行的代码后注入到 js bundle 中,含有 wxs 的渲染函数也能够正常访问并执行 wxs 逻辑。
setData 优化示意图
包体积优化
类似于运行时对于 setData 的接管,Mpx 在编译阶段接管了项目的资源管理。得益于 webpack 强大的插件机制,Mpx 开发了一个深度定制的 webpack 插件,基于 webpack 完成小程序的打包构建工作。用户在使用 Mpx 开发小程序时可以不受限制地使用 npm 依赖、最新的 es 特性和 css 预处理器等现代 web 开发能力。与此同时,Mpx 在包体积优化上也做了很多工作,让用户专注于业务开发而无需花费过多精力进行包体积管理,我们所做的优化工作如下:
打包构建工作完全基于依赖分析,任何没有被引用的资源都不会出现在 dist 当中;
对于 npm 组件和页面的构建也完全基于依赖分析按需打包,不会 copy 整个 miniprogram_dist 目录,也不需要执行构建 npm,使用体验和包体积均优于微信小程序自身的 npm 支持方案;
基于 webpack 提供的能力进行公共模块抽取和代码压缩等优化工作;
完善的分包支持,对所有资源进行从属分析,将所有分包 only 的资源都输出到分包目录中。
分包作为微信小程序中优化包体积的核心手段(类似于异步按需加载),Mpx 对其进行了完善的支持。为了精确地标记出分包 only 的资源,我们在构建时将主包和分包的依赖收集步骤拆分开来串行处理,先处理主包,再处理分包。在主包的处理过程中,将主包页面中引用的所有非 js 资源 ( 组件、外部样式、外部模板、wxs、图像媒体等 ) 都记录下来,在处理分包时,对分包内引用的非 js 资源都进行检查,如果被主包引用过则输出到主包中,否则标记为分包 only 的资源输出到分包目录下。
对于 js 模块资源,我们在脚手架中生成的构建配置中提供了辅助函数,便于用户进行分包 bundle 的配置,经过该配置后,分包 only 的公用模块会被打入分包 bundle 输出到分包目录下,其余的公共模块会正常打入主 bundle 中。
在跨平台开发中,我们建议用户使用 Mpx 提供的 packages 来定义分包,这样在转换到不支持分包的小程序平台时会自动降级为同步包进行处理。
分包构建示意图
3.渐进迁移
Mpx 提供了良好的渐进迁移支持,对于使用原生或其他小程序框架的开发者来说,采用渐进迁移的方式逐步引入 Mpx 进行开发成本并不大。
在 2.0 版本中我们进一步完善了 Mpx 的原生兼容性,跟进支持了各个小程序平台最新的技术能力,如自定义 tabbar、独立分包、分包预加载、workers、云开发等能力,同时补齐了一些 1.x 版本遗漏的支持。得益于此,对于使用原生小程序开发的开发者来说,迁移 Mpx 的成本几乎为 0,用户只需将对应页面组件的构造函数替换为 Mpx 提供的 createPage/createCompnent,即可使用 Mpx 提供的各种增强能力。
对于使用其他框架的开发者,Mpx 也提供了局部构建的机制,允许用户将特定的页面和组件单独构建输出为原生组件,用户只需手动或者编写脚本输出的原生组件整合进原有项目中即可。
4.未来规划
作为滴滴公司内部小程序生态的基础设施,我们会对 Mpx 框架进行长期的维护更新,确保能在第一时间支持各个小程序平台最新的技术特性。与此同时,我们也会进一步完善框架的基础能力,目前已排上日程待支持能力包括:
i18n
ts支持
单元测试支持
在跨平台能力方面,我们也会根据社区的反馈和建议,以及小程序的标准化进程,对其进行持续的完善与更新。
本文转载自公众号滴滴技术(ID:didi_tech)。
原文链接:
https://mp.weixin.qq.com/s/1egWKpHBIXuFQ7YKHj3dSg
评论