Flutter for Web 詳細預研

首先感謝@棲冰 @祖建國 一塊兒對FFW的預研作的投入!css

背景

Google在最新的Google I/O上推出了Flutter for Web,旨在進一步解決一次代碼,多端運行的問題。Flutter for Web還處於早期試驗版,官方不建議在生產環境上使用。那麼到底它的實際狀況怎麼樣呢? 咱們作了一次預研。指望此次預研的結果能夠幫你決定是用,仍是不用FFW。html

Flutter for Web原理

Flutter for Web和Flutter在上層都是Dart環境,二者不一樣的是,Flutter的Dart代碼運行在Dart虛擬機中,界面由Flutter引擎處理,經過Skia繪圖引擎經由GPU繪製到屏幕上。而Flutter for Web的Dart代碼編譯成JavaScript,界面上部分轉換成標準的html標籤,部分轉換成經過Canvas繪製的自定義標籤,最終構成一個dom樹。
這個原理上的差別很是重要,這直接可讓咱們經過原理得出下面的結論:前端

Flutter for Web的一致性和體驗上存在矛盾

若是Flutter for Web追求(和Flutter)完美的一致性,勢必須要大量使用Canvas去繪製,而Canvas去繪製組件的性能(尤爲在移動端)至少不會比html標籤好。若是FFW追求性能極限而使用大量標準的html標籤,這就會帶來和Weex、RN等同樣的一致性問題:對於Flutter全部的控件都是一套代碼在繪圖引擎上繪製,對Flutter for Web若是要使用大量html標籤,那如何保證一致性呢?只能靠大量精細的打磨工做了。因此FFW必需要處理好這個平衡。android

爲啥使用canvas繪製性能不優於手寫html呢,定性的從幾個角度分析:ios

  1. FFW在canvas上繪製的組件帶有不少MD特點的視覺和動畫,好比陰影、Z軸變化等,這部分對性能的消耗要大於普通html標籤
  2. FFW是經過Dart的DSL轉成的dom樹結構,轉化後的dom樹十分複雜,不太可能比手寫的dom樹更簡潔
  3. 使用canvas的控件,其手勢事件的捕獲分發都是靠FFW框架本身實現的,emmmm
    雖然不排除Google大力出奇跡的狀況,可是無論怎樣,相同素質的開發人員,相同的界面,性能上也不可能優於html+css+js

另一點,若是FFW在原理上涉及大量HTML標籤的轉化,那就勢必會涉及到碎片化的處理中,瀏覽器的碎片化程度可一點都不比Android系統的碎片化小。像Flutter自己之因此被那麼多人看重,就是由於其經過繪圖引擎這一層,完美的避開了碎片化,保證一致性。
因此最好的平衡就是,只有有限的一部分標準的html標籤能夠被FFW複用,其必須有幾點性質:nginx

  1. 標籤自己的功能簡單又直觀
  2. 最好不要有直接圖形化的展現,或者只負責簡單的圖形化展現(好比畫方形)
    那幾個比較典型的標籤就是<p><div>這種了

Flutter官方就是這麼作的,因此個人結論是:
一致性上大致不會存在問題,性能上,FFW應該不會優於純手寫html標籤界面。git

官方現狀&建議

根據官網Github repo上的說法,咱們整理了一下:github

  1. Flutter for Web和Flutter目前暫時是兩個倉庫,官方正在進行合併,沒有給出結論。這一點在工程上很是重要,它說明了幾個問題:web

    1. 目前官方對FFW的成熟度沒有信心,同時FFW的迭代速度也很快。
    2. 目前FFW和Flutter最多保證API同樣,實現原理差別可能很是大,同時不保證全部控件都已經在FFW上實現。
  2. 官方不建議應用在生產環境
  3. 目前插件能力十分有限,和系統交互的一些能力缺失,好比拍照等。
  4. 性能沒法保證,運行會慢,可能會有掉幀
  5. FFW中針對桌面的UI部分沒有完成(跟我無線有什麼關係?)
  6. 開發中只能在Chrome中調試(又有什麼關係?),release版是能夠運行在任意瀏覽器中(除了IE,另支持的最低版本存疑)。

實踐

對於這麼新的東西,官網上的內容的確很少,並且簡單來看這些問題好像也沒什麼,因此對於到底能不能用,咱們仍是須要抱着吃螃蟹的心態具體進去預研一下,爲了儘快弄清,我計劃找一個咱們app已經作好的flutter頁面,把它遷移成FFW,對整個遷移過程作個評估,再看下頁面效果,基本上就能得出結論了。
具體的遷移細節就不提了,官網也有遷移文檔,大致上就是這麼幾個步驟chrome

  1. 安裝Flutter for Web的工具webdev
  2. 改SDK依賴,新增Web文件夾(和以前存在的android、ios文件夾同級),新增一些其餘文件(index.html, main.dart等)。
  3. 將全部flutter代碼中依賴的flutter包,改爲flutter_web包
  4. 去掉全部不兼容的代碼,好比多語言、路由、Platform.isAndroid等等
  5. 編譯運行

實踐的主要目的,有如下幾個:

  1. 對總體坑的深度和廣度有個認知,方便推算出填坑成本
  2. 對FFW總體的性能和體驗有個把握,尤爲是咱們本身的頁面跑在FFW上是什麼體驗。
  3. 對FFW和JS相互調用有具體的瞭解,若是可行,那複用集團已有能力(好比mtop)的坑就會小不少

刪了一萬行代碼跑成功以後,最終在工程、開發體驗、用戶體驗上獲得一些結論,如下的結論中,體驗部分是我在個人mix2s上的感覺:

工程

  1. 支持debug和release模式,後者比前者性能高(差別很明顯)。

    1. debug模式支持代碼修改後自動從新編譯,和其餘的前端框架(我只用過Django)一致
  2. 支持hotreload,暫時沒有嘗試
  3. 支持webdev build命令編譯出index.html+js,能夠經過nginx作反向代理。
  4. 很是重要 編譯出來的代碼,gzip壓縮前,最簡單的helloworld的main.dart.js大小約爲500k左右,sample中的gallery大小約爲2M,閹割版的純展現用的訂單列表大小約爲1.3M。gzip對文本的壓縮率通常是80%,壓縮後也要動輒幾百k的大小。並且main.dart.js不加載完,界面是不會展現的。

開發體驗

  1. 很是重要flutter for web使用flutter_web庫,且不支持其餘許多插件,這會帶來幾個問題

    1. 工程上沒法優雅的解決flutter和flutter_web共存的狀況,最多搞個dart2的conditional import(這個特性可不在官方文檔中哦)
    2. 依賴flutter sdk的幾個庫,尤爲是多語言庫沒法應用在flutter_web上,而且Google確定不會再單獨爲flutter_web適配,而是在合併時作支持。這就意味着現階段全部依賴flutter sdk的庫不能被flutter_web使用。
  2. 調試困難

    1. 錯誤日誌能夠打印到瀏覽器的console中,可是try catch部分的堆棧很差拿
    2. 瀏覽器中的堆棧很複雜,可是基本上能找到出錯的dart代碼
    3. 目前沒有發現單步調試的能力
  3. Platform.isAndroid所有報錯,針對Android和iOS作差別化展現目前還不知道有沒有其餘方法能夠作到。
  4. 目前沒有發現控件的api不一致的地方,不過有些控件的行爲十分異常,好比下拉刷新,在Android手機上常常卡死、失效。猜想重交互的一些控件都有可能存在相似的問題,可是測一遍的成本過高。
  5. 圖片控件NetworkImage能夠直接用,可是如今來看有些糊,不肯定是官方控件的問題,仍是咱們作的cdn url策略有問題。
  6. dart代碼能夠調用js,開發體驗和反射相似,而且須要處理JS類型和Dart類型的轉換。Dart和JS的交互速度未知。只能說哪怕FFW有不少瀏覽器的API不支持,也能夠經過JS來擴展能力。
  7. Dart和Js語言自己的差別會帶來測試和兼容成本的增長,雖然Dart能夠編譯成Js,可是跑在DartVM上的Dart的表現,和其編譯成Js運行在瀏覽器中的表現並不徹底相同。好比對於以下代碼

    Map<String, String> query = null;
    val b = query["abc"];

    在DartVM中該代碼能夠執行,結果是b=null;可是編譯成Js之後運行時由於query爲null,會報空指針。

用戶體驗

使用了chrome、uc、小米自帶瀏覽器分別試了一下訂單列表和官方的sample-gallery界面,體驗以下:

  1. 加載速度差很少,由於是局域網環境,感知不到差別。
  2. 很是重要打出的惟一的main.dart.js和部分資源文件(好比MaterialIcons)沒有加載出來的時候,界面不會展現。
  3. 幀率或者流暢度上,chrome > uc >> 小米自帶瀏覽器,其中chrome算是最流暢的體驗,可是sample中的一些動畫和頁面轉場也能夠看到明顯的卡頓。
  4. 文字展現上,看flutter for web的界面,chrome對大部分文字處理的很清晰,小米自帶瀏覽器看文字明顯模糊。對比下面兩張圖,點開放大以後查看,FFW頁面的文字模糊的很明顯。

  1. 全部瀏覽器都不能選中文字複製粘貼。flutter for web應該是以canvas處理展現文字的,這樣才能解釋爲啥有的字體size會模糊,而且不能選中文字。
  2. iOS的safari和chrome訪問demo頁,TextField整個不可用,包括如下問題:

    1. 軟鍵盤彈出邏輯詭異,大部分時候彈出自動縮回,小部分時候正常彈出(Android這部分表現正常);但焦點轉移的時候不會自動收回
    2. safari不能輸入文字,chrome能夠輸入(Android這部分表現正常)
    3. 能夠選中文字,複製和粘貼不生效(Android問題相同)
    4. 焦點到TextField的時候界面會自動放大,這個時候很難縮放回去(Android這部分表現正常)

總結

按照上面的,總體總結一下,Flutter for Web有幾個比較嚴重的問題,不解決的話估計是沒法應用到生產環境上的:

  1. 包大小問題,這會帶來幾個問題:

    1. FFW的包遠大於正常h5的包,對流量和頁面加載速度都是很大的挑戰
    2. FFW打成一個JS包,多個FFW頁面沒法對公共組件進行復用,進一步形成浪費。
    3. FFW的js包不加載完,頁面沒法展現,用戶體驗極差;而H5能夠漸進加載,js能夠後入場。
  2. SDK分離的問題,這也會帶來幾個問題:

    1. 工程上,很難優雅的解決兩個SDK並存的問題
    2. 能力上,依賴Flutter SDK的官方庫,好比多語言庫,不支持FFW SDK。只能自研一套多語言方案。
  3. 表單場景不要用FFW,上述說到的TextField的問題不知可否在應用層去解。
  4. 一些重交互的組件,好比下拉刷新等,存在問題,幾乎沒法使用。不肯定總體組件的質量狀況如何,挨個去當作本太大。

結論

  1. 沒有很是強的業務訴求或者技術推進,不要在目前嘗試在生產環境使用Flutter for Web。
  2. 若是有填坑的決心,而且捨得投入,而且對包大小不關心,對幀率等用戶體驗也不看重,能夠考慮現階段進行嘗試。
  3. 我我的判斷填坑成本在100人日以上(上限未知),而且有些坑(包大小)可能根本填不了。
  4. 何時能夠再次跟進?我認爲在FFW合併進Flutter SDK的時候,至於他們具體的規劃須要問下Google的人了。

填坑指北

本節的主要目的是列出假設要作FFW,咱們須要作的技術項和對應方案。



本文做者:shoulder

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索