Бенчмарк и производительность
Этот бенчмарк воспроизводит архитектуру тестирования paraglide-js benchmark. Он симулирует работу современных многоязычных веб-приложений при начальном пререндеринге и гидратации на клиенте, измеряя общий объем сетевого трафика (HTML + рантайм JS + языковые чанки), необходимый клиенту.
Контекст сценария: В чисто статическом MPA без клиентского JavaScript сервер напрямую отдает готовый локализованный HTML, поэтому накладные расходы на i18n на клиенте равны нулю. Данный бенчмарк моделирует современные полностековые приложения с гидратацией на клиенте, динамическими интерактивными элементами (например, валидацией форм, клиентскими уведомлениями) и маршрутизацией, измеряя суммарный объем статических ресурсов, загружаемых для достижения интерактивного состояния.
Оцениваемые библиотеки и конфигурации:
ts-intl(легковесный рантайм): протестирован в режимахdefault(все языки в общем бандле) иlocale-splitting(динамическая загрузка чанков по локалям).paraglide(компиляторный подход): протестирован в режимахdefault(общий бандл скомпилированных функций) иexperimental-middleware-locale-splitting(разделение чанков с помощью middleware маршрутизации).i18next(традиционный рантайм): протестирован в режимахdefault(общий бандл со встроенными JSON-словарями) иhttp-backend(асинхронная загрузка JSON на клиенте).
Сравнение объёма передаваемых данных
Измерения проводились с использованием Playwright Headless Chromium с фиксацией объёма всех успешных сетевых HTTP-передач 2xx/3xx вплоть до события networkidle:
Playwright Headless Chromium · Real HTTP Transfer Size
Матрица данных бенчмарка
Базовая нагрузка: 100 сообщений перевода, отображаемых на странице (20% содержат переменные динамической интерполяции).
Сценарий 1: Масштабированное приложение (10 локалей · Пространство имён на 500 сообщений)
В этом сценарии пространство имён содержит 500 сообщений, из которых 100 задействованы и отрендерены на странице:
| Библиотека и конфигурация | Общий размер передачи | В сравнении с i18next Default | Технические особенности |
|---|---|---|---|
| paraglide (middleware splitting) | 36.3 KB | -91.4% | Компиляция в JS-функции; tree-shaking неиспользуемых ключей; чанк локали |
| ts-intl (locale-splitting) | 57.8 KB | -86.2% | Рантайм-ядро ~2 KB; загрузка JSON только активной локали (500 сообщений) |
| paraglide (default) | 76.6 KB | -81.8% | Tree-shaking неиспользуемых ключей; компилированные функции для 10 локалей |
| i18next (http-backend) | 188.7 KB | -55.1% | Асинхронная загрузка JSON активной локали; включает базовый рантайм i18next |
| ts-intl (default bundled) | 360.0 KB | -14.4% | Объединение словарей JSON для всех 10 локалей (500 сообщений) в общий бандл |
| i18next (default bundled) | 420.4 KB | Базовый уровень | 10 словарей JSON + полный рантайм i18next в одном общем бандле |
Сценарий 2: Стартовое приложение (5 локалей · Пространство имён на 100 сообщений)
В этом сценарии пространство имён содержит 100 сообщений, и все 100 сообщений задействованы и отрендерены:
| Библиотека и конфигурация | Общий размер передачи | В сравнении с i18next Default | Технические особенности |
|---|---|---|---|
| ts-intl (locale-splitting) | 29.7 KB | -83.8% | Рантайм-ядро ~2 KB; загрузка JSON только активной локали (100 сообщений) |
| paraglide (middleware splitting) | 36.1 KB | -80.3% | Загрузка 100 скомпилированных функций сообщений только активной локали |
| paraglide (default) | 47.1 KB | -74.3% | 100 скомпилированных функций сообщений для всех 5 локалей в общем бандле |
| ts-intl (default bundled) | 56.9 KB | -69.0% | Объединение словарей JSON для всех 5 локалей (100 сообщений) в общий бандл |
| i18next (http-backend) | 167.5 KB | -8.6% | Асинхронная загрузка JSON активной локали; включает базовый рантайм i18next |
| i18next (default bundled) | 183.3 KB | Базовый уровень | 5 словарей JSON + полный рантайм i18next в одном общем бандле |
Архитектурный анализ
1. Tree-shaking в решениях на основе компилятора
- Компромисс:
paraglideкомпилирует каждое сообщение в отдельную функцию JavaScript. Сборщики (Rollup / esbuild) анализируют AST и исключают неиспользуемые функции во время сборки. В Сценарии 1 все 400 неиспользуемых сообщений полностью исключаются из бандла, что обеспечивает наименьший полезный объём передачи (36.3 KB). - Ограничение: Требует обязательного этапа генерации кода при сборке и не позволяет динамически загружать произвольные JSON-словари во время выполнения.
2. Разделение на чанки в легковесных библиотеках с рантаймом
- Ноль кодогенерации:
ts-intl— это чистая TypeScript-библиотека времени выполнения. Она напрямую работает со стандартными объектами TypeScript или словарями JSON без генерации кода на этапе сборки. - Масштабируемость без роста бандла: В режиме
locale-splittingсборщики разбивают каждый язык на отдельный чанк. Браузер скачивает только чанк активного языка. Как следствие, увеличение числа языков с 5 до 10 и более не увеличивает начальный размер загрузки отдельной страницы (~30 KB против ~57 KB). - Минимальный оверхед рантайма: Ядро рантайма
ts-intlзанимает около 2 KB в минифицированном виде и делегирует форматирование чисел, дат и множественных чисел нативным стандартным Web APIIntlбез внешних полифилов.
3. Причины накладных расходов в традиционных рантаймах
i18nextвключает широкие возможности управления конфигурацией, эмиттеры событий, парсеры AST и кастомные форматтеры, что приводит к большему базовому размеру рантайм-бандла.- В конфигурациях по умолчанию импорт всех языковых словарей в единую точку входа приводит к тому, что все языки попадают в начальный клиентский бандл.
Локальное воспроизведение бенчмарка
Набор тестов бенчмарка расположен в каталоге apps/benchmark. Вы можете воспроизвести измерения локально:
# 1. Установка Chromium (разовая настройка)
pnpm --filter @aaakul/ts-intl-benchmark prebench
# 2. Запуск полной матрицы бенчмарка (сборка SSG + измерения Playwright)
pnpm --filter @aaakul/ts-intl-benchmark bench
# 3. Запуск локального сервера предварительного просмотра (интерфейс доступен по адресу http://localhost:3005)
pnpm --filter @aaakul/ts-intl-benchmark preview