恰好近期有这么一次需求要将现有的微信小程序上开发别家的小程序,这个事要么通过现在比较好的方案uni-app来做,要么就用对应的原生小程序来写。但是从零开始做,工作量实在太大了,周期好长呀,那么多页面,得搞到啥时候。就在决定开始调研uni-app来做的时候,恰好有一天在微信上看见了一篇技术文章:开源|wwto:小程序跨端迁移解决方案——微信转其他小程序 最后放弃了使用uni-app来做,尝试通过这个工具来转换。
下面也将围绕 wwto 这个工具库,通过将我们现有的微信小程序转支付宝小程序来了解其转换原理,同时呢会说下在转换的过程中遇到的各种问题是如何解决的,希望对有需要的同学能有所帮助
在了解 wwto 这个工具库后,它大致的架构是这样的,下面这张图是使用作者的,更权威一点。
通过了解 编译 以及 运行时 这两个模块的实现过程就能够明白小程序转换的过程中做了那些事情以及怎么去做的了
下面对这两个阶段所做的事简单说下:
1、在 编译 阶段主要对4个文件做了处理,分别是:*.js、 *.json、 *.wxml、 *wxss
*.wxml 的处理部分代码如下,可看源码wxml.js
function convert(wxmlText, isWpy) { return wxmlText .replace(/wx:/g, 'a:') .replace(/a:for-items/g, 'a:for') .replace(/a:for-key/g, 'a:key') // data-set 全部转为小写 .replace(/data-[^=\s]=/g, (match) => match.toLocaleLowerCase()) // // s:for-index="{{idx}}" -> s:for-index="idx" .replace(/a:for-index=['"]({{\w+}})['"]/ig, (match) => match.replace('{{', '').replace('}}', '')) // 自定义组件命名不能用驼峰 .replace(/<[\w]+/ig, (match) => { return isWpy ? match : match.replace(/[A-Z]/g, (m) => ['-', m.toLowerCase()].join('')); }) // 事件绑定名称对齐 .replace(/\s+catch[\w]+=['"]/ig, (match) => match.replace(/catchsubmit/ig, 'onSubmit') .replace(/catch(\w)/g, (m, p1) => ['catch', p1.toUpperCase()].join(''))); ... 省略 } module.exports = convert;
通过对文件的处理:例如
<view bind:cellTap='onTabMyCrad' wx:if="{{hasJoin}}">...</view> 变成了 <view onCellTap='onTabMyCrad' a:if="{{hasJoin}}">...</view> 也就是把微信的语法转换为目标小程序的语法结构。
*.js 的处理部分代码如下,源代码script.js
function convert(jsText, isWpy) { return jsText .replace(/(require\(['"])(\w+)/g, '$1./$2') .replace(/(from\s+['"])(\w+)/g, (match, p1) => { // 相对路径以./开头 return match.replace(p1, [p1, isWpy ? '' : './'].join('')); }) .replace(/\.properties/g, (match) => { return match.replace('.properties', '.props'); }) .replace(/Component\([\s\S]+methods:[^{]*{/, (match) => { return [ match, `,\r\ntriggerEvent: function(name, opt) { this.props['on' + name[0].toUpperCase() + name.substring(1)]({detail:opt}); },\r\n` ].join(''); }) .replace(/[\s\S]+/, (match) => { // 只处理组件 if (!match.match(/Component\(/)) return match; ... 省略 }); } module.exports = convert;
通过对组件的处理如图:
这么转换的目的也就是原文中开源|wwto:小程序跨端迁移解决方案——微信转其他小程序 提到的 :支付宝小程序组件的生命周期函数与微信小程序完全不一样,也没有一一对应的关系。这种情况无法使用简单的方法名正则替换,本方案是注入支付宝小程序组件的生命周期函数,在这些生命周期函数中在调用微信小程序的生命周期函数,这样以来就避免了方法名替换无法一一对应的问题,也能更方便地书写适配代码。