0%

Flutter Web在連網限制環境下使用CanvasKit渲染器

在使用CanvasKit渲染器開發Flutter web app時,會在app啟動時從CDN服務下載CanvasKit,因此在採用CanvasKit渲染器的情況下預設是需要有連網的環境,否則app在啟動時會因為無法下載CanvasKit出現Failed to load resource: net::ERR_INTERNET_DISCONNECTED的錯誤訊息。

但如果是在有連網限制的開發環境下,雖然可以在開發環境使用html渲染器進行開發,並在佈署環境使用CanvasKit渲染器來達到最佳的操作效果,但因為兩種渲染器方法不同,所以渲染出來的效果還是有所差異,這會造成開發和佈署的版面不一致。

雖然預設需要連網才能使用CanvasKit,但目前版本(2.2.2)可以透過指定CanvasKit URL的方式置換掉預設的URL,而且也支援將CanvasKit與web檔案bundle在一起佈署,達到在離線或是有連網限制的環境下執行。但這個方法目前只支援profile與release模式,不支援debug模式

下載CanvasKit放入web資料夾

下載canvaskit.js與canvaskit.wasm並放進web資料夾,舉例來說目前版本使用的CanvasKit為0.25.1,可以先從CDN下載canvaskit.jscanvaskit.wasm。如果要使用profile模式就將兩個檔案在進/web/profiling/目錄內,要使用release模式的話直接放在/web/目錄。

修改url指到CanvasKit位置

透過--dart-define覆寫FLUTTER_WEB_CANVASKIT_URL環境變數,並指到下載的CanvasKit檔案位置。因為這裡的預設根目錄會是web/,所以如果用上述的檔案放法的話只要給/就行了。這樣在profile模式下會自動在/web/profiling/讀取CanvasKit,在release模式會自動在根目錄(預設輸出的local位置為/web/,實際佈署會存在於根目錄)讀取CanvasKit。

使用profile模式:

flutter run -d chrome --profile --dart-define=FLUTTER_WEB_CANVASKIT_URL=/

使用release模式:

flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=/

使用profile模式也可以透過在VS Code設定launch.json檔中的flutterMode與args參數,接著直接在VS Code執行啟動偵錯就可以進入profile模式。如果是使用release模式也可以透過dhttpd在本地端啟動web server測試。

1
2
3
4
5
6
7
8
9
10
11
// launch.json
"configurations": [
{
"name": "Flutter",
"type": "dart",
"request": "launch",
"program": "lib/main.dart",
"flutterMode": "profile",
"args": ["--dart-define=FLUTTER_WEB_CANVASKIT_URL=/"]
}
]

在專案中引用Roboto預設字型

如果app內Text相關widget沒有指定字型(fontFamily),或是雖然有指定字型但沒有將字型檔(.ttf/.otf)放進專案並在pubspec宣告,使用CanvasKit渲染器時會預設從fonts.google.com下載Roboto-Regular使用。

因此要先將Roboto放在專案並宣告在pubspec,在web啟動時就會自動使用專案內的字型檔而不會連到google下載字型。如果有使用到其它字型,可以參考官方的字型引用方法。

從google下載下來會有Rotobo全部的ttf檔,只要把Roboto-Regular放進來即可

接著在pubspec宣告引用

1
2
3
4
5
6
flutter:
uses-material-design: true
fonts:
- family: Roboto
fonts:
- asset: assets/fonts/Roboto-Regular.ttf

預設app啟動就會自動使用Roboto而不會連到google下載字型。

在Flutter官方提供更簡易的支援前,可以使用上述的三個步驟來達成在連網限制的環境上使用CanvasKit渲染器,在部署時只要將CanvasKit檔案一起部署即可。

參考資料:
Flutter issues - Can’t build web apps with CanvasKit without internet
Flutter issues - support bundling CanvasKit instead of CDN
Flutter issues - support specifying CanvasKit URL in debug builds