引言
2018 年 12 月,Google 釋出了 Flutter 1.0 正式版,並在2019年9月在釋出Flutter 的最新穩定版本:Flutter 1.9,同時,宣佈將flutter web 合併到master。flutter web立志於開發人員可以使用相同的程式碼,更快地釋出功能,並確保其跨裝置(Android、iOS、Web)體驗的一致性。
然而就最新的Flutter1.9.x而言,Flutter Web還處於技術預覽版階段,離真正應用到生產環境中還是有一些距離的。官方也不建議將其運用在生產上,後期將會有很多的優化,而且很多flutter的庫還未相容web環境,實踐中也發現很多的坑。
目標
將Flutter web 的Demo用docker與Jenkins完成自動化部署。
技術棧
Flutter Web
因為Flutter將web整合進專案當中,所以在建立web專案時,只要保證分支版本在1.5以上即可。
建立過程:
flutter channel beta
flutter upgrade
flutter config --enable-web
flutter create myapp
cd myapp
flutter run -d chrome複製程式碼
flutter config --enable-web
新增flutter對web的支援,可以使用Chrome
原理
為了使得一套程式碼可以共享到各個平臺,並且沒有差別,開發者保留最頂層的dart:ui,在瀏覽器用Web技術重新實現一次完整的dart:ui API。
將flutter專案編譯成web專案並且在瀏覽器中展示,一共分為三個階段:
- 建立Widgets
- 元素佈局
- 頁面繪製
建立Widgets
Widget的構建機制不依賴於應用程式執行的環境。該過程只需要例項化記憶體中的物件並跟蹤它們的狀態,當狀態改變時,計算佈局和繪畫所需的最小更新。將此部分移植到Web上非常簡單,當Dart團隊在dart2js中實現了super-mixin支援之後,編譯器將所有widget和widget框架編譯為JavaScript時幾乎沒有任何問題;
元素佈局
佈局系統有點棘手。最大的挑戰是文字佈局。其他所有Widget - Center,Row, Column, Stack, Scrollable, Padding, Wrap等 - 這些widget都由框架佈局,因此無需修改即可編譯到Web上執行。我們用來測量文字佈局屬性的技巧是讓瀏覽器將其佈局,然後從DOM元素中讀回相關屬性。
頁面繪製
通過HTML+CSS+Canvas的組合方法,我們將框架生成的圖片分類為使用HTML + CSS表達的圖片,以及使用Canvas 2D表達的圖片。然後,我們輸出結合了HTML,CSS和2D畫布的HTML DOM。
我們更喜歡HTML + CSS,因為它有瀏覽器的現實列表支援。這意味著我們可以優化圖片的光柵化在瀏覽器上的渲染引擎。這也意味著我們可以應用任意變換,尤其是旋轉和縮放,而不必擔心畫素化。我們將此畫布實現稱為“DomCanvas”。
如果我們無法使用HTML + CSS表達圖片,我們會回到畫布。
渲染結果 ⬇️
docker
概念
docker官方解釋是一個軟體容器平臺。douker中有幾個重要的概念。
- Image 映象:映象是輕量級的,可獨立執行的軟體包。比如在伺服器上使用flutter來編譯專案時,傳統配置,我們需要下載Android sdk ,flutter sdk ,在沒有軟體的情況下,我們可能還需要java sdk,並且配置系統path等複雜的環境配置,如果換一套電腦,又需要重新配置環境。但是使用docker映象,只要在執行檔案中引入映象,就可以完成環境的配置。只要執行檔案不變,在任何一臺機器上面,都可以快速搭建相同的環境。
- Container 容器:像是映象執行時的一個載體,在引入映象,並且使用映象進行一系列操作後,存放產物的“容器”,比如說編譯完成的網站。依託 Docker 的虛擬化技術,給容器建立了獨立的埠、程式、檔案等“空間”,Container 就是一個與宿機隔離 “容器”。
優勢
- 在這次實踐中,明顯感覺到,傳統配置環境的複雜,並且複用性很差,遷移伺服器則需要重新配置。但是使用docker,只要執行檔案不變,就能保證環境的一致性。
- 另外容器中的映象可以相互複用,但是容器與容器之間卻是相互隔離的,更加便於管理,不會出現環境衝突等問題。
- 輕量。多個 Docker 容器可以共享這臺機器的作業系統核心,啟動迅速,佔用少量的記憶體空間。映象是通過檔案系統層進行構造的,並共享一些公共檔案。這樣就能儘量降低磁碟用量,並能更快地下載映象。
Jenkins
原理
持續整合
持續整合是一種軟體開發實踐,倡導開發者可以每天多次整合專案,每次的整合都是通過自動化的構建來驗證,包括合併程式碼、打包、測試和通知分發的一系列軟體工程開始的操作。
Jenkins
最流行的開源免費持續整合工具,由java語言開發,用於監控持續重複的工作,包括:持續的軟體版本釋出/測試專案,監控外部呼叫執行的工作。
⬇️Jenkins工作流程圖
實踐過程
環境搭建
準備一臺雲伺服器,我是用的騰訊雲 Linux.Centos7.6環境。但是,如果在遠端打包,最好是mac環境,linux版本的Flutter不支援build web。
安裝docker和Jenkins,並且設定Jenkins自動拉取程式碼。
參考⬇️(雖然是最後部署Vue,原理是一樣的)
juejin.im/post/5d369d…
大體過程
- 將程式碼部署在github上,本地打包完成之後,生成build/web 資料夾,將程式碼上傳github。
- 當master分支上傳專案時,會Jenkins的自動構建,拉取github上的專案。
- Jenkins拉取完成之後,執行專案中的構建指令碼檔案 setup.sh。
- 檔案中會執行docker命令,配置nginx伺服器,將build/web中的檔案放入指定目錄。
然後就可以通過網址訪問了。
相關配置檔案
(只留下關鍵程式碼,未做詳細配置)
setup.sh
#!/usr/bin/env bash
image_version=`date +%Y%m%d%H%M`;
# 設定映象
#
docker build . -t flutter/web:$image_version;
# 執行容器
docker run -p 9527:80 -d --name flutter_web flutter/web:$image_version;
# 檢視日誌
docker logs flutter_web;複製程式碼
docker build
最後的 .
號,其實是在指定映象構建過程中的上下文環境的目錄,執行當前上下文中的Dockerfil檔案構建映象容器。將容器的80埠對映到伺服器的9527埠。之後可以通過 域名(IP地址):9527訪問
Dockerfile
FROM nginx
COPY conf.nginx /etc/nginx/nginx.conf
RUN mkdir /app
WORKDIR /app
COPY ./build/web /app/
EXPOSE 80
複製程式碼
在Dockerfile中,主要是構建了一個nginx容器。因為Linux版本的Flutter專案並不支援build web, 所以只能本地打包,更改.gitignore檔案,將build出來的檔案也傳到gitlub上面。這邊的docker只是將檔案複製到nginx容器當中。
*若未來版本中支援Linux打包之後,Dockerfile可以直接拉取flutter與Android sdk映象,遠端打包生成build檔案。我在嘗試中,遠端是可以打包出apk檔案,但是無法打出web檔案
conf.nginx nginx的相關配置。
events {
worker_connections 1024;
}
http {
server {
listen 80;
location / {
root /app/;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
}複製程式碼
執行之後,可以通過docker images
來檢視生成的映象。映象是可以重複引用,提高構建效率。
docker ps -a
來檢視當前所有執行中的容器。
只有up狀態的才表示正在執行中。如果執行失敗,可以通過檢視容器日誌來尋找錯誤。
使用Flutter web 優缺點
優
- 對於客戶端開發人員來說,特別是涉及到flutter開發的,可以零成本過渡到web專案的開發。對於現有的flutter專案,再剔除安卓特有的功能後,專案程式碼保持100%的可移植性。
- 各個端的表現差異不大,不必過於擔心適配問題。
劣
- Linux版本不支援flutter build web, 無法在遠端打包,可能需要一臺mac伺服器專門部署專案。
- flutter外掛與映象支援web的數量過少,很多如傳送請求的外掛可能都需要自己進行封裝,目前只推薦做宣傳頁等邏輯偏少的靜態介面。
- 很主要的一點,專案打包體積過大。單純一個hello world 可以打包出2M的大小,直接導致白屏時間長。
- 由於web端一大部分由canvas進行繪製,當頻繁縮放螢幕等需要進行頁面重繪的操作時,很容易面臨效能的問題。
- 由於自身Flutter Web並沒有專門的開發者工具,而Chrome自帶的工具無法準確找到關鍵元素,導致後續開發除錯困難。
綜上所述,flutter web當前並不適用與生產環境,官方也不推薦,1.19.x版本還是處於技術預覽階段。但是其良好的分層設計,各個端的程式碼零成本移植還是有非常大的前景。Dart現如今幾乎只為flutter所服務,谷歌對Flutter投入也很大,期待其新版本技術的成熟。