You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web浏览器端Golden测试中自定义字体加载失败,loadAppFonts()无限挂起

Flutter Web浏览器端Golden测试中自定义字体加载失败,loadAppFonts()无限挂起

最近帮朋友排查Flutter Web Golden测试的问题时,正好碰到了一模一样的情况——自定义字体加载失败,不管是用golden_toolkit的loadAppFonts()还是手动调用FontLoader,都会无限挂起,导致测试只能用系统字体,和生产环境的渲染效果差老远了。下面我把问题细节、复现步骤以及可行的解决办法整理出来,希望能帮到你。

问题核心

在标记了@TestOn('browser')的Golden测试中,自定义字体无法正常加载,不管是工具库提供的加载方法还是手动实现,都会出现挂起卡死的情况,最终测试只能 fallback 到系统字体,完全失去了视觉回归测试的准确性。

预期应该达到的效果

  • 配置在pubspec.yaml里的自定义字体,能在浏览器端Golden测试中正常加载
  • 测试的渲染效果和生产环境完全一致,保证视觉回归测试的有效性

实际遇到的问题

  • loadAppFonts()在浏览器测试中直接无限挂起,根本没法继续执行后续测试
  • 手动调用FontLoader('Inter').load()也会出现同样的挂起问题
  • 测试被迫使用系统字体,和生产环境的字体渲染效果有明显差异

复现步骤

要复现这个问题,你只需要按下面的步骤操作就行:

  1. 在项目的pubspec.yaml里配置自定义字体:
fonts:
  - family: Inter
    fonts:
      - asset: assets/fonts/inter/Inter-VariableFont_slnt,wght.ttf
  1. 写一个带@TestOn('browser')标记的Golden测试:
@TestOn('browser')
testGoldens('test with custom fonts', (tester) async {
  await tester.pumpWidgetBuilder(MyWidget());
  await screenMatchesGolden(tester, 'test');
});
  1. 在flutter_test_config.dart里加入loadAppFonts()初始化:
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  await loadAppFonts(); // 这里在浏览器测试中会直接挂起
  await testMain();
}
  1. 执行测试命令:
flutter test --platform chrome --update-goldens

我试过的无效方案

当时为了解决这个问题,我试了好几种办法,但都没奏效:

  • 手动用FontLoader加载:直接调用FontLoader('Inter').load(),结果还是挂起
  • 加超时机制:给加载方法加.timeout(),但超时后还是会 fallback 到系统字体,问题没解决
  • 用dart:html注入CSS:尝试直接给浏览器注入字体样式,但遇到了编译问题
  • 换VM环境测试:VM环境下字体加载正常,但没法测试Web端特有的行为,根本不满足需求

环境信息

  • Flutter版本:3.x.x(稳定通道)
  • Dart版本:3.x.x
  • golden_toolkit版本:^0.15.0

可行的解决办法

后来摸索出几个可行的方案,你可以根据自己的情况选择:

1. 给Web端字体加载加超时处理

在flutter_test_config.dart里针对Web环境做特殊处理,给字体加载加个超时,避免无限挂起,同时打印日志提示:

import 'dart:io' show Platform;
import 'package:golden_toolkit/golden_toolkit.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  if (Platform.isWeb) {
    // Web环境下给字体加载设置5秒超时
    try {
      await loadAppFonts().timeout(const Duration(seconds: 5));
    } catch (_) {
      debugPrint('字体加载超时,将使用 fallback 字体继续测试');
    }
  } else {
    await loadAppFonts();
  }
  await testMain();
}

2. 直接用浏览器API预加载字体

绕开Flutter的字体加载机制,直接用dart:html让浏览器提前加载字体,这样测试时就能正常使用自定义字体了:

import 'dart:html' as html;
import 'package:golden_toolkit/golden_toolkit.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  if (html.window != null) {
    // 创建字体样式标签并注入到页面
    final style = html.StyleElement()
      ..text = '''
        @font-face {
          font-family: 'Inter';
          src: url('assets/fonts/inter/Inter-VariableFont_slnt,wght.ttf') format('truetype');
        }
      ''';
    html.document.head?.append(style);
    // 等待浏览器加载完成字体
    await html.document.fonts?.load('12px Inter');
  } else {
    await loadAppFonts();
  }
  await testMain();
}

注意:这种方法要确保测试时能正确访问到字体文件,记得检查pubspec.yaml里的资源配置是否正确,保证字体文件能被测试环境访问到。

3. 升级golden_toolkit到最新版本

有时候这类问题是工具库的已知bug,你可以尝试把golden_toolkit升级到最新版本,看看官方是否已经修复了Web端字体加载的问题:

dependencies:
  golden_toolkit: ^0.16.0 # 替换成当前最新版本

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 07:19:30