1
0
forked from baron/baron-sso

perf(userfront): optimize login web loading

This commit is contained in:
2026-05-15 14:16:34 +09:00
parent 57456bd4cd
commit 4346f48bbe
12 changed files with 383 additions and 62 deletions

View File

@@ -31,6 +31,22 @@ class LocaleRegistry {
static final Set<String> _localeCodes = <String>{};
static bool _initialized = false;
static void primeWithDefaults({
Iterable<String> localeCodes = const ['en', 'ko'],
}) {
if (_localeCodes.isNotEmpty) {
return;
}
_localeCodes.addAll(
localeCodes
.map((code) => code.toLowerCase().replaceAll('_', '-'))
.where(_isValidLocaleCode),
);
if (_localeCodes.isEmpty) {
_localeCodes.add(_safeFallbackLocaleCode);
}
}
static Future<void> initialize({AssetBundle? assetBundle}) async {
if (_initialized) {
return;

View File

@@ -42,11 +42,7 @@ ThemeData buildDarkTheme() {
ThemeData _buildTheme(ColorScheme colorScheme) {
final isDark = colorScheme.brightness == Brightness.dark;
final base = ThemeData(
useMaterial3: true,
colorScheme: colorScheme,
fontFamily: 'NotoSansKR',
);
final base = ThemeData(useMaterial3: true, colorScheme: colorScheme);
return base.copyWith(
scaffoldBackgroundColor: colorScheme.surfaceContainerLowest,

View File

@@ -1,4 +1,5 @@
// ignore_for_file: avoid_print
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
@@ -7,7 +8,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:easy_localization/easy_localization.dart' hide tr;
import 'package:go_router/go_router.dart';
import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'features/auth/presentation/login_screen.dart';
import 'features/auth/presentation/signup_screen.dart';
@@ -90,18 +90,6 @@ void _attemptRecoveryFromNullCheck({
webWindow.redirectTo(target);
}
Future<void> _loadBundledFonts() async {
const family = 'NotoSansKR';
final loader = FontLoader(family);
try {
loader.addFont(rootBundle.load('assets/fonts/NotoSansKR-Regular.ttf'));
loader.addFont(rootBundle.load('assets/fonts/NotoSansKR-Bold.ttf'));
await loader.load();
} catch (e) {
_log.warning("Failed to preload bundled fonts: $e");
}
}
Future<void> _silentSessionRecovery() async {
_log.info("[SessionRecovery] Starting silent session recovery check...");
@@ -165,11 +153,20 @@ Future<void> _silentSessionRecovery() async {
}
}
bool _shouldRunStartupSessionRecovery(Uri uri) {
final requestedLocale = extractLocaleFromPath(uri);
if (requestedLocale == null) {
return true;
}
final path = stripLocalePath(uri);
return !isPublicAuthPath(path, uri);
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
usePathUrlStrategy();
await EasyLocalization.ensureInitialized();
await LocaleRegistry.initialize();
LocaleRegistry.primeWithDefaults();
// 1. Global Error Handling
FlutterError.onError = (details) {
@@ -201,14 +198,6 @@ void main() async {
// 0. Initialize Logger
LoggerService.init();
await ThemeController.app.restore();
await ThemeController.auth.restore();
// 폰트를 먼저 로딩해서 렌더링 깨짐(FOIT/FOUT) 최소화
await _loadBundledFonts();
// 2. Silent Session Recovery (from cookies)
await _silentSessionRecovery();
runApp(
// URL(/en, /ko)이 있으면 우선 적용해서 첫 렌더부터 올바른 언어로 시작합니다.
@@ -552,6 +541,12 @@ class _BaronSSOAppState extends State<BaronSSOApp> {
// Re-run router redirects after the first frame so session-only web
// storage state is reflected even when startup routing evaluated too early.
AuthNotifier.instance.notify();
unawaited(LocaleRegistry.initialize());
unawaited(ThemeController.app.restore());
unawaited(ThemeController.auth.restore());
if (_shouldRunStartupSessionRecovery(Uri.base)) {
unawaited(_silentSessionRecovery());
}
});
}