最近在做一个 Flutter 2.0 for Web
的项目, 在项目打开第一次运行的时候, 总是要等很久才能看到效果.
经过一番研究发现是 Flutter
使用的一个渲染引擎 Canvaskit
下载太慢导致的.
解决方法
Canvaskit
是一个 js
框架, Flutter
定义默认是从 https://unpkg.com 去加载的, 在国内最好是改变这个地址, 让它通过镜像地址去加载.
编译发布修改
在 {SDK_PATH}/bin/cache/flutter_web_sdk/lib/_engine/engine/canvaskit/initialization.dart
文件中有定义:
/// The URL to use when downloading the CanvasKit script and associated wasm.
///
/// The expected directory structure nested under this URL is as follows:
///
/// /canvaskit.js - the release build of CanvasKit JS API bindings
/// /canvaskit.wasm - the release build of CanvasKit WASM module
/// /profiling/canvaskit.js - the profile build of CanvasKit JS API bindings
/// /profiling/canvaskit.wasm - the profile build of CanvasKit WASM module
///
/// The base URL can be overridden using the `FLUTTER_WEB_CANVASKIT_URL`
/// environment variable, which can be set in the Flutter tool using the
/// `--dart-define` option. The value must end with a `/`.
///
/// Example:
///
/// ```
/// flutter run \
/// -d chrome \
/// --web-renderer=canvaskit \
/// --dart-define=FLUTTER_WEB_CANVASKIT_URL=https://example.com/custom-canvaskit-build/
/// ```
///
/// When CanvasKit pushes a new release to NPM, update this URL to reflect the
/// most recent version. For example, if CanvasKit releases version 0.34.0 to
/// NPM, update this URL to `https://unpkg.com/canvaskit-wasm@0.34.0/bin/`.
const String canvasKitBaseUrl = String.fromEnvironment(
'FLUTTER_WEB_CANVASKIT_URL',
defaultValue: 'https://unpkg.com/canvaskit-wasm@0.24.0/bin/',
);
意思是可以通过 FLUTTER_WEB_CANVASKIT_URL
这个环境变量改变默认的下载地址.
所以我们只要在 flutter
命令后面加上 --dart-define=FLUTTER_WEB_CANVASKIT_URL=https://cdn.jsdelivr.net/npm/canvaskit-wasm@0.24.0/bin/
就可以了.
flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=https://cdn.jsdelivr.net/npm/canvaskit-wasm@0.24.0/bin/
运行调试修改
但在开发和调试时发现上面的方法并不生效.
所以如果要在本地开发调试的时候用上面的方法就需要再加上 --release
参数, 让它运行在 编译模式
. 最终的命令如下:
flutter run -d chrome --dart-define=FLUTTER_WEB_CANVASKIT_URL=https://cdn.jsdelivr.net/npm/canvaskit-wasm@0.24.0/bin/ --release
又经过一番折腾之后, 发现在本地运行或调试的时候使用的其实是 {SDK_PATH}/bin/cache/flutter_web_sdk/kernel/{MODE}/dart_sdk.js
里面的值:
/*_engine.canvasKitBaseUrl*/get canvasKitBaseUrl() {
return "https://unpkg.com/canvaskit-wasm@0.24.0/bin/";
},
这些值被固定成 https://unpkg.com/canvaskit-wasm@0.24.0/bin/
, 经过验证只要改掉里面的地址, 运行模式也能走我们改掉后的镜像地址了.
但是呢, 这些文件为了匹配不同的环境所以有很多个, 并且每个文件都很长很巨大, 我用 IDEA
编辑一度内存溢出报警, 于是写了个 Shell
脚本来帮助修改:
#!/bin/bash
export flutter_path=$(which flutter)
export flutter_web_sdk_folder=${flutter_path%flutter}cache/flutter_web_sdk
if [ ! -d $flutter_web_sdk_folder ]; then
echo Flutter web sdk folder not found!
read -n1 -p "Press any key to exit..."
exit
fi
echo Find flutter web sdk folder:
echo $flutter_web_sdk_folder
echo
read -n1 -p "Press any key to continue..."
echo "Start performing the replacement..."
find $flutter_web_sdk_folder/kernel -name dart_sdk.js | xargs sed -i 's?//unpkg.com/?//cdn.jsdelivr.net/npm/?g'
echo "Complete replacement!"
read -n1 -p "Press any key to exit..."
将上面的内容保存为 sh
脚本文件, Unix
系统可以使用终端直接运行, Windows
系统可以使用 Git
的 bash
运行.
正常情况下这段脚本会自动找到 Flutter SDK
中 Flutter Web SDK
目录下的 kernel
子目录下所有的 dart_sdk.js
, 并将原本的 //unpkg.com/
替换为 //cdn.jsdelivr.net/npm/
, 实现依赖加速的目的.
其他的镜像源
知乎
--dart-define=FLUTTER_WEB_CANVASKIT_URL=https://unpkg.zhimg.com/canvaskit-wasm@0.24.0/bin/
饿了么
--dart-define=FLUTTER_WEB_CANVASKIT_URL=https://npm.elemecdn.com/canvaskit-wasm@0.24.0/bin/
jsDelivr
--dart-define=FLUTTER_WEB_CANVASKIT_URL=https://cdn.jsdelivr.net/npm/canvaskit-wasm@0.24.0/bin/