如何在Flutter Web发布版本中排除默认字体优化页面加载速度
Flutter Web 冗余默认字体移除与加载优化方案
问题现状
- Flutter Web应用平均加载时长达20秒,加载耗时占比详情:

- 排查定位到
FontManifest.json配置文件、MaterialIcons-Regular.otf、CupertinoIcons.ttf两个默认字体文件拉取平均耗时达10秒。项目已接入Google Fonts,未使用上述默认字体,该部分资源加载属于无效流量与时间开销。 - 已尝试以下方案均未生效:
- 直接编辑
FontManifest.json删除.otf、.ttf字体相关条目,该文件为构建自动生成,每次Flutter构建时都会被重写 - 无法接受设置
use-material-design: false的方案,需要保留Material Design其他组件能力 - 修改
pubspec.yaml中的fonts字段配置,未生效 - 查阅公开技术资料,内容大多围绕字体显示异常问题,无对应加载优化方案
- 直接编辑
可落地解决方案
方案1:构建后自动裁剪冗余资源(推荐,无侵入、不影响框架功能)
该方案不修改Flutter SDK源码,在构建完成后自动删除无效字体、重写字体清单,从根源上取消这两个资源的加载请求。
操作步骤:
- 在项目根目录新建后置构建脚本
post_build.dart,代码如下:
import 'dart:io'; import 'dart:convert'; void main() async { final webBuildDir = Directory('build/web'); // 删除冗余字体文件 const redundantFontPaths = [ 'assets/fonts/MaterialIcons-Regular.otf', 'assets/fonts/CupertinoIcons.ttf' ]; for (final path in redundantFontPaths) { final file = File('${webBuildDir.path}/$path'); if (await file.exists()) { await file.delete(); } } // 重写FontManifest.json,移除冗余字体条目 final manifestFile = File('${webBuildDir.path}/FontManifest.json'); if (await manifestFile.exists()) { final List manifest = jsonDecode(await manifestFile.readAsString()); manifest.removeWhere((fontConfig) { final family = fontConfig['family'].toString(); return family == 'MaterialIcons' || family == 'CupertinoIcons'; }); await manifestFile.writeAsString(jsonEncode(manifest)); } }
- 替换原有构建命令,将构建与后置裁剪逻辑绑定执行:
flutter build web --release --tree-shake-icons && dart run post_build.dart
如果项目中用到少量Material/Cupertino图标,不要直接全量删除字体,可替换为SVG图标或图标字体分片加载方案,避免加载完整的大体积图标字体。
方案2:静态资源配置优化(不删除资源的前提下降低加载耗时)
如果暂时不想移除默认字体,可通过部署层配置大幅降低TTFB与资源下载耗时:
- 开启压缩:在Nginx/CDN层开启gzip、brotli压缩,上述两个字体文件原始体积合计约3MB,压缩后可降至1.2MB以内,下载耗时降低60%以上。Nginx配置参考:
gzip on; gzip_min_length 1k; gzip_types font/otf font/ttf application/json application/javascript text/css; brotli on; brotli_types font/otf font/ttf application/json application/javascript text/css;
- 配置强缓存:给字体文件、
FontManifest.json这类带hash的静态资源设置7天以上的强缓存规则,用户二次访问时直接从本地缓存读取,不会重新发起请求。 - 调整资源加载优先级:在
web/index.html的head标签中,给实际使用的Google Fonts添加预加载标签,将非关键的默认字体加载优先级调低,避免阻塞首屏渲染。 - 构建时开启图标树摇:Flutter 3.0及以上版本支持
--tree-shake-icons构建参数,构建时会自动剔除代码中未引用的图标数据,最终打包生成的字体文件体积可缩小70%以上。
方案3:修改SDK源码永久移除默认字体引用(适合固定Flutter版本的项目)
如果不想每次构建都执行后置脚本,可直接修改本地Flutter SDK的默认字体配置:
- 进入本地Flutter SDK目录,打开
packages/flutter/lib/src/material/icons.dart文件,删除文件头部@FontManifest注解中指向MaterialIcons-Regular.otf的配置项 - 打开
packages/flutter/lib/src/cupertino/icons.dart文件,删除文件头部@FontManifest注解中指向CupertinoIcons.ttf的配置项 - 执行
flutter clean清理缓存后重新构建,生成的FontManifest.json将不再包含这两个字体条目,也不会自动打包对应字体文件
注意:该修改会在Flutter SDK升级后被覆盖,升级后需要重新操作。
内容的提问来源于stack exchange,提问作者Drewena
相关产品推荐
相关产品推荐

