本文字数:4307字
预计阅读时间:30分钟
01
前言
在之前的文章中,我们详细的介绍过
Flutter Web
从0到部署上线的流程,并且针对其中遇到的问题进行了分析与修复:https://www.jianshu.com/p/6213f8a88288
我们也对
Flutter Web
的项目进行了打包部署上线。在产品体验中会发现,跟传统的
web
端网页对比,还是明显感觉到性能上的差异,特别是启动的过程明显耗时较长。本文将针对
Flutter Web
项目的做一些启动上的优化和探讨。
SDK
版本:
Flutter SDK 3.19.0
。
02
main.dart.js分包
main.dart.js
是
Flutter Web
的编译产物,所有的业务逻辑都在这一个
js
文件里,可想而知它会比较臃肿。在
Flutter Web
发布后,就有了
main.dart.js
分包的需求,看了很多网上的案例,使用
deferred-components
即可达成分包的目的。但在写上一篇文章的时候,我们用的是
Flutter SDK 3.10.5
,按照官网的步骤进行了分包处理发现编译是成功的,但是最终并没有实现分包。阅读官网文档,当时明确说明了
deferred-components
只能用于
Android
的编译产物。猜测那时候可能发现了
Web
分包的一些问题,导致在某一些版本的
SDK
并不支持
Web
的
deferred-components
。链接如下:https://flutter.cn/docs/perf/deferred-components
现在重新阅读官网,描述已经进行了修改:
Flutter
在
Android
和
Web
上支持延迟加载或「懒」加载。在不同平台实现方式有所不同。
Android
平台的 动态功能模块 提供打包为
Android module
的延迟组件。
Web
平台将这些组件创建为单独的
*.js
文件。延迟组件中的代码不会影响其他平台,其他平台在初始安装时会正常构建包含所有延迟组件和资源的应用。
看上去目前
deferred-components
在
Web
端已经做到了很好的支持,那么我们就实验一下,步骤如下:
1、添加依赖
通过将
deferred-components
依赖添加到应用程序的
pubspec.yaml
中的
flutter
下即可:
flutter:
deferred-components:
2、实现
我们找到一个可以被延迟加载的
Widget
,使用
deferred
关键字进行导入:
import './widget/me_read_achievement_widget.dart' deferred as achievement;
然后调用
loadLibrary()
:
late Future<void> _libraryFuture;
@override
void initState() {
super.initState();
_libraryFuture = achievement.loadLibrary();
}
最后使用
FutureBuilder
等待
loadLibrary
的
Future
对象初始化完成,并实现延迟加载:
@override
Widget build(BuildContext context) {
return FutureBuilder<void>(
future: _libraryFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return achievement.MeReadAchievementWidget();
}
return const CircularProgressIndicator();
},
);
}
最后再进行打包。
3、编译产物
打包完成后我们看下编译产物,会发现除了
main.dart.js
之外又多了一个
main.dart.js_1.part.js
:
main.dart.js_1.part.js
即为分包。
4、分包加载
部署之后我们打开浏览器看一下效果:
在启动
Web
页面后我们发现只加载了
main.dart.js
:
只有操作到相应的页面,才会加载
main.dart.js_1.part.js
:
这说明如果业务比较复杂页面很多的情况下,我们可以根据自己的需求和体验细化项目的结构,将
Widget
进行拆分,在需要的时候再进行延迟加载,一定程度上减少
main.dart.js
的包体积,以达到启动时加速的目的。
03
canvaskit.js和canvaskit.wasm
CanvasKit
是以
WASM
为编译目标的
Web
平台图形绘制接口,其目标是将
Skia
的图形
API
导出到
Web
平台。其中
canvaskit
中绘制的实现全部在
canvaskit.js
中调用浏览器绘制
API
来实现,而计算相关的内容全部放在了
wasm
中实现。由此可知这两个文件是实现
Flutter Web
渲染核心文件。它们也是在启动过程中进行的,且是从
google
的服务器进行的下载:
canvaskit.js:
canvaskit.wasm:
由于众所周知的原因,访问这两个地址将会比较慢,在有些时候甚至会访问失败。这两个文件的加载失败也就直接导致了页面无法渲然的问题。由于我们的项目是
CDN
部署,因此我们也需要把它部署到
CDN
上面,并访问其
CDN
地址。官方给了两种方式:
1、在初始化引擎时配置
从官网说明来看,我们可以在
initializeEngine
时通过配置
canvasKitBaseUrl
参数的方式来实现加载
canvaskit
相关的文件。如:
_flutter.loader.loadEntrypoint({
onEntrypointLoaded: async function(engineInitializer) {
let appRunner = await engineInitializer.initializeEngine({
canvasKitBaseUrl: YOUR_CANVASKIT_CDN_BASE_URL
});
await appRunner.runApp();
}
});
其中
YOUR_CANVASKIT_CDN_BASE_URL
是你
canvaskit.js
和
canvaskit.wasm
文件所在的根目录,然后正常编译打包即可。另外我们也可以不改源文件配置,通过在打包时配置参数来实现。
2、打包配置参数
我们可以通过以下参数进行配置:
--dart-define=FLUTTER_WEB_CANVASKIT_URL
完整的打包命令如下:
flutter build web -t lib/main_test.dart --no-tree-shake-icons --dart-define=FLUTTER_WEB_CANVASKIT_URL=YOUR_CANVASKIT_CDN_BASE_URL --release
通过实践,这两种方式都可以实现从自己的
CDN
上读取
canvaskit.js
和
canvaskit.wasm
文件的目的,我们来看一下执行结果:
对比一下,从
Google
服务器下载下来的用时:
都用了2,3秒的时间,而从我们自己的
CDN
上:只用了毫秒级,优化效果非常明显。
好的,接下来我们发现,还有一些字体文件会从
Google
的服务器进行下载,接下来我们优化一下字体的问题。
注意:在开发调试的过程中,由于直接加载的是本地的
canvaskit.js
和
canvaskit.wasm
文件,所以不用做任何处理。
04
字体加载优化
优化了
canvaskit
相关文件后,我们发现启动还是很慢,抓包看原来还有一些字体是从
Google
下载的,比如:
这两个文件的下载路径修改,
Flutter
官方并没有给任何参考。那么我们找找加载它们的实现。打开编译后的产物,
main.dart.js
,我们搜一下这两个字体:
找到了这个代码后,处理就很简单了,将
KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf
这个文件下载下来,放到
CDN
上,再修改一下这段代码的
url
到我们的
CDN
地址即可。另一个字体我们看到,它是在一个数组中:
这个数组长度非常长,有一百多个成员。
Flutter
会根据不同的浏览器环境,和不同的语言环境加载不同的字体。其
Host
定义如下:
其中
j
就是每个字体的
url
参数。一百多个字体一个一个手动下载是不太现实了,但我们可以批量下载,思路就是从这个数组中截取所有的
ttf
路径,拼上
Host
进行下载。注意:需要保留
Google
的目录结构。大家可以用任意自己熟悉的方式实现批量下载,我用
Python
写了个脚本进行批量实现:
# coding=utf-8
import os
import requests
original_text = 'r=this.b=A.cOH(new A.bs4(this),A.a([A.aY("Noto Sans","notosans/v32/o-0IIpQlx3QUlC5A4PNb4j5Ba_2c7A.ttf",!0),A.aY("Noto Color Emoji","notocoloremoji/v25/Yq6P-KqIXTD0t4D9z1ESnKM3-HpFab5s79iz64w.ttf",s),A.aY("Noto Emoji","notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob-r0jwvS-FGJCMY.ttf",!s),A.aY("Noto Music","notomusic/v20/pe0rMIiSN5pO63htf1sxIteQB9Zra1U.ttf",!0),A.aY("Noto Sans Symbols","notosanssymbols/v41/rP2up3q65FkAtHfwd-eIS2brbDN6gxP34F9jRRCe4W3gfQ8gavVFRkzrbQ.ttf",!0),A.aY("Noto Sans Symbols 2","notosanssymbols2/v22/I_uyMoGduATTei9eI8daxVHDyfisHr71ypPqfX71-AI.ttf",!0),A.aY("Noto Sans Adlam","notosansadlam/v22/neIczCCpqp0s5pPusPamd81eMfjPonvqdbYxxpgufnv0TGnBZLwhuvk.ttf",!0),A.aY("Noto Sans Anatolian Hieroglyphs","notosansanatolianhieroglyphs/v16/ijw9s4roRME5LLRxjsRb8A0gKPSWq4BbDmHHu6j2pEtUJzZWXybIymc5QYo.ttf",!0),A.aY("Noto Sans Arabic","notosansarabic/v18/nwpxtLGrOAZMl5nJ_wfgRg3DrWFZWsnVBJ_sS6tlqHHFlhQ5l3sQWIHPqzCfyGyvu3CBFQLaig.ttf",!0),A.aY("Noto Sans Armenian","notosansarmenian/v42/ZgN0jOZKPa7CHqq0h37c7ReDUubm2SEdFXp7ig73qtTY5idb74R9UdM3y2nZLorxb60iYy6zF3Eg.ttf",!0),A.aY("Noto Sans Avestan","notosansavestan/v21/bWti7ejKfBziStx7lIzKOLQZKhIJkyu9SASLji8U.ttf",!0),A.aY("Noto Sans Balinese","notosansbalinese/v24/NaPwcYvSBuhTirw6IaFn6UrRDaqje-lpbbRtYf-Fwu2Ov7fdhE5Vd222PPY.ttf",!0),A.aY("Noto Sans Bamum","notosansbamum/v27/uk-0EGK3o6EruUbnwovcbBTkkklK_Ya_PBHfNGTPEddO-_gLykxEkxA.ttf",!0),A.aY("Noto Sans Bassa Vah","notosansbassavah/v17/PN_bRee-r3f7LnqsD5sax12gjZn7mBpL5YwUpA2MBdcFn4MaAc6p34gH-GD7.ttf",!0),A.aY("Noto Sans Batak","notosansbatak/v19/gok2H6TwAEdtF9N8-mdTCQvT-Zdgo4_PHuk74A.ttf",!0),A.aY("Noto Sans Bengali","notosansbengali/v20/Cn-SJsCGWQxOjaGwMQ6fIiMywrNJIky6nvd8BjzVMvJx2mcSPVFpVEqE-6KmsolLudCk8izI0lc.ttf",!0),A.aY("Noto Sans Bhaiksuki","notosansbhaiksuki/v17/UcC63EosKniBH4iELXATsSBWdvUHXxhj8rLUdU4wh9U.ttf",!0),A.aY("Noto Sans Brahmi","notosansbrahmi/v18/vEFK2-VODB8RrNDvZSUmQQIIByV18tK1W77HtMo.ttf",!0),A.aY("Noto Sans Buginese","notosansbuginese/v18/esDM30ldNv-KYGGJpKGk18phe_7Da6_gtfuEXLmNtw.ttf",!0),A.aY("Noto Sans Buhid","notosansbuhid/v22/Dxxy8jiXMW75w3OmoDXVWJD7YwzAe6tgnaFoGA.ttf",!0),A.aY("Noto Sans Canadian Aboriginal","notosanscanadianaboriginal/v22/4C_TLjTuEqPj-8J01CwaGkiZ9os0iGVkezM1mUT-j_Lmlzda6uH_nnX1bzigWLn_yAsg0q0uhQ.ttf",!0),A.aY("Noto Sans Carian","notosanscarian/v16/LDIpaoiONgYwA9Yc6f0gUILeMIOgs7ob9yGLmfI.ttf",!0),A.aY("Noto Sans Caucasian Albanian","notosanscaucasianalbanian/v16/nKKA-HM_FYFRJvXzVXaANsU0VzsAc46QGOkWytlTs-TXrYDmoVmRSZo.ttf",!0),A.aY("Noto Sans Chakma","notosanschakma/v17/Y4GQYbJ8VTEp4t3MKJSMjg5OIzhi4JjTQhYBeYo.ttf",!0),A.aY("Noto Sans Cham","notosanscham/v29/pe06MIySN5pO62Z5YkFyQb_bbuRhe6D4yip43qfcERwcv7GykboaLg.ttf",!0),A.aY("Noto Sans Cherokee","notosanscherokee/v20/KFOPCm6Yu8uF-29fiz9vQF9YWK6Z8O10cHNA0cSkZCHYWi5PDkm5rAffjl0.ttf",!0),A.aY("Noto Sans Coptic","notosanscoptic/v20/iJWfBWmUZi_OHPqn4wq6kgqumOEd78u_VG0xR4Y.ttf",!0),A.aY("Noto Sans Cuneiform","notosanscuneiform/v17/bMrrmTWK7YY-MF22aHGGd7H8PhJtvBDWgb9JlRQueeQ.ttf",!0),A.aY("Noto Sans Cypriot","notosanscypriot/v15/8AtzGta9PYqQDjyp79a6f8Cj-3a3cxIsK5MPpahF.ttf",!0),A.aY("Noto Sans Deseret","notosansdeseret/v17/MwQsbgPp1eKH6QsAVuFb9AZM6MMr2Vq9ZnJSZtQG.ttf",!0),A.aY("Noto Sans Devanagari","notosansdevanagari/v25/TuGoUUFzXI5FBtUq5a8bjKYTZjtRU6Sgv3NaV_SNmI0b8QQCQmHn6B2OHjbL_08AlXQly-AzoFoW4Ow.ttf",!0),A.aY("Noto Sans Duployan","notosansduployan/v17/gokzH7nwAEdtF9N8-mdTDx_X9JM5wsvrFsIn6WYDvA.ttf",!0),A.aY("Noto Sans Egyptian Hieroglyphs","notosansegyptianhieroglyphs/v28/vEF42-tODB8RrNDvZSUmRhcQHzx1s7y_F9-j3qSzEcbEYindSVK8xRg7iw.ttf",!0),A.aY("Noto Sans Elbasan","notosanselbasan/v16/-F6rfiZqLzI2JPCgQBnw400qp1trvHdlre4dFcFh.ttf",!0),A.aY("Noto Sans Elymaic","notosanselymaic/v15/UqyKK9YTJW5liNMhTMqe9vUFP65ZD4AjWOT0zi2V.ttf",!0),A.aY("Noto Sans Georgian","notosansgeorgian/v42/PlIaFke5O6RzLfvNNVSitxkr76PRHBC4Ytyq-Gof7PUs4S7zWn-8YDB09HFNdpvnzFj-f5WK0OQV.ttf",!0),A.aY("Noto Sans Glagolitic","notosansglagolitic/v17/1q2ZY4-BBFBst88SU_tOj4J-4yuNF_HI4ERK4Amu7nM1.ttf",!0),A.aY("Noto Sans Gothic","notosansgothic/v16/TuGKUUVzXI5FBtUq5a8bj6wRbzxTFMX40kFQRx0.ttf",!0),A.aY("Noto Sans Grantha","notosansgrantha/v17/3y976akwcCjmsU8NDyrKo3IQfQ4o-r8cFeulHc6N.ttf",!0),A.aY("Noto Sans Gujarati","notosansgujarati/v23/wlpWgx_HC1ti5ViekvcxnhMlCVo3f5pv17ivlzsUB14gg1TMR2Gw4VceEl7MA_ypFwPM_OdiEH0s.ttf",!0),A.aY("Noto Sans Gunjala Gondi","notosansgunjalagondi/v19/bWtX7e7KfBziStx7lIzKPrcSMwcEnCv6DW7n5g0ef3PLtymzNxYL4YDE4J4vCTxEJQ.ttf",!0),A.aY("Noto Sans Gurmukhi","notosansgurmukhi/v26/w8g9H3EvQP81sInb43inmyN9zZ7hb7ATbSWo4q8dJ74a3cVrYFQ_bogT0-gPeG1OenbxZ_trdp7h.ttf",!0),A.aY("Noto Sans HK","notosanshk/v31/nKKF-GM_FYFRJvXzVXaAPe97P1KHynJFP716qHB--oWTiYjNvVA.ttf",!0),A.aY("Noto Sans Hanunoo","notosanshanunoo/v20/f0Xs0fCv8dxkDWlZSoXOj6CphMloFsEsEpgL_ix2.ttf",!0),A.aY("Noto Sans Hatran","notosanshatran/v16/A2BBn4Ne0RgnVF3Lnko-0sOBIfL_mM83r1nwzDs.ttf",!0),A.aY("Noto Sans Hebrew","notosanshebrew/v43/or3HQ7v33eiDljA1IufXTtVf7V6RvEEdhQlk0LlGxCyaeNKYZC0sqk3xXGiXd4qtoiJltutR2g.ttf",!0),A.aY("Noto Sans Imperial Aramaic","notosansimperialaramaic/v16/a8IMNpjwKmHXpgXbMIsbTc_kvks91LlLetBr5itQrtdml3YfPNno.ttf",!0),A.aY("Noto Sans Indic Siyaq Numbers","notosansindicsiyaqnumbers/v16/6xK5dTJFKcWIu4bpRBjRZRpsIYHabOeZ8UZLubTzpXNHKx2WPOpVd5Iu.ttf",!0),A.aY("Noto Sans Inscriptional Pahlavi","notosansinscriptionalpahlavi/v16/ll8UK3GaVDuxR-TEqFPIbsR79Xxz9WEKbwsjpz7VklYlC7FCVtqVOAYK0QA.ttf",!0),A.aY("Noto Sans Inscriptional Parthian","notosansinscriptionalparthian/v16/k3k7o-IMPvpLmixcA63oYi-yStDkgXuXncL7dzfW3P4TAJ2yklBJ2jNkLlLr.ttf",!0),A.aY("Noto Sans JP","notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFBEj75vY0rw-oME.ttf",!0),A.aY("Noto Sans Javanese","notosansjavanese/v23/2V01KJkDAIA6Hp4zoSScDjV0Y-eoHAHT-Z3MngEefiidxJnkFFliZYWj4O8.ttf",!0),A.aY("Noto Sans KR","notosanskr/v36/PbyxFmXiEBPT4ITbgNA5Cgms3VYcOA-vvnIzzuoyeLTq8H4hfeE.ttf",!0),A.aY("Noto Sans Kaithi","notosanskaithi/v20/buEtppS9f8_vkXadMBJJu0tWjLwjQi0KdoZIKlo.ttf",!0),A.aY("Noto Sans Kannada","notosanskannada/v26/8vIs7xs32H97qzQKnzfeXycxXZyUmySvZWItmf1fe6TVmgop9ndpS-BqHEyGrDvNzSIMLsPKrkY.ttf",!0),A.aY("Noto Sans Kayah Li","notosanskayahli/v21/B50nF61OpWTRcGrhOVJJwOMXdca6Yecki3E06x2jVTX3WCc3CZH4EXLuKVM.ttf",!0),A.aY("Noto Sans Kharoshthi","notosanskharoshthi/v16/Fh4qPiLjKS30-P4-pGMMXCCfvkc5Vd7KE5z4rFyx5mR1.ttf",!0),A.aY("Noto Sans Khmer","notosanskhmer/v23/ijw3s5roRME5LLRxjsRb-gssOenAyendxrgV2c-Zw-9vbVUti_Z_dWgtWYuNAJz4kAbrddiA.ttf",!0),A.aY("Noto Sans Khojki","notosanskhojki/v18/-nFnOHM29Oofr2wohFbTuPPKVWpmK_d709jy92k.ttf",!0),A.aY("Noto Sans Khudawadi","notosanskhudawadi/v21/fdNi9t6ZsWBZ2k5ltHN73zZ5hc8HANlHIjRnVVXz9MY.ttf",!0),A.aY("Noto Sans Lao","notosanslao/v30/bx6lNx2Ol_ixgdYWLm9BwxM3NW6BOkuf763Clj73CiQ_J1Djx9pidOt4ccbdf5MK3riB2w.ttf",!0),A.aY("Noto Sans Lepcha","notosanslepcha/v19/0QI7MWlB_JWgA166SKhu05TekNS32AJstqBXgd4.ttf",!0),A.aY("Noto Sans Limbu","notosanslimbu/v22/3JnlSDv90Gmq2mrzckOBBRRoNJVj0MF3OHRDnA.ttf",!0),A.aY("Noto Sans Linear A","notosanslineara/v18/oPWS_l16kP4jCuhpgEGmwJOiA18FZj22zmHQAGQicw.ttf",!0),A.aY("Noto Sans Linear B","notosanslinearb/v17/HhyJU4wt9vSgfHoORYOiXOckKNB737IV3BkFTq4EPw.ttf",!0),A.aY("Noto Sans Lisu","notosanslisu/v25/uk-3EGO3o6EruUbnwovcYhz6kh57_nqbcTdjJnHP2Vwt29IlxkVdig.ttf",!0),A.aY("Noto Sans Lycian","notosanslycian/v15/QldVNSNMqAsHtsJ7UmqxBQA9r8wA5_naCJwn00E.ttf",!0),A.aY("Noto Sans Lydian","notosanslydian/v17/c4m71mVzGN7s8FmIukZJ1v4ZlcPReUPXMoIjEQI.ttf",!0),A.aY("Noto Sans Mahajani","notosansmahajani/v19/-F6sfiVqLzI2JPCgQBnw60Agp0JrvD5Fh8ARHNh4zg.ttf",!0),A.aY("Noto Sans Malayalam","notosansmalayalam/v26/sJoi3K5XjsSdcnzn071rL37lpAOsUThnDZIfPdbeSNzVakglNM-Qw8EaeB8Nss-_RuD9BFzEr6HxEA.ttf",!0),A.aY("Noto Sans Mandaic","notosansmandaic/v16/cIfnMbdWt1w_HgCcilqhKQBo_OsMI5_A_gMk0izH.ttf",!0),A.aY("Noto Sans Manichaean","notosansmanichaean/v17/taiVGntiC4--qtsfi4Jp9-_GkPZZCcrfekqCNTtFCtdX.ttf",!0),A.aY("Noto Sans Marchen","notosansmarchen/v19/aFTO7OZ_Y282EP-WyG6QTOX_C8WZMHhPk652ZaHk.ttf",!0),A.aY("Noto Sans Masaram Gondi","notosansmasaramgondi/v17/6xK_dThFKcWIu4bpRBjRYRV7KZCbUq6n_1kPnuGe7RI9WSWX.ttf",!0),A.aY("Noto Sans Math","notosansmath/v15/7Aump_cpkSecTWaHRlH2hyV5UHkG-V048PW0.ttf",!0),A.aY("Noto Sans Mayan Numerals","notosansmayannumerals/v16/PlIuFk25O6RzLfvNNVSivR09_KqYMwvvDKYjfIiE68oo6eepYQ.ttf",!0),A.aY("Noto Sans Medefaidrin","notosansmedefaidrin/v23/WwkzxOq6Dk-wranENynkfeVsNbRZtbOIdLb1exeM4ZeuabBfmErWlT318e5A3rw.ttf",!0),A.aY("Noto Sans Meetei Mayek","notosansmeeteimayek/v15/HTxAL3QyKieByqY9eZPFweO0be7M21uSphSdhqILnmrRfJ8t_1TJ_vTW5PgeFYVa.ttf",!0),A.aY("Noto Sans Meroitic","notosansmeroitic/v17/IFS5HfRJndhE3P4b5jnZ3ITPvC6i00UDgDhTiKY9KQ.ttf",!0),A.aY("Noto Sans Miao","notosansmiao/v17/Dxxz8jmXMW75w3OmoDXVV4zyZUjgUYVslLhx.ttf",!0),A.aY("Noto Sans Modi","notosansmodi/v23/pe03MIySN5pO62Z5YkFyT7jeav5qWVAgVol-.ttf",!0),A.aY("Noto Sans Mongolian","notosansmongolian/v17/VdGCAYADGIwE0EopZx8xQfHlgEAMsrToxLsg6-av1x0.ttf",!0),A.aY("Noto Sans Mro","notosansmro/v18/qWcsB6--pZv9TqnUQMhe9b39WDzRtjkho4M.ttf",!0),A.aY("Noto Sans Multani","notosansmultani/v20/9Bty3ClF38_RfOpe1gCaZ8p30BOFO1A0pfCs5Kos.ttf",!0),A.aY("Noto Sans Myanmar","notosansmyanmar/v20/AlZq_y1ZtY3ymOryg38hOCSdOnFq0En23OU4o1AC.ttf",!0),A.aY("Noto Sans NKo","notosansnko/v6/esDX31ZdNv-KYGGJpKGk2_RpMpCMHMLBrdA.ttf",!0),A.aY("Noto Sans Nabataean","notosansnabataean/v16/IFS4HfVJndhE3P4b5jnZ34DfsjO330dNoBJ9hK8kMK4.ttf",!0),A.aY("Noto Sans New Tai Lue","notosansnewtailue/v22/H4cKBW-Pl9DZ0Xe_nHUapt7PovLXAhAnY7wqaLy-OJgU3p_pdeXAYUbghFPKzeY.ttf",!0),A.aY("Noto Sans Newa","notosansnewa/v16/7r3fqXp6utEsO9pI4f8ok8sWg8n_qN4R5lNU.ttf",!0),A.aY("Noto Sans Nushu","notosansnushu/v19/rnCw-xRQ3B7652emAbAe_Ai1IYaFWFAMArZKqQ.ttf",!0),A.aY("Noto Sans Ogham","notosansogham/v17/kmKlZqk1GBDGN0mY6k5lmEmww4hrt5laQxcoCA.ttf",!0),A.aY("Noto Sans Ol Chiki","notosansolchiki/v29/N0b92TJNOPt-eHmFZCdQbrL32r-4CvhzDzRwlxOQYuVALWk267I6gVrz5gQ.ttf",!0),A.aY("Noto Sans Old Hungarian","notosansoldhungarian/v18/E213_cD6hP3GwCJPEUssHEM0KqLaHJXg2PiIgRfjbg5nCYXt.ttf",!0),A.aY("Noto Sans Old Italic","notosansolditalic/v16/TuGOUUFzXI5FBtUq5a8bh68BJxxEVam7tWlRdRhtCC4d.ttf",!0),A.aY("Noto Sans Old North Arabian","notosansoldnortharabian/v16/esDF30BdNv-KYGGJpKGk2tNiMt7Jar6olZDyNdr81zBQmUo_xw4ABw.ttf",!0),A.aY("Noto Sans Old Permic","notosansoldpermic/v17/snf1s1q1-dF8pli1TesqcbUY4Mr-ElrwKLdXgv_dKYB5.ttf",!0),A.aY("Noto Sans Old Persian","notosansoldpersian/v16/wEOjEAbNnc5caQTFG18FHrZr9Bp6-8CmIJ_tqOlQfx9CjA.ttf",!0),A.aY("Noto Sans Old Sogdian","notosansoldsogdian/v16/3JnjSCH90Gmq2mrzckOBBhFhdrMst48aURt7neIqM-9uyg.ttf",!0),A.aY("Noto Sans Old South Arabian","notosansoldsoutharabian/v16/3qT5oiOhnSyU8TNFIdhZTice3hB_HWKsEnF--0XCHiKx1OtDT9HwTA.ttf",!0),A.aY("Noto Sans Old Turkic","notosansoldturkic/v17/yMJNMJVya43H0SUF_WmcGEQVqoEMKDKbsE2RjEw-Vyws.ttf",!0),A.aY("Noto Sans Oriya","notosansoriya/v27/AYCppXfzfccDCstK_hrjDyADv5e9748vhj3CJBLHIARtgD6TJQS0dJT5Ivj0f6_c6LhHBRe-.ttf",!0),A.aY("Noto Sans Osage","notosansosage/v18/oPWX_kB6kP4jCuhpgEGmw4mtAVtXRlaSxkrMCQ.ttf",!0),A.aY("Noto Sans Osmanya","notosansosmanya/v18/8vIS7xs32H97qzQKnzfeWzUyUpOJmz6kR47NCV5Z.ttf",!0),A.aY("Noto Sans Pahawh Hmong","notosanspahawhhmong/v18/bWtp7e_KfBziStx7lIzKKaMUOBEA3UPQDW7krzc_c48aMpM.ttf",!0),A.aY("Noto Sans Palmyrene","notosanspalmyrene/v16/ZgNPjOdKPa7CHqq0h37c_ASCWvH93SFCPnK5ZpdNtcA.ttf",!0),A.aY("Noto Sans Pau Cin Hau","notosanspaucinhau/v20/x3d-cl3IZKmUqiMg_9wBLLtzl22EayN7ehIdjEWqKMxsKw.ttf",!0),A.aY("Noto Sans Phags Pa","notosansphagspa/v15/pxiZyoo6v8ZYyWh5WuPeJzMkd4SrGChkqkSsrvNXiA.ttf",!0),A.aY("Noto Sans Phoenician","notosansphoenician/v17/jizFRF9Ksm4Bt9PvcTaEkIHiTVtxmFtS5X7Jot-p5561.ttf",!0),A.aY("Noto Sans Psalter Pahlavi","notosanspsalterpahlavi/v16/rP2Vp3K65FkAtHfwd-eISGznYihzggmsicPfud3w1G3KsUQBct4.ttf",!0),A.aY("Noto Sans Rejang","notosansrejang/v21/Ktk2AKuMeZjqPnXgyqrib7DIogqwN4O3WYZB_sU.ttf",!0),A.aY("Noto Sans Runic","notosansrunic/v17/H4c_BXWPl9DZ0Xe_nHUaus7W68WWaxpvHtgIYg.ttf",!0),A.aY("Noto Sans SC","notosanssc/v36/k3kCo84MPvpLmixcA63oeAL7Iqp5IZJF9bmaG9_FnYxNbPzS5HE.ttf",!0),A.aY("Noto Sans Saurashtra","notosanssaurashtra/v23/ea8GacQ0Wfz_XKWXe6OtoA8w8zvmYwTef9ndjhPTSIx9.ttf",!0),A.aY("Noto Sans Sharada","notosanssharada/v16/gok0H7rwAEdtF9N8-mdTGALG6p0kwoXLPOwr4H8a.ttf",!0),A.aY("Noto Sans Shavian","notosansshavian/v17/CHy5V_HZE0jxJBQlqAeCKjJvQBNF4EFQSplv2Cwg.ttf",!0),A.aY("Noto Sans Siddham","notosanssiddham/v20/OZpZg-FwqiNLe9PELUikxTWDoCCeGqndk3Ic92ZH.ttf",!0),A.aY("Noto Sans Sinhala","notosanssinhala/v26/yMJ2MJBya43H0SUF_WmcBEEf4rQVO2P524V5N_MxQzQtb-tf5dJbC30Fu9zUwg2a5lgLpJwbQRM.ttf",!0),A.aY("Noto Sans Sogdian","notosanssogdian/v16/taiQGn5iC4--qtsfi4Jp6eHPnfxQBo--Pm6KHidM.ttf",!0),A.aY("Noto Sans Sora Sompeng","notosanssorasompeng/v24/PlIRFkO5O6RzLfvNNVSioxM2_OTrEhPyDLolKvCsHzCxWuGkYHR818DpZXJQd4Mu.ttf",!0),A.aY("Noto Sans Soyombo","notosanssoyombo/v17/RWmSoL-Y6-8q5LTtXs6MF6q7xsxgY0FrIFOcK25W.ttf",!0),A.aY("Noto Sans Sundanese","notosanssundanese/v24/FwZw7_84xUkosG2xJo2gm7nFwSLQkdymq2mkz3Gz1_b6ctxpNNHCizv7fQES.ttf",!0),A.aY("Noto Sans Syloti Nagri","notosanssylotinagri/v20/uU9eCAQZ75uhfF9UoWDRiY3q7Sf_VFV3m4dGFVfxN87gsj0.ttf",!0),A.aY("Noto Sans Syriac","notosanssyriac/v16/Ktk7AKuMeZjqPnXgyqribqzQqgW0LYiVqV7dXcP0C-VD9MaJyZfUL_FC.ttf",!0),A.aY("Noto Sans TC","notosanstc/v35/-nFuOG829Oofr2wohFbTp9ifNAn722rq0MXz76Cy_CpOtma3uNQ.ttf",!0),A.aY("Noto Sans Tagalog","notosanstagalog/v22/J7aFnoNzCnFcV9ZI-sUYuvote1R0wwEAA8jHexnL.ttf",!0),A.aY("Noto Sans Tagbanwa","notosanstagbanwa/v18/Y4GWYbB8VTEp4t3MKJSMmQdIKjRtt_nZRjQEaYpGoQ.ttf",!0),A.aY("Noto Sans Tai Le","notosanstaile/v17/vEFK2-VODB8RrNDvZSUmVxEATwR58tK1W77HtMo.ttf",!0),A.aY("Noto Sans Tai Tham","notosanstaitham/v20/kJEbBv0U4hgtwxDUw2x9q7tbjLIfbPGHBoaVSAZ3MdLJBCUbPgquyaRGKMw.ttf",!0),A.aY("Noto Sans Tai Viet","notosanstaiviet/v19/8QIUdj3HhN_lv4jf9vsE-9GMOLsaSPZr644fWsRO9w.ttf",!0),A.aY("Noto Sans Takri","notosanstakri/v23/TuGJUVpzXI5FBtUq5a8bnKIOdTwQNO_W3khJXg.ttf",!0),A.aY("Noto Sans Tamil","notosanstamil/v27/ieVc2YdFI3GCY6SyQy1KfStzYKZgzN1z4LKDbeZce-0429tBManUktuex7vGo70RqKDt_EvT.ttf",!0),A.aY("Noto Sans Tamil Supplement","notosanstamilsupplement/v21/DdTz78kEtnooLS5rXF1DaruiCd_bFp_Ph4sGcn7ax_vsAeMkeq1x.ttf",!0),A.aY("Noto Sans Telugu","notosanstelugu/v25/0FlxVOGZlE2Rrtr-HmgkMWJNjJ5_RyT8o8c7fHkeg-esVC5dzHkHIJQqrEntezbqQUbf-3v37w.ttf",!0),A.aY("Noto Sans Thaana","notosansthaana/v23/C8c14dM-vnz-s-3jaEsxlxHkBH-WZOETXfoQrfQ9Y4XrbhLhnu4-tbNu.ttf",!0),A.aY("Noto Sans Thai","notosansthai/v20/iJWnBXeUZi_OHPqn4wq6hQ2_hbJ1xyN9wd43SofNWcd1MKVQt_So_9CdU5RtpzF-QRvzzXg.ttf",!0),A.aY("Noto Sans Tifinagh","notosanstifinagh/v20/I_uzMoCduATTei9eI8dawkHIwvmhCvbn6rnEcXfs4Q.ttf",!0),A.aY("Noto Sans Tirhuta","notosanstirhuta/v16/t5t6IQYRNJ6TWjahPR6X-M-apUyby7uGUBsTrn5P.ttf",!0),A.aY("Noto Sans Ugaritic","notosansugaritic/v16/3qTwoiqhnSyU8TNFIdhZVCwbjCpkAXXkMhoIkiazfg.ttf",!0),A.aY("Noto Sans Vai","notosansvai/v17/NaPecZTSBuhTirw6IaFn_UrURMTsDIRSfr0.ttf",!0),A.aY("Noto Sans Wancho","notosanswancho/v17/zrf-0GXXyfn6Fs0lH9P4cUubP0GBqAPopiRfKp8.ttf",!0),A.aY("Noto Sans Warang Citi","notosanswarangciti/v17/EYqtmb9SzL1YtsZSScyKDXIeOv3w-zgsNvKRpeVCCXzdgA.ttf",!0),A.aY("Noto Sans Yi","notosansyi/v19/sJoD3LFXjsSdcnzn071rO3apxVDJNVgSNg.ttf",!0),A.aY("Noto Sans Zanabazar Square","notosanszanabazarsquare/v19/Cn-jJsuGWQxOjaGwMQ6fOicyxLBEMRfDtkzl4uagQtJxOCEgN0Gc.ttf",!0)],t.Qg))}return r},'
font_list_content = original_text.split('"')
font_list = []
for font in font_list_content:
if font.endswith(".ttf"):
font_list.append(font)
host = 'https://fonts.gstatic.com/s/'
fonts = "fonts/"
path = ""
for font in font_list:
folder_list = font.split("/")
for folder in folder_list:
if (folder.endswith(".ttf")):
url = host + path + folder
proxies = {
'http': 'http://127.0.0.1:9098', # 替换为你的VPN IP和端口
'https': 'http://127.0.0.1:9098', # 同上
}
r = requests.get(url,proxies=proxies)
print("finish")
with open(fonts + path + folder, 'wb') as file:
file.write(r.content)
path = ""
else:
path += folder + "/"
os.makedirs(fonts + path, exist_ok=True)
其中由于这两天
Google
的字体服务器连接不上,所以我使用了
vpn
,在代码中需要通过
proxies
进行代理的相关配置。下载完成后的结果如下:
我们再将所有的字体资源上传到
CDN
上,然后修改
main.dart.js
文件,将
Host
改为我们
CDN
的相应地址,然后我们来看一下优化效果:
优化之前也是2,3秒的样子,再看一下优化后的:也是毫秒级别,可见优化效果之明显。
字体的打包部署时如何优化我们已经了解了。那么我们开发调试的时候应该怎么处理呢?我们复习一下
Flutter Web
的渲染模式:
Flutter
为了实现多浏览器的效果一致性,在
canvaskit
渲染模式下,会下载相应的字体进行绘制。因此在开发调试的阶段,我们可以关闭
canvaskit
渲染模式使用
html
方式进行渲染,就不会加载这些字体了。命令如下:
flutter run -d Chrome -t lib/main_test.dart --web-renderer html
这样就解决了开发调试时的字体问题。
05
总结
到此为止,我们通过
main.dart.js分包
,配置
canvaskit.js
和
canvaskit.wasm
的加载
url
,字体加载优化这三个方式可以为
Flutter Web
项目减少5-6秒的启动耗时。希望可以给大家一些帮助。
版权归原作者 搜狐技术产品小编2023 所有, 如有侵权,请联系我们删除。