铺垫
随着大前端蓬勃发展, 冒出越来越多的端, 最火的当数最近出现的微信小程序. 但是无论是 微信小程序 , 还是 支付宝小程序, 或者 快应用 都有一个明显的缺点, 虽然他们还是按照一定的 js html css 标准作为开发方式, 但是他们都与当前所有主流技术有相当大的壕沟.
虽然小程序使用类似Vue, angular的模板渲染, 实现了类MVVM的开发方式.但是小程序的开发方式相当蛋疼. 以下是一个简单小程序的目录结构:
上述目录只包含页面内容, 开发过程中需要不断在不同文件中切换. 相比React的Component+css 和 Vue的单文件来看, 开发体验不太好. 并且很多小程序开发者都是vue、React、angular等等前端框架的使用者, 使用熟悉的开发栈对他们来说更容易上手.
小程序的本质
在开发一个工具前要理解运行载体的原理. 正如我们希望用React去开发小程序, 那么我们必须要了解小程序的原理.
因为小程序是闭源的, 我只能在自己的猜想上分析. 但是小程序的底层是Native 这是前提. 那么我猜想小程序的实现原理应该跟ReactNative类似, 通过js bridge搭建js和原生通信的桥梁, 由js及模板, 实现对页面的渲染描述.
但是小程序与ReactNative的不同点是, ReactNative对js层开放renderer api. 而小程序则对这层进行了封装. 这让我们无法通过重新实现React的renderer来使用React的一些特性(如vdom).
所以我的思路是通过语法转换, 把React文件转换成小程序工程文件. 并实现小程序的框架, 来对接小程序与react的生命周期方法.
期望
我希望能把React文件, 经过编译后, 变成可执行的微信小程序
import Page from '../wechat'
import './page.css'
class P extends Page {
onClick(){
}
render() {
return (
<div className="app" onClick={this.onClick} style={{posistion:"relative"}}>
威武
</div>
)
}
}
复制代码
开始我们的旅程
有了开发小程序的思路, 那我们就来动手. 我使用了babel作为语法转换的工具, 我们先开个头. 下面是转换的核心代码
function transform(code, sourcePath) {
let output = {
wxml:'',
wxss:'',
js:'',
json:'',
type:''//App||page||component
}
sharedState.sourcePath = sourcePath;
const result = babel.transform(code, {
babelrc: false,
plugins: [
'@babel/plugin-syntax-jsx',
transformPlugin,
'@babel/plugin-proposal-object-rest-spread',
['@babel/plugin-proposal-decorators',{"legacy": true}]
]
})
// tranform后, 结果都会写入sharedState.output
output = sharedState.output;
const obj = t.objectExpression(sharedState.methods);
output.js = generate(obj).code;
sharedState.reset();
switch(output.type){
case 'App':
output.js = CodeWrapper('App', output.js);
break;
default: //Page
output.js = CodeWrapper('Page', output.js);
break;
}
return output;
}
复制代码
该部分代码实际上就是通过babel 对React代码文件进行处理, 处理后把结果写入到output. 重点在于, 我们通过babel.transform这个方法, 把代码拆分成四块, 分别写入到sharedState.output中.
最终通过一些简单处理后, 返回output, 不难看出output中的wxss, js, json, wxml就是一个小程序页面/组件的代码文件.
其中 transformPlugin
是自定义的编译插件. 今天有点晚先到这里, 下期继续讨论插件开发思路.
项目代码: https://github.com/PepperYan/react-miniapp)
喜欢这篇文章的大佬, 点个赞和star, ٩(๑´0`๑)۶
该项目参考了mpvue, taro, weact等. babel-traverse和babylon babel
还有感谢 @方正 提点
原文链接: https://zhuanlan.zhihu.com/p/38102065