鋪墊
隨著大前端蓬勃發展, 冒出越來越多的端, 最火的當數最近出現的微信小程式. 但是無論是 微信小程式 , 還是 支付寶小程式, 或者 快應用 都有一個明顯的缺點, 雖然他們還是按照一定的 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