用 React 開發小程序的探索之路

在目前市面上已經有非常多的小程序開發框架,其中的佼佼者如 wepy 以及 mpvue ,他們都是非常優秀的小程序開發框架。但是它們都有一個共同的特點,都是通過類 vue 語法的小程序開發框架。這點對於國內一些 react 的開發者來說就顯得有點遺憾了。

我們團隊在去年就整體轉入了 react 開發陣營,對於我們團隊來說, react 會更加熟悉一些。所以我們一直在探索如何用 react 開發小程序,前端時間我們開源了一個框架,叫做 Taro 。本次也會圍繞這個,來分享 探索使用 react 開發小程序。主要包含以下五個部分內容:

用 React 開發小程序的探索之路

第一部分:原生開發之痛

開發小程序由三部分組成,這三大部分都是由四種類型文件,如下圖所示:

用 React 開發小程序的探索之路

我們以 JS 文件為例:

用 React 開發小程序的探索之路

我們在寫原生小程序的時候,這兩份代碼是非常常見的。 它們都是藉助函數工廠類的方式去構建頁面以及組件。 在小程序中的一大特色就是使用字符串模板的形式來編寫界面,如圖:

用 React 開發小程序的探索之路

以上就是一些小程序官方寫法上的一些約定,但也是這些約定,讓開發者存在一些開發上的痛點,這些痛點主要集中在:

  • 開發體驗
  • 性能瓶頸

在開發體驗上,代碼組織稍顯複雜。 當組件和頁面越來越多,項目越來越龐大的時候開發成本就會顯得有點高,其次就是編碼體驗不夠順暢,如下圖:

用 React 開發小程序的探索之路

頁面或者組件無法被繼承的時候,我們在實現一些功能的時候會受到一些限制 ,同時小程序本身提供了一些 API ,但是卻沒有提供一個跟編輯器很好結合的東西,當我們在使用這些 API 的時候缺乏智能提示。 其次就是字符串模板稍顯孱弱。例如 :

用 React 開發小程序的探索之路

當我們實現一個日期格式化的時候,點擊的時候無法傳參,還有就是直接寫一個格式化函數是無法運行的,我們需要藉助 wxs 這樣的一些工具去實現這樣的一個功能,但是這樣是非常麻煩的。 還有就是小程序的代碼規範並不是很統一,以 Button 組件為例:

用 React 開發小程序的探索之路

一些屬性參數都是有很大的差異的。 其次就是缺乏統一的自動化編譯處理,導致無法直接在小程序中直接使用一些 新的 ES 語法,以及 SASS 、 LESS 來書寫樣式代碼。

在性能瓶頸上面,小程序的整體架構是這樣的:

用 React 開發小程序的探索之路

分為視圖層和邏輯層,這兩個層之間是有一個特定的通信方式的,當我們在調用 setData 去更新視圖的時候,小程序首先把你傳入的數據 使用 JSON.stringify 進行序列化,之後拼接成一段可執行的 JS 腳本,最後運行。在這樣的一層通信機制上,導致去調用 setData 的去更新視圖的時候成本非常之高。所以小程序官方也是提供了一些對於性能優化上的提示

  • 避免頻繁 setData
  • setData 避免傳入大規模數據

針對以上的痛點和限制,業界也有一些優秀的解決方案,諸如 mpvue, wepy, 但是它們都是類 vue 的開發框架。正如前面所說,這樣子的話對於我們團隊或者使用 react 的開發者有點遺憾。

第二部分:如何使用 React 開發小程序

使用 react 來開發應用帶來的的一些好處:

用 React 開發小程序的探索之路

react 和 小程序是有一些共同特點的

  • View = F(Data),都是通過數據來驅動視圖模型
  • 同時都是用一種類似的 API 來驅動整個視圖的更新 (小程序:this.setData(), react:this.setState() )

正因為這樣,也是更加想用 react 來開發小程序。 經過進一步的研究發現,小程序和 react 之間的差異是非常大的 主要是由於三大塊的差異:

JS 代碼對比:

用 React 開發小程序的探索之路

生命週期對比:

用 React 開發小程序的探索之路

模板對比:

用 React 開發小程序的探索之路

這麼大的差異導致我們想用 react 來開發小程序的難度非常之大,所以我們應該怎麼使用 react 來開發小程序呢? 仔細思考一下我們的需求,我們是希望通過 react 語法的代碼來開發小程序,那麼其中的核心工作就是將 react 代碼通過某種轉換操作,變成小程序可以運行的代碼。這樣一種在兩種語法之間轉換的這種操作其實就涉及到一個編譯原理。 編譯原理的一個大致過程大概如圖所示:

用 React 開發小程序的探索之路

其中最核心的就是把源代碼編譯成 AST (虛擬語法樹),然後將 AST 進行轉換操作得出目標代碼。 在 JS 中,它是有自己的 AST 規範來進行定義,這個規範就是 ESTree Spac

在 JS 領域中,有非常多的 JS 的解析器,來幫你把代碼轉換成語法樹的工具,其中最廣為應用的就是 BABEL。

用 React 開發小程序的探索之路

它提供了一套非常完成的工具來幫你做代碼轉換。 從源代碼到語義分析,我們都可以藉助 BABEL 來進行轉換。 在這之後的語法樹轉換、代碼優化還是需要們自己來進行的,這一部分也是非常繁瑣且複雜。

用 React 開發小程序的探索之路

在 Taro 中,我們通過在編譯時處理以及運行時適配來轉換成小程序代碼,

編譯時的處理:

用 React 開發小程序的探索之路

用 React 開發小程序的探索之路

用 React 開發小程序的探索之路

用 React 開發小程序的探索之路

在 JSX 中,通常有各種各樣的寫法:

用 React 開發小程序的探索之路

這導致在編譯的時候非常複雜,需要做大量的測試用例來保證轉換是正常的。

代碼編譯出來時候,還是不能只在小程序上運行的,小程序需要一個運行時的適配來幫助我們把代碼運行在小程序裡面。 運行時的框架主要是一些生命週期的轉換適配,還有一些事件處理。

僅僅這些是不夠的,如果真正需要投入開發使用還是有點差距的。這個時候我麼你需要一個開發工具來進行配合。

用 React 開發小程序的探索之路

同時,Taro 來提供了一些貼心的功能,來幫助我們獲得良好的開發體驗

  • 智能的代碼提示
  • 健全的錯誤代碼檢查

第三部分:重生之路

開源之初,由於種種原因,Taro 的微信小程序端組件化採用的是小程序