铺垫
随着大前端蓬勃发展, 冒出越来越多的端, 最火的当数最近出现的微信小程序. 但是无论是 微信小程序 , 还是 支付宝小程序, 或者 快应用 都有一个明显的缺点, 虽然他们还是按照一定的 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 https://babeljs.io/docs/en/babylon.html
还有感谢 @方正 提点
来源: https://juejin.im/post/5b23b93bf265da59b83d3c52