框架設計:小程序框架與組件化如何選型定製

著做權歸做者全部。商業轉載請聯繫 Scott 得到受權,非商業轉載請註明出處[務必保留全文,勿作刪減]。

螞蟻雄兵的年代,人人皆可爲王。前端

現在早已經是全民聯網年代,能夠發現本身的父母大姑大姨等親戚甚至爺爺奶奶,只要他們在使用千元智能機了,不管是看頭條仍是微信仍是抖音,都在參與整個互聯網的流量和內容的產生,他/她們經過手機消費了本身的時間,同時爲全部的產品提供了更多人物畫像的行爲數據,不管是上翻下翻仍是留言點贊,每個 APP 都是一個獨立的平臺,而在這兩年,冉冉升起的區別於 APP 的新應用平臺,非小程序莫屬:vue

上圖是從阿拉丁公佈的數據報告中截取引用過來的,整個 2018 年,基於小程序生態的融資規模是 80 億,是 2017 年的整整 8 倍,小程序幾乎紮根了全部領域的全部層面,並且除了微信小程序,其餘小程序小應用也都在佈局:git

在整個泛小程序生態崛起的過程當中,許多創業公司都主動登船,小菜也不例外,咱們是在 2018 年 3 月份開始技術預研和擁抱小程序生態,至此 1 年咱們業務上收穫頗豐,而技術這裏,也略有積澱,就跟你們分享小程序這塊咱們的思考和沉澱。github

用原生仍是用框架

小菜前端的個別同窗,包括我都有過一些開發小程序的經驗,沒使用任何框架就用小程序原生語法來實現,但小程序的功能都比較簡單,因此也天然沒遇到太大的工程挑戰,而咱們 2018 年要啓動的小程序產品具備兩個特徵:第一個是功能和交互足夠的複雜,第二是迭代速度要很是快,兩週就要首版上線,以後每週至少發一到兩個版本,基於這樣的業務背景,咱們也就毅然的選擇使用框架而非原生,但這個決策帶來的後期風險也的確超出了咱們的預期。面試

若是咱們再回到一年前作選型,估計仍是會選擇框架,但至少不會那麼樂觀的 All in 其中,而是擇時機儘早切回原生(雖然咱們目前已經是半原生)。因此給你們的建議是:若是產品功能相對簡單,一二十個頁面也沒有太奇怪的交互和太大的列表數據量,用框架用原生均可以,開發週期短的話就用框架,實際上市面上看到的絕大多數小程序都不屬因而複雜應用,用框架都能很好很快的 hold 住,但反過來假如你要實現的產品交互和前端列表數據量較大,圖片圖表視頻多媒體複雜搜索應有盡有,那麼能用原生就用原生。redux

如何選擇框架

框架的核心價值就是效率,一旦咱們決定使用框架,那麼就要把當下及將來市面上可用的小程序框架,作一個必要的比較和選擇,這個過程一般會比較糾結。由於截止到 2019 年,還並無一個小程序框架足夠足夠的好,你們都在六七十分上下,那咱們能夠從哪些方面來考慮呢?小程序

小菜前端最初選型框架主要考慮以下幾個方面(都很必要但優先級程度自上向下依次下降):微信小程序

  • 框架的成熟程度與開發效率 - 是否知足產品迭代需求
  • 多端(H5/小程序)的兼容程度 - 是否知足產品的端覆蓋需求
  • 配置成本/易用性/拓展性 - 是否知足工程師的工程架構需求
  • 總體性能的表現 - 是否能頂得住複雜交互和大數據列表
  • 團隊成員的學習成本 - 是否有必要的人員和技術棧儲備
  • 框架背後的團隊實力 - 是否有足夠好的工程實踐和開發支持
  • 框架在社區的沉澱和生態 - 是否有羣衆基礎和社區方案
  • 框架是不是 KPI 產品 - 是否會慢慢 Bug 不修棄坑跑路

整體作選型的路子是優先保產品,再看工程質量及合理性,最後看社區及開發者生態健康程度。緩存

很惋惜,即使咱們考慮了這麼多,限於當時(2018 年 3~5 月)的小程序框架生態太過早期也太單薄,咱們最終選擇了美團的 MPVue(實際上沒得選),但上面的參考項今天看來對你們依然是通用的,當時的比對過程我再給你們呈現下,幫你們加深下這個選型運用的過程:微信

首先針對可否優先保產品,也就是框架成熟程度和開發效率,多端兼容程度這塊,咱們實際上只有 wepy,MPVue,Taro 可選,針對他們三個,咱們是這樣比對的:

  • 社區生態是否足夠活躍
  • 跨端遷移成本
  • 框架核心團隊是否背靠大廠,是不是 KPI 產物
  • 開發效率問題,更可能是踩坑時間問題

其次,針對工程質量與合理性,也就是框架的配置成本/易用性/拓展性,總體性能這塊,咱們是這樣評估的:

  • 框架上手成本
  • 底層工程架構基建是否支持到位
  • 性能問題: 先上再說,過得去就好,剩下的就慢慢優化

最後,針對社區/開發者生態,也就是團隊成員既有技術棧、社區反饋和生態這塊,咱們是這樣評估的:

  • 團隊成員中是否有人具有相應的技術棧能力
  • 框架是否支持已有的庫快速接入
  • 社區對於該框架的反應如何,是否還屬於半成品或者存在 Bug 不少的問題

如何作組件化

小菜最初的產品端載體主要是 APP 和 PC Web,尤爲是 APP,有 7 個之多,因此 RN 的組件化在 2018 年是有過兩個大版本的累計了好幾十個,但這個對於小程序來說遠水解不了近渴,而小程序的頁面數目愈來愈多,組件複用變成了剛需,因此咱們開始了小程序的組件建設之旅。

基於 MPVue 在小程序裏寫組件,也是比較神傷。由於小程序端代碼是靜態的(即提早編譯好的模版), 因此像 HOC 就沒辦法用了(還有不少其餘一些 Vue 語法糖編譯不了), 咱們這裏用的都是 mixins,基礎的 mixins 有不少:

  • 函數調用相關(去抖/節流)
  • 列表加載相關
  • 用戶基礎信息/微信信息
  • 數據初始化相關
  • 分享調用相關
  • 頁面下拉/滾動相關
  • 收集 Form Id
  • 受權處理相關

基於 mixins 就能夠來設計組件了,一旦決定要抽象出一個組件,咱們主要考慮以下因素:

  • UI/功能的耦合程度
  • 內外部調用的耦合程度
  • 組合組件(組件間的通訊層)
  • 組件性質(基礎/業務)
  • 兼容問題
  • 後期擴展能力

咱們已經沉澱的組件有:

  • 上傳組件(Upload)
  • Tabbar
  • Spinner
  • Radio/Radio Group
  • Video
  • Cell
  • Input/Textarea
  • SearchBar
  • 受權/登陸彈窗 組件
  • 保存/預覽圖片 組件
  • 圖片懶加載/佔位 組件
  • 語音錄製/播放 組件(Record-bubble/Record-button)
  • 頁面異常狀態組件 (102/404)
  • 其餘業務組件......

這些組件裏面:

好比 Input/Textarea 組件,它須要重點考慮 UI/功能的耦合,要如何設計?

  • 組件複雜度高的話,能夠切分數據服務層與 UI 層,採用 Mixin 混合抽象方法到 UI 層裏。

好比受權/登陸彈窗組件,它須要重點考慮內外部調用的耦合,要如何設計?

  • 組件須要具有單一職責,不能圖方便把不少東西都耦合進去
  • 如何和其餘組件配合使用

好比 Upload Group 組件,它屬因而組合組件,要如何設計?

  • 上傳發生異常的處理與上拋。
  • 組合層之間調用的 Hook。
  • 注意 Props 的透傳與值的雙向綁定。

好比語音錄製/播放組件,它須要組件性質,要如何設計?

  • 業務級別的組件,在複雜度高的狀況下,也能夠考慮切分 UI/數據服務層。
  • 若是通訊層較複雜的話,能夠考慮相似 redux 的設計,下層組件 dispatch action 到上層,上層統一管理 action 並 分發數據/事件 給下層組件。

除此之外,組件設計的時候還要兼顧小程序端上與 Vue 的差別性。好比生命週期(組件與頁面),在 MPVue 編譯完後, Vue 組件生命週期並不會編譯成小程序組件的生命週期,說白了就是須要你熟悉兩套生命週期:  Vue 組件生命週期與小程序組件/頁面生命週期。

  1. MPVue 編譯完的 Vue 組件生命週期並不會和 小程序組件生命週期的調用一致,好比第二次點開同一個頁面,非頁面級別的組件 mounted 永遠只會調用一次(除非你在組件或者組件上層掛了 v-if ),而實際上這個組件在小程序裏被調用了兩次 attached 小程序組件生命週期。
  2. 更不用說 beforeMount/onUnload 的問題了。
  3. 頁面數據緩存問題,小程序自己會緩存打開過的頁面數據,常見場景就是商品詳情頁面,第二次打開的時候,在進行頁面數據更新以前,頁面並非空狀態,而是上一次詳情的數據。處理的話就有不少種方法了,能夠在 beforeMount/onUnload/其餘生命週期 裏初始化頁面數據及置空全部狀態,具體就看你怎麼設計和抽象了,最主要的目的仍是讓開發者儘量少的感知/手動調用。

除了要考慮以上這些問題以外,咱們還須要去解決端上的兼容問題以及框架帶來的問題。

微信端的兼容問題簡直是層出不窮,不只和機型、系統版本有關,甚至還和微信版本有關。因此當遇到這一類問題的時候,咱們只能求助於 微信開發者社區,期待有相應的解決方案。

框架帶來的問題有時候就有點噁心了。好比說 MPVue 並不支持動態的傳入 input 的 type 屬性,這就致使若是咱們須要文本鍵盤、數字鍵盤、帶小數點數字鍵盤等等這一類的 input 時,咱們須要每種類型都寫一個 input 組件,平白增長了代碼量,而且定位到問題也不方便。

逃不過的原生能力

以上咱們探討了框架選型和組件化設計,最後再回歸到咱們認爲很是核心的一個能力,就是小程序的原生開發和優化能力,MPVue 編譯完的代碼運行時的性能在不少場景裏並不達到你的要求,好比輸入組件的雙向綁定之光標閃爍/內容回退,,大數據量之操做延遲等等...... (沒遇到過的同窗自行搜索)。總的來講就是 MPVue 底層對於數據的操做實現的很稀爛,這個問題也只有當咱們將項目作大了才遇到。

當遇到相似上面這種性能問題的時候,就避免不了去尋找解決方案。但所謂的解決方案頗有限,要麼換框架,這時候已經上車,全量換框架工程太過浩大不敢想。要麼寫原生,寫原生不只工程量也浩大,並且原生代碼的複用成本也難度不小,這就是框架選型帶來的後續維護成本和風險了。

但問題是躲不過去的,終究要解決。除了上面這幾點須要去衡量的以外, 還要衡量一些非技術因素:

  • 產品發展形態/可預見的趨勢:隨着業務的發展以及小程序的權限收縮,爲了繼續擴大產品的可觸達範圍,勢必會新增更多的端。
  • 用戶羣體:須要去收集用戶的地理信息、手機型號、網絡環境等等,綜合這些數據去優化相應的點,作到有的放矢。

咱們最終仍是決定當部分組件替換爲原生組件,好比:

  • MPVue 寫的 input/textarea 在輸入的時候就會出現光標閃爍/內容回滾的異常(緣由就不贅述了),因此使用小程序原生語法重寫了 input/textarea 組件,主要目的就是讓組件的輸入可以脫離 MPVue 的更新,直接組件內部走小程序的 setData ,由於當時 MPVue 尚未對數據更新作 diff 操做,目前聽說作了一層 diff (實際效果你們本身去測評吧)
  • 產品中的文章詳情須要 Markdown 渲染,由於文章內容相對來講都是數據量比較大的,使用 MPVue 去對這部分數據進行解析的話性能會相對來講較差。所以咱們也使用了原生去實現了一個 Markdown 渲染的組件。

其實除了將組件替換爲原生組件以外,咱們還能夠去優化原生的 setData 方法,具體內容能夠閱讀 westore 這個庫,進一步提高性能。

最終,咱們的架構慢慢就會變成了這樣:Vue 會慢慢成爲一個數據注入/數據分析/事件分發三者集合的中心樞紐同樣的存在,底層是由各類高性能的原生組件,上層是由 Vue 來分發事件給不一樣組件,注入數據到不一樣組件裏,收集埋點行爲/事件。

這樣一個現狀依然有它新的問題,首先是多端複用成本低,如今還沒法一套代碼在 H5/小程序裏所有通用,其次是小程序原生學習成本仍是比框架要高,這對於不熟悉原生的同窗都是一個不小的技術學習成本。

當下的困境

當下來看,咱們以前選擇的 MPVue 已經不能很好地支撐業務需求了。其一是由於 Vue 與咱們的主體技術棧的分割,二來 MPVue 並不能支持跨多個平臺開發。

跨多平臺開發已是當下的一個迫切需求。假如一個需求須要維護多端的代碼,那麼勢必會須要更多的前端資源投入,這個成本是難以接受的。所以咱們也開始考慮究竟是使用市面上相似 Taro 這樣的框架仍是選擇自研,二者的選擇都有各自的好處。選擇 Taro 這樣的框架可以讓咱們迅速進入開發,可是長遠來看免不了可能會出現 MPVue 相似的維護問題;選擇自研的話雖然不會存在維護上的問題,可是會短時間內須要投入更多的前端資源。

以上這些問題就是咱們當下遇到的一個困境,選擇任何一個方案均可能對未來形成巨大的問題,就好比當初咱們選擇 MPVue 那樣。

Scott 近兩年不管是面試仍是線下線上的技術分享,遇到許許多多前端同窗,因爲團隊緣由,我的緣由,職業成長,技術方向,甚至家庭等等緣由,在理想國與現實之間,在放棄與堅守之間,搖擺不停,心酸硬扛,你們能夠找我聊聊南聊聊北,對工程師的宿命有更多的瞭解,有更多的看見與聽見,Scott 微信: codingdream,也能夠來 關注 Scott 跟進個人動態

2.png
1.png

相關文章
相關標籤/搜索