中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
GMTC | 《小程序跨框架開發(fā)的探索與實(shí)踐》演講全文

前言:隨著小程序開發(fā)的熱度上升,小程序開發(fā)框架也層出不窮。但目前每個框架都會綁定一個專屬 DSL,如類 React 或者類 Vue,在一個框架內(nèi),開發(fā)者無法根據(jù)團(tuán)隊(duì)技術(shù)棧自由選擇 DSL,同時也無法共享框架本身的生態(tài)與工具。

本次分享將為大家介紹 Taro 如何將各種語法的前端框架運(yùn)行在小程序上,討論一個框架支持多 DSL 的實(shí)現(xiàn)探索,使得開發(fā)者可以使用任意熱門框架/語法/DSL 來編寫小程序應(yīng)用,同時復(fù)用相關(guān)生態(tài)。

小程序開發(fā)的歷程

2017 年 1 月 9 日凌晨,萬眾期待的微信小程序正式上線。

在此之前,京東投入一個前端小團(tuán)隊(duì),經(jīng)過一個月的封閉式開發(fā),以一周一個版本的速度進(jìn)行迭代,終于在第一時間發(fā)布了自己的 「京東購物」 小程序,盡管功能和界面現(xiàn)在看起來有些簡陋,但在當(dāng)時是完全符合微信小程序「觸手可及,用完即走」的理念。

當(dāng)然,隨著整個項(xiàng)目的不斷迭代,現(xiàn)在的 「京東購物」小程序在設(shè)計(jì)、交互以及功能復(fù)雜度已經(jīng)全面向 APP 端看齊,這里面的工程化實(shí)踐已經(jīng)由 劉慧敏 老師在 GMTC 全球大前端技術(shù)大會(北京站)2019[1] 進(jìn)行過分享,有興趣的可以下載 PPT:京東購物小程序工程化之路[2]。

當(dāng)時的微信小程序的開發(fā)存在一些缺點(diǎn),比如依賴管理混亂、工程化流程落后、ES Next 支持不完善、命名規(guī)范不統(tǒng)一等。這些問題在現(xiàn)在看來都已經(jīng)有了各種官方或非官方的解決辦法,但是在當(dāng)時小程序開發(fā)的探索階段,這些問題都是一些痛點(diǎn)問題。

有句話我個人特別喜歡,那就是「當(dāng)一門語言的能力不足,而用戶的運(yùn)行環(huán)境又不支持其它選擇的時候,這門語言就會淪為  “編譯目標(biāo)”  語言」。

縱觀整個前端的歷史,無論是 CSS 預(yù)處理器的大行其道、各種模版的流行,還是 CoffeeScript 乃至 TypeScript[3] 的誕生,都印證了這個說法,微信小程序這里也不例外。因此,各種小程序開發(fā)框架如百花齊放,層出不窮。

這些小程序開發(fā)框架最主要的區(qū)別是 DSL,這點(diǎn)從 logo 顏色上就可以看出來,除了滴滴的 Chameleon[4] 是自定義 DSL 外,其余的綠色的 logo 是遵循了 Vue 語法(如 mpvue ),藍(lán)色的 logo 是遵循了 React 的語法(如 Taro)。

在微信小程序之后,各大廠商紛紛發(fā)布了自己的小程序平臺,比如:支付寶、百度、頭條、QQ 等,再加上快應(yīng)用、網(wǎng)易、360、京東等,小程序的賽道越來越擁擠,開發(fā)人員需要適配的小程序平臺越來越多,因此,各大小程序開發(fā)框架也紛紛進(jìn)行了多端適配。

因此,站在這個時間節(jié)點(diǎn)反過來回顧整個小程序開發(fā)框架的進(jìn)程,你會發(fā)現(xiàn)整個 2018 年乃至 2019 年初,小程序的開發(fā)框架主要的區(qū)別和重心在于:DSL 以及 多端適配

Taro 的起源與初心

正所謂「業(yè)務(wù)孵化技術(shù),技術(shù)服務(wù)業(yè)務(wù)」,Taro[5] 的誕生源自于業(yè)務(wù)需求的增加,當(dāng)時我們的團(tuán)隊(duì)需要同時負(fù)責(zé):京東購物,TOPLIFE 等業(yè)。團(tuán)隊(duì)人力資源捉襟見肘,與此同時,以上的業(yè)務(wù)都或多或少存在多端的需求,比如 微信小程序、H5、React Native(京東的主流 APP 基本都內(nèi)置了 React Native 渲染引擎),而且可以預(yù)見的是,以后很有可能需要適配更多的小程序平臺,而每個端開發(fā)一套代碼又不現(xiàn)實(shí),會導(dǎo)致:研發(fā)成本上升,代碼維護(hù)困難

當(dāng)時我們團(tuán)隊(duì)自研了一款 類 React 框架:Nervjs[6], 整個團(tuán)隊(duì)的技術(shù)棧因此全部轉(zhuǎn)向了 React ,而當(dāng)時市面上又沒有一款遵循 React 語法的小程序框架,因此,我們開發(fā)了 Taro,希望能夠使用 React 語法寫小程序的同時,通過「Write once Run anywhere」來實(shí)現(xiàn)跨端的。

整個 Taro 框架從 2018 年 6 月 7 日開源至今,一致保持著高速迭代,這些迭代主要集中在三個方面:

  • 多端適配:從一個端到多個端
  • 開發(fā)體驗(yàn):如支持 React Hooks、CSS Modules、Mobx 等
  • 社區(qū)共建:如 Taro 論壇[7]Taro 物料市場[8] 等平臺,以及后面發(fā)布的 社區(qū)共建計(jì)劃[9]

經(jīng)過團(tuán)隊(duì) 一年多的努力,Taro 得到了社區(qū)的廣泛認(rèn)可,截止 2019 年 12 月 18 日,Taro 已擁有 22254 Stars 和 250 名 Contributors,社區(qū)主動提交的開發(fā)案例 150+:taro-user-cases[10],其中不乏多端案例。

但是盡管如此,Taro 還是存在一些問題無法解決,或者說:沒那么好解決。比如:和 React DSL 強(qiáng)綁定、JSX 適配工作量大、社區(qū)貢獻(xiàn)復(fù)雜等。這些問題歸根到底,很大一部分是 Taro 的架構(gòu)問題。

因此我們團(tuán)隊(duì)也一直在等待一次合適的機(jī)會,對整個架構(gòu)進(jìn)行一次提升,同時修復(fù)一些項(xiàng)目快速迭代欠下的技術(shù)債。

最主要的是,單純的項(xiàng)目維護(hù)迭代已經(jīng)滿足不了我們團(tuán)隊(duì)躁動的心,我們渴望借此機(jī)會進(jìn)行一次技術(shù)突破。

小程序跨框架開發(fā)的探索

在講 Taro 架構(gòu)之前,我們先來回顧一下小程序的架構(gòu)。

微信小程序主要分為 邏輯層視圖層,以及在他們之下的原生部分。邏輯層主要負(fù)責(zé) JS 運(yùn)行,視圖層主要負(fù)責(zé)頁面的渲染,它們之間主要通過 EventData 進(jìn)行通信,同時通過 JSBridge 調(diào)用原生的 API。這也是以微信小程序?yàn)槭椎拇蠖鄶?shù)小程序的架構(gòu)。

由于原生部分對于前端開發(fā)者來說就像是一個黑盒,因此,整個架構(gòu)圖的原生部分可以省略。同時,我們我們對 邏輯層 和 視圖層 也做一下簡化,最后可以得到小程序架構(gòu)圖的極簡版:

也就是說,只需要在邏輯層調(diào)用對應(yīng)的 App()/Page() 方法,且在方法里面處理 data、提供生命周期/事件函數(shù)等,同時在視圖層提供對應(yīng)的模版及樣式供渲染就能運(yùn)行小程序了。這也是大多數(shù)小程序開發(fā)框架重點(diǎn)考慮和處理的部分。

Taro 當(dāng)前架構(gòu)

Taro 當(dāng)前的架構(gòu)主要分為:編譯時運(yùn)行時。

其中編譯時主要是將 Taro 代碼通過 Babel[11] 轉(zhuǎn)換成 小程序的代碼,如:JSWXML、WXSS、JSON。

運(yùn)行時主要是進(jìn)行一些:生命周期、事件、data 等部分的處理和對接。

Taro 編譯時

有過 Babel 插件開發(fā)經(jīng)驗(yàn)的應(yīng)該對一下流程十分熟悉,Taro 的編譯時也是遵循了此流程,使用 babel-parser[12] 將 Taro 代碼解析成抽象語法樹,然后通過 babel-types[13] 對抽象語法樹進(jìn)行一系列修改、轉(zhuǎn)換操作,最后再通過 babel-generate[14] 生成對應(yīng)的目標(biāo)代碼。

詳情可以參考:babel-handbook[15]

整個編譯時最復(fù)雜的部分在于 JSX 編譯。

我們都知道 JSX 是一個 JavaScript 的語法擴(kuò)展,它的寫法千變?nèi)f化,十分靈活。這里我們是采用 窮舉 的方式對 JSX 可能的寫法進(jìn)行了一一適配,這一部分工作量很大,實(shí)際上 Taro 有大量的 Commit 都是為了更完善的支持 JSX 的各種寫法。

但盡管如此,我們也不可能完全覆蓋所有的情況,因此還是推薦大家按照官方規(guī)范書寫 React 代碼,同時,我們也提供了豐富的 ESlint 插件來輔助大家書寫規(guī)范的代碼。

這一塊我們團(tuán)隊(duì)內(nèi)部一直有個梗:如果你使用 Taro 開發(fā)感覺 Bug 少,那說明你的 React 代碼寫得很規(guī)范。

Taro 運(yùn)行時

接下來,我們可以對比一下編譯后的代碼,可以發(fā)現(xiàn),編譯后的代碼中,React 的核心 render 方法 沒有了。同時代碼里增加了 BaseComponentcreateComponent ,它們是 Taro 運(yùn)行時的核心。

// 編譯前
import Taro, { Component } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import './index.scss'

export default class Index extends Component {

  config = {
    navigationBarTitleText'首頁'
  }

  componentDidMount () { }

  render () {
    return (
      <View className=‘index' onClick={this.onClick}>
        <Text>Hello world!</Text>
      </View>

    )
  }
}

// 編譯后
import {BaseComponent, createComponent} from '@tarojs/taro-weapp'

class Index extends BaseComponent {

// ...

  _createDate(){
    //process state and props
  }
}

export default createComponent(Index)

BaseComponent 大概的 UML 圖如下,主要是對 React 的一些核心方法:setState、forceUpdate 等進(jìn)行了替換和重寫,結(jié)合前面編譯后 render 方法被替換,大家不難猜出:Taro 當(dāng)前架構(gòu)只是在開發(fā)時遵循了 React 的語法,在代碼編譯之后實(shí)際運(yùn)行時,和 React 并沒有關(guān)系

createComponent 主要作用是調(diào)用 Component() 構(gòu)建頁面;對接事件、生命周期等;進(jìn)行 Diff Data 并調(diào)用 setData 方法更新數(shù)據(jù)。

總結(jié)

因此,整個 Taro 當(dāng)前架構(gòu)的特點(diǎn)是:

  • 重編譯時,輕運(yùn)行時:這從兩邊代碼行數(shù)的對比就可見一斑。
  • 編譯后代碼與 React 無關(guān):Taro 只是在開發(fā)時遵循了 React 的語法。
  • 直接使用 Babel 進(jìn)行編譯:這也導(dǎo)致當(dāng)前 Taro 在工程化和插件方面的羸弱。

其它解決方案的架構(gòu)

小程序開發(fā)框架百花齊放,我們也從社區(qū)里得到了不少啟發(fā)。

接下來我們來看看 遵循 vue 語法的小程序開發(fā)框架的代表:mpvue[16] 是怎樣實(shí)現(xiàn)的。

看過 Vue 源碼的同學(xué)對上面的文件夾和架構(gòu)肯定熟悉,本質(zhì)上,mpvue 就是 fork 了一份 vuejs/vue@2.4.1 的代碼,保留了 Vue runtime 能力,同時添加了小程序平臺的支持。

具體在源碼中的表現(xiàn)就是:在 Vue 源碼的 platforms 文件夾下面增加了 mp 目錄,在里面實(shí)現(xiàn)了 complier(編譯時)runtime (運(yùn)行時)支持。

mpvue 的實(shí)現(xiàn)同樣分為:編譯時運(yùn)行時

mpvue 編譯時

其中編譯時做的事情和 Taro 很類似:將 Vue SFC 寫法的代碼編譯成 小程序代碼文件(JS、WXML、WXSS、JSON)。

最大的區(qū)別是 Taro 將 JSX 編譯成 小程序模版,而 mpvue 是將 Vue 模版編譯成 小程序模版。但是由于 Vue 模版和 小程序模版的相似性,mpvue 在這一塊的工作量比 Taro 少得多。

mpvue 運(yùn)行時

而 mpvue 的運(yùn)行時和 Vue 的運(yùn)行時是強(qiáng)關(guān)聯(lián)的,首先我們來看看 Vue 的運(yùn)行時。

一個 .vue 的單文件由三部分構(gòu)成: template, script, style 。

橙色路徑部分, template 會在編譯的過程中,在 vue-loader 中通過 ast 進(jìn)行分析,最終生成一段 render 函數(shù),執(zhí)行 render 函數(shù)會生成虛擬 dom 樹,虛擬 DOM 樹是對真實(shí) DOM 樹的抽象,樹中的節(jié)點(diǎn)被稱作 vnode 。

Vue 拿到 虛擬 DOM 樹之后,就可以去和上次老的 虛擬 DOM 樹 做 patch diff 對比。patch 階段之后,vue 就會使用真實(shí)的操作 DOM 的方法(比如說 insertBefore , appendChild 之類的),去操作 DOM 結(jié)點(diǎn),更新視圖。

同時,綠色路徑的部分,在實(shí)例化 Vue 的時候,會對數(shù)據(jù) data 做響應(yīng)式的處理,在監(jiān)測到 data 發(fā)生改變時,會調(diào)用 render 函數(shù),生成最新的虛擬 DOM 樹, 接著對比老的虛擬 DOM 樹進(jìn)行 patch, 找出最小修改代價的 vnode 節(jié)點(diǎn)進(jìn)行修改。

而 mpvue 的運(yùn)行時,會首先將 patch 階段的 DOM 操作相關(guān)方法置空,也就是什么都不做。其次,在創(chuàng)建 Vue 實(shí)例的同時,還會偷偷的調(diào)用 Page() 用于生成了小程序的 page 實(shí)例。然后 運(yùn)行時的 patch 階段會直接調(diào)用 $updateDataToMp() 方法,這個方法會獲取掛在在 page 實(shí)例上維護(hù)的數(shù)據(jù) ,然后通過 setData 方法更新到視圖層。

mpvue 整體原理圖也就如下:

一些總結(jié)與思考

因此,和 Taro 重編譯時輕運(yùn)行時不同,mpvue 算是:半編譯時,半運(yùn)行時。這點(diǎn)從代碼量的對比也能大致反映出來。

mpvue 的 WXML 模版和 Taro 一樣,也是通過代碼編譯得到的;不同于 Taro 運(yùn)行時和 React 無關(guān),mpvue 本質(zhì)上還是將 Vue 運(yùn)行在了小程序,且實(shí)現(xiàn)了 Vue@2.4.1 絕大部分特性(只有極少數(shù)特性由于小程序模版的限制未能實(shí)現(xiàn),如 :filter、slot、v-html);且整個框架基于 Webpack 實(shí)現(xiàn)了較為完善的工程化。

其他小程序框架的實(shí)現(xiàn)原理和效果上的差異性,也帶來了我們的一些思考:

  • 編譯時 OR 運(yùn)行時:當(dāng)初 Taro 選擇重編譯時的主要原因是處于性能考慮,畢竟同等條件下,編譯時做的工作越多,也就意味著運(yùn)行時做的工作越少,性能會更好;另外,重編譯時也保證了 Taro 的代碼在編譯之后的可讀性。但是從長遠(yuǎn)來看,計(jì)算機(jī)硬件的性能越來越冗余,如果在犧牲一點(diǎn)可以容忍的性能的情況下?lián)Q來整個框架更大的靈活性和更好的適配性,我們認(rèn)為是值得的。
  • 模版靜態(tài)編譯 OR 動態(tài)構(gòu)建:盡管 Taro 和 mpvue 的模版都是通過靜態(tài)編譯生成的,但是社區(qū)也不乏動態(tài)構(gòu)建的例子,比如:Remax[17]。
  • DSL 限制:我們能否實(shí)現(xiàn)一個小程序開發(fā)框架,擺脫 DSL 的限制?

新架構(gòu) Taro Next 的適配與實(shí)現(xiàn)

這一次,我們站在瀏覽器的角度來思考前端的本質(zhì):無論開發(fā)這是用的是什么框架,React 也好,Vue 也罷,最終代碼經(jīng)過運(yùn)行之后都是調(diào)用了瀏覽器的那幾個 BOM/DOM 的 API ,如:createElement、appendChild、removeChild 等。

因此,我們創(chuàng)建了 taro-runtime[18] 的包,然后在這個包中實(shí)現(xiàn)了 一套 高效、精簡版的 DOM/BOM API(下面的 UML 圖只是反映了幾個主要的類的結(jié)構(gòu)和關(guān)系):

然后,我們通過 Webpack 的 ProvidePlugin[19] 插件,注入到小程序的邏輯層。

這樣,在小程序的運(yùn)行時,就有了 一套高效、精簡版的 DOM/BOM API。

React 實(shí)現(xiàn)

DOM/BOM 注入之后,理論上來說,Nerv/Preact 就可以直接運(yùn)行了。但是 React 有點(diǎn)特殊,因?yàn)?React-DOM 包含大量瀏覽器兼容類的代碼,導(dǎo)致包太大,而這部分代碼我們是不需要的,因此我們需要做一些定制和優(yōu)化。

在 React 16+ ,React 的架構(gòu)如下:

最上層是 React 的核心部分 react-core ,中間是 react-reconciler,其的職責(zé)是維護(hù) VirtualDOM 樹,內(nèi)部實(shí)現(xiàn)了 Diff/Fiber 算法,決定什么時候更新、以及要更新什么。

Renderer 負(fù)責(zé)具體平臺的渲染工作,它會提供宿主組件、處理事件等等。例如 React-DOM 就是一個渲染器,負(fù)責(zé) DOM 節(jié)點(diǎn)的渲染和 DOM 事件處理。

因此,我們實(shí)現(xiàn)了 taro-react[20] 包,用來連接 react-reconcilertaro-runtime 的 BOM/DOM API:

具體的實(shí)現(xiàn)主要分為兩步:

  1. 實(shí)現(xiàn) react-reconcilerhostConfig 配置,即在 hostConfig 的方法中調(diào)用對應(yīng)的 Taro BOM/DOM 的 API。
  2. 實(shí)現(xiàn) render 函數(shù)(類似于 ReactDOM.render)方法,可以看成是創(chuàng)建 Taro DOM Tree 的容器。

經(jīng)過上面的步驟,React 代碼實(shí)際上就可以在小程序的運(yùn)行時正常運(yùn)行了,并且會生成 Taro DOM Tree,那么偌大的 Taro DOM Tree 怎樣更新到頁面呢?

首先,我們將小程序的所有組件挨個進(jìn)行模版化處理,從而得到小程序組件對應(yīng)的模版,如下圖就是小程序的 view 組件經(jīng)過模版化處理后的樣子:

然后,我們會:基于組件的 template,動態(tài) “遞歸” 渲染整棵樹。

具體流程為先去遍歷 Taro DOM Tree 根節(jié)點(diǎn)的子元素,再根據(jù)每個子元素的類型選擇對應(yīng)的模板來渲染子元素,然后在每個模板中我們又會去遍歷當(dāng)前元素的子元素,以此把整個節(jié)點(diǎn)樹遞歸遍歷出來。

整個 Taro Next 的 React 實(shí)現(xiàn)流程圖如下:

Vue 實(shí)現(xiàn)

別看 React 和 Vue 在開發(fā)時區(qū)別那么大,其實(shí)在實(shí)現(xiàn)了 BOM/DOM API 之后,它們之間的區(qū)別就很小了。

Vue 和 React 最大的區(qū)別就在于運(yùn)行時的 CreateVuePage 方法,這個方法里進(jìn)行了一些運(yùn)行時的處理,比如:生命周期的對齊。

其他的部分,如通過 BOM/DOM 方法構(gòu)建、修改 DOM Tree 及渲染原理,都是和 React 一致的。

Flutter 實(shí)現(xiàn)

提到 Flutter ,就不得不提 Flutter Web[21]Flutter Web 是在標(biāo)準(zhǔn)瀏覽器 API 之上實(shí)現(xiàn) Flutter 的核心繪圖層,本質(zhì)上也是最終調(diào)用了 BOM/DOM API。因此,理論來說,也是可以進(jìn)行適配的,但這一塊我們并不會投入太多的精力,最終會像快應(yīng)用一樣交給社區(qū)來實(shí)現(xiàn)和維護(hù)。

更多細(xì)節(jié)

接下來和大家展開聊一下 Taro Next 更多的細(xì)節(jié)實(shí)現(xiàn),比如:事件、更新、生命周期。

事件

首先的 Taro Next 事件,具體的實(shí)現(xiàn)方式如下:

  1. 在 小程序組件的模版化過程中,將所有事件方法全部指定為 調(diào)用 ev 函數(shù),如:bindtap、bindchange、bindsubmit 等。
  2. 在 運(yùn)行時實(shí)現(xiàn) eventHandler 函數(shù),和 eh 方法綁定,收集所有的小程序事件
  3. 通過 document.getElementById() 方法獲取觸發(fā)事件對應(yīng)的 TaroNode
  4. 通過 createEvent() 創(chuàng)建符合規(guī)范的 TaroEvent
  5. 調(diào)用 TaroNode.dispatchEvent 重新觸發(fā)事件

可以看到,Taro Next 事件本質(zhì)上是基于 Taro DOM 實(shí)現(xiàn)了一套自己的事件機(jī)制,這樣做的好處之一是,無論小程序是否支持事件的冒泡與捕獲,Taro 都能支持。

更新

無論是 React 還是 Vue ,最終都會調(diào)用 Taro DOM 方法,如:appendChild、insertChild 等。

這些方法在修改 Taro DOM Tree 的同時,還會調(diào)用 enqueueUpdate 方法,這個方法能獲取到每一個 DOM 方法最終修改的節(jié)點(diǎn)路徑和值,如:{root.cn.[0].cn.[4].value: '1'},并通過 setData 方法更新到視圖層。

可以看到,這里更新的粒度是 DOM 級別,只有最終發(fā)生改變的 DOM 才會被更新過去,相對于之前 data 級別的更新會更加精準(zhǔn),性能更好。

生命周期

相對與其他部分大刀闊斧的升級改造,生命周期可能是變動最小的部分之一。和之前類似,生命周期的實(shí)現(xiàn)是在運(yùn)行時維護(hù)的 App 實(shí)例 / Page 實(shí)例進(jìn)行了生命周期方法的一一對應(yīng)。

const config: PageInstance = {
  onLoad (this: MpInstance, options) {
    //...
  },
  onUnload () {
    //...
  },
  onShow () {
    safeExecute('onShow')
  },
  onHide () {
    safeExecute('onHide')
  },
  onPullDownRefresh () {
    safeExecute('onPullDownRefresh')
  }
  //...
}

新架構(gòu)特點(diǎn)

和之前的架構(gòu)不同,Taro Next 是 近乎全運(yùn)行。

新的架構(gòu)基本解決了之前的遺留問題:

  • 無 DSL 限制:無論是你們團(tuán)隊(duì)是 React 還是 Vue 技術(shù)棧,都能夠使用 Taro 開發(fā)
  • 模版動態(tài)構(gòu)建:和之前模版通過編譯生成的不同,Taro Next 的模版是固定的,然后基于組件的 template,動態(tài) “遞歸” 渲染整棵 Taro DOM 樹。
  • 新特性無縫支持:由于 Taro Next 本質(zhì)上是將 React/Vue 運(yùn)行在小程序上,因此,各種新特性也就無縫支持了。
  • 社區(qū)貢獻(xiàn)更簡單:錯誤棧將和 React/Vue 一致,團(tuán)隊(duì)只需要維護(hù)核心的 taro-runtime。
  • 基于 Webpack:Taro Next 基于 Webpack 實(shí)現(xiàn)了多端的工程化,提供了插件功能。

性能優(yōu)化

前面提到,同等條件下,編譯時做的工作越多,也就意味著運(yùn)行時做的工作越少,性能會更好。Taro Next 的新架構(gòu)變成 近乎全運(yùn)行 之后,花了很多精力在性能優(yōu)化上面。

再這之前??梢韵瓤匆幌?Taro Next 的流程和原生小程序的流程對比。

可以發(fā)現(xiàn),相比原生小程序,Taro Next 多了紅色部分的帶來的性能隱患,如:引入 React/Vue 帶來的 包的 Size 增加,運(yùn)行時的損耗、Taro DOM Tree 的構(gòu)建和更新、DOM data 初始化和更新。

而我們真正能做的,只有綠色部分,也就是:Taro DOM Tree 的構(gòu)建和更新、DOM data 初始化和更新。

Size

首先我們來看包 Size,下面的表格是 TodoMVC 的例子,在原生、Taro Old、Taro Next 等情況下的包大小對比,可以看到,引入 React/Vue 后,包大小在 Gzip 情況下大概增加了 30k 左右。

不過我們在前面一再強(qiáng)調(diào):和之前模版通過編譯生成的不同,Taro Next 的模版是固定的,然后基于組件的 template,動態(tài) “遞歸” 渲染整棵 Taro DOM 樹。也就是說,Taro Next 的 WXML 大小是有上限的。

隨著項(xiàng)目的增加,頁面越來越多,原生的項(xiàng)目 WXML 體積會不斷增加,而 Taro Next 不會。也就是說,當(dāng)頁面的數(shù)量超過一個臨界點(diǎn)時,Taro Next 的包體積可能會更小。因此,包 Size 的問題不足為慮。

DOM Tree

在 Taro DOM Tree 的構(gòu)建和更新階段,我們實(shí)現(xiàn)了一套僅實(shí)現(xiàn)了高效的、精簡版 DOM/BOM API,而且僅僅實(shí)現(xiàn)了必要的。

Github 上有一個倉庫 jsdom[22],基本上是在 Node.js 上實(shí)現(xiàn)了一套 Web 標(biāo)準(zhǔn)的 DOM/BOM ,這個倉庫的代碼在壓縮前大概有 2.1M,而 Taro Next 的核心的 DOM/BOM API 代碼才 1000 行不到。

因此,我們最大限度的保證了 Taro DOM Tree 構(gòu)建和更新階段的性能。

Update Date

在數(shù)據(jù)更新階段,首先前面有提到過,Taro Next 的更新是 DOM 級別的,比 Data 級別的更新更加高效,因?yàn)?Data 粒度更新實(shí)際上是有冗余的,并不是所有的 Data 的改變最后都會引起 DOM 的更新。

其次,Taro 在更新的時候?qū)?Taro DOM Tree 的 path 進(jìn)行壓縮,這點(diǎn)也極大的提升了性能。

最終的結(jié)果是:在某些業(yè)務(wù)場景寫,add、select 數(shù)據(jù),Taro Next 的性能比原生的還要好。

taro-benchmark

當(dāng)然,實(shí)驗(yàn)的數(shù)據(jù)總歸會有缺陷,最終具體的性能表現(xiàn),還要靠各種復(fù)雜業(yè)務(wù)場景的檢驗(yàn)。大家如果對 Taro Next 的性能感興趣的,可以自行跑一下 taro-benchmark[23] 包,對比一下結(jié)果。

我們也在一直持續(xù)的全方位優(yōu)化 Taro Next 的性能,具體可以關(guān)注 Taro Next 的最新的 Commit 。

總結(jié)及展望

Taro 未來規(guī)劃

Taro Next 將會在不久之后的 3.0 版本正式發(fā)布,支持使用 React/Vue 開發(fā)跨端小程序,然后在會在后續(xù)的迭代中拓展至其他端,并完善對應(yīng)的生態(tài)。

Taro 團(tuán)隊(duì)還是會將支持的重點(diǎn)放在 React/Vue,F(xiàn)lutter 和 Angular 會像快應(yīng)用一樣,交給社區(qū)來適配和維護(hù),快應(yīng)用就是華為的 Qiyu8[24]Issacpeng[25] 在幫我們進(jìn)行適配,非常感謝他們。

同時,我們還打造了 「Taro 移動端一站式研發(fā)平臺」,將先前積累的多端開發(fā)工作流和工程化的方案進(jìn)行了統(tǒng)一,并內(nèi)置了數(shù)據(jù)監(jiān)控、組件市場以及可視化搭建,當(dāng)前正處于內(nèi)測階段。

一點(diǎn)思考

  • 業(yè)務(wù)孵化技術(shù),技術(shù)服務(wù)業(yè)務(wù):這也是整個 Taro 項(xiàng)目從創(chuàng)建到迭代至今最重要的、感受最深的一點(diǎn)。
  • 自上而下 OR 自下而上:從開發(fā)者的角度自上而下看,React/Vue 的代碼書寫方式差異挺大的;然而站在瀏覽器的角度自下而上的看,它們的差別其實(shí)沒那么大,都是調(diào)用了 BOM/DOM 那幾個常用的 API。如果我們再往底層一點(diǎn),站在渲染層的角度,不同平臺之間的差異會不會也沒那么大?比如:Flutter。
  • Learn Once Write AnyWhere & Write Once Run AnyWhere:很多開發(fā)者更喜歡 React 提出的Learn Once Write AnyWhere,而我們 Taro 的口號是 Write Once Run AnyWhere,這一點(diǎn)也經(jīng)常導(dǎo)致我們經(jīng)常被人噴,這里說一點(diǎn)我自己的想法:Learn Once Write AnyWhere其實(shí)本質(zhì)上對開發(fā)者更友好,比如開發(fā)者只需要學(xué)習(xí) React 技術(shù)棧,就可以開發(fā) Web/移動端 應(yīng)用,但是對項(xiàng)目就沒那么友好了,每個項(xiàng)目都得維護(hù)一份代碼;而 Write Once Run AnyWhere 是對開發(fā)者沒那么友好(適配的端越多,適配的成本必然也會水漲船高,對開發(fā)者要求也很變高),但是根據(jù)我們的實(shí)踐,對項(xiàng)目會更友好,「一套代碼,多端適配」。當(dāng)然,這里適配的粒度,并不一定是項(xiàng)目級別的,其實(shí)在我們的具體實(shí)踐中,有相當(dāng)一部分是:業(yè)務(wù)級甚至是頁面級的。

寫在最后

正所謂「單絲不成線,獨(dú)木不成林」,Taro 發(fā)展至今早已不在屬于單一團(tuán)隊(duì)的項(xiàng)目了,而是整個 Taro 開發(fā)社區(qū)共同的項(xiàng)目。

最后,還是借此機(jī)會感謝一些社區(qū)所有幫助過 Taro 的成長的人,特別是 Taro 的貢獻(xiàn)者們,非常感謝!

同時也感謝受邀成為 TaroUI[26] 核心維護(hù)人員的 Garfield550[27] (小姐姐)、梁音[28]、ShaoQian Liu[29],他們將支撐起 TaroUI 的后續(xù)迭代與維護(hù)。

當(dāng)然還有在社區(qū)中樂于助人、積極貢獻(xiàn)的 zacksleo[30] 、Jay Fong[31]、loveonelong[32]lolipop99[33]、波仔糕[34]、原罪[35]lentoo[36] 、白領(lǐng)夏公子[37]YuanQuan[38]、 tourze[39]、 lingxiaoZhu[40] 等等。

此外,還要感謝一直默默為 Taro 發(fā)展提供寶貴建議的研發(fā)團(tuán)隊(duì):騰訊云、數(shù)字廣東、騰訊 CDC、網(wǎng)易嚴(yán)選、華為開源團(tuán)隊(duì)、招聯(lián)消費(fèi)金融等等。

長風(fēng)破浪會有時,直掛云帆濟(jì)滄海。

歡迎關(guān)注凹凸實(shí)驗(yàn)室博客:aotu.io[41]

或者關(guān)注凹凸實(shí)驗(yàn)室公眾號(AOTULabs),不定時推送文章:

參考資料

[1]

GMTC 全球大前端技術(shù)大會(北京站)2019: https://gmtc.infoq.cn/2019/beijing/

[2]

京東購物小程序工程化之路: http://ppt.geekbang.org/slide/download?cid=42&pid=2416

[3]

TypeScript: https://www.typescriptlang.org/

[4]

Chameleon: https://github.com/didi/chameleon

[5]

Taro: https://github.com/NervJS/taro

[6]

Nervjs: https://github.com/NervJS/nerv

[7]

Taro 論壇: https://taro-club.jd.com/

[8]

Taro物料市場: https://taro-ext.jd.com/

[9]

社區(qū)共建計(jì)劃: https://taro-club.jd.com/topic/680/taro-%E9%82%80%E4%BD%A0%E5%8A%A0%E5%85%A5%E7%A4%BE%E5%8C%BA%E5%85%B1%E5%BB%BA-%E7%A4%BE%E5%8C%BA%E5%85%B1%E5%BB%BA%E5%80%A1%E8%AE%AE%E4%B9%A6

[10]

taro-user-cases: https://github.com/NervJS/taro-user-cases

[11]

Babel: https://babeljs.io/

[12]

babel-parser: https://babeljs.io/docs/en/babel-parser

[13]

babel-types: https://babeljs.io/docs/en/babel-types

[14]

babel-generate: https://babeljs.io/docs/en/babel-generator

[15]

babel-handbook: https://github.com/jamiebuilds/babel-handbook/blob/master/translations/zh-Hans/plugin-handbook.md

[16]

mpvue: https://github.com/Meituan-Dianping/mpvue

[17]

Remax: https://github.com/remaxjs/remax

[18]

taro-runtime: https://github.com/NervJS/taro/tree/next/packages/taro-runtime

[19]

ProvidePlugin: https://webpack.js.org/plugins/provide-plugin/

[20]

taro-react: https://github.com/NervJS/taro/tree/next/packages/taro-react

[21]

Flutter Web: https://flutter.dev/web

[22]

jsdom: https://github.com/jsdom/jsdom

[23]

taro-benchmark: https://github.com/NervJS/taro-benchmark

[24]

Qiyu8: https://github.com/Qiyu8

[25]

Issacpeng: https://github.com/Issacpeng

[26]

TaroUI: https://github.com/NervJS/taro-ui

[27]

Garfield550: https://github.com/Garfield550

[28]

梁音: https://github.com/yinLiangDream

[29]

ShaoQian Liu: https://github.com/lsqy

[30]

zacksleo: https://github.com/zacksleo

[31]

Jay Fong: https://github.com/fjc0k

[32]

loveonelong: https://github.com/loveonelong

[33]

lolipop99: https://github.com/lolipop99

[34]

波仔糕: https://github.com/bozaigao

[35]

原罪: https://github.com/fwh1990

[36]

lentoo: https://github.com/lentoo/

[37]

白領(lǐng)夏公子: https://taro-club.jd.com/user/%E7%99%BD%E9%A2%86%E5%A4%8F%E5%85%AC%E5%AD%90

[38]

YuanQuan: https://github.com/YuanQuan

[39]

tourze: https://github.com/tourze

[40]

lingxiaoZhu: https://github.com/lingxiao-Zhu

[41]

aotu.io: https://aotu.io/

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
小程序開發(fā)框架技術(shù)分析選型
小程序第三方框架對比 ( wepy / mpvue / taro )
強(qiáng)烈推薦:絕對是最好的一個小程序開源框架
用Vue.js開發(fā)微信小程序:開源框架mpvue解析
目前最流行的前端開發(fā)框架
這幾個開源微信小程序, 永遠(yuǎn)的神!
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服