Задайте вопрос и получите краткое содержание документа через любого ИИ-провайдера на этой странице
История версий
- "Добавить сравнение звезд GitHub"v8.9.818.05.2026
- "Инициализация бенчмарка"v8.7.1206.01.2026
Содержимое этой страницы было переведено с помощью ИИ.
Смотреть последнюю версию оригинального контента на английскомIf you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
Библиотеки i18n для Solid - Отчет о бенчмарке 2026
Эта страница представляет собой отчет о бенчмарке i18n-решений для Solid.
Содержание
Интерактивный бенчмарк
Ссылка на результаты:
Посмотреть полные данные бенчмарка
Полный репозиторий бенчмарка можно найти здесь.
Введение
Решения для интернационализации являются одними из самых тяжелых зависимостей в Solid-приложении. Основной риск заключается в передаче ненужного контента: переводов для других страниц и других локалей в бандле одного маршрута.
По мере роста вашего приложения эта проблема может быстро привести к раздуванию JavaScript, отправляемого клиенту, и замедлению навигации.
На практике в наименее оптимизированных реализациях интернационализированная страница может оказаться в несколько раз тяжелее версии без i18n.
Другой аспект - это опыт разработчика: то, как вы объявляете контент, типы, организацию пространств имен, динамическую загрузку и реактивность при смене локали.
TL;DR
- Intlayer: Рекомендуемый выбор для профессиональных Solid-приложений, требующих расширенных функций и оптимизации (v8.7.12).
- @solid-primitives/i18n: Отличная легкая альтернатива для простых проектов, хотя ей не хватает расширенных функций, таких как ленивая загрузка.
- solid-i18next: Стандартный, но тяжелый вариант (~4.7 раза больше Intlayer) с теми же недостатками, что и React i18next.
- Paraglide: Инновационный подход, но сложный DX и проблемы с tree-shaking в некоторых конфигурациях.
Проверьте свое приложение
Чтобы быстро выявить проблемы с утечкой i18n, я настроил бесплатный сканер, доступный здесь.
Проблема
Два рычага необходимы для ограничения стоимости мультиязычного приложения:
- Разделение контента по страницам / пространствам имен, чтобы не загружать целые словари, когда они вам не нужны.
- Динамическая загрузка нужной локали только тогда, когда она требуется.
Понимание технических ограничений этих подходов:
Динамическая загрузка
Без динамической загрузки большинство решений хранят сообщения в памяти с первого рендеринга, что создает значительные накладные расходы для приложений с множеством маршрутов и локалей.
При использовании динамической загрузки вы идете на компромисс: меньше начального JS, но иногда дополнительный запрос при переключении языка.
Разделение контента
Синтаксис, построенный вокруг t('a.b.c'), очень удобен, но часто способствует хранению больших JSON-объектов во время выполнения. Эта модель затрудняет tree-shaking, если библиотека не предлагает реальную стратегию разделения контента для каждой страницы.
Методология
Для этого бенчмарка мы сравнили следующие библиотеки:
Base App(Без библиотеки i18n)solid-intlayer(v8.7.12)@solid-primitives/i18n(v2.2.1)solid-i18next(v17.0.2)@inlang/paraglide-js(v2.17.0)
Фреймворк - Solid с мультиязычным приложением из 10 страниц и 10 языков.
Мы сравнили четыре стратегии загрузки:
Открыть таблицу в модальном окне для четкого просмотра всех данных
| Стратегия | Без пространств имен (глобальная) | С пространствами имен (локальная/scoped) |
|---|---|---|
| Статическая загрузка | Static: Все в памяти при запуске. | Scoped static: Разделено по пространствам имен; все загружается при запуске. |
| Динамическая загрузка | Dynamic: Загрузка по требованию для локали. | Scoped dynamic: Гранулярная загрузка по пространствам имен и локалям. |
Резюме стратегий
- Статическая (Static): Простота; отсутствие задержек сети после начальной загрузки. Минус: большой размер бандла.
- Динамическая (Dynamic): Уменьшает начальный вес (ленивая загрузка). Идеально при наличии множества локалей.
- Локальная статическая (Scoped static): Позволяет организовать код (логическое разделение) без сложных дополнительных сетевых запросов.
- Локальная динамическая (Scoped dynamic): Лучший подход для разделения кода и производительности. Минимизирует использование памяти, загружая только то, что нужно для текущего представления и активной локали.
Что я измерял:
Я запустил одно и то же многоязычное приложение в реальном браузере для каждого стека, а затем записал, что фактически появилось в сети и сколько времени это заняло. Размеры указаны после обычного сжатия веб-контента, поскольку это ближе к тому, что люди загружают, чем к подсчету необработанного исходного кода.
Размер библиотеки интернационализации: После объединения, удаления неиспользуемого кода и минификации размер библиотеки i18n — это размер поставщиков + код hooks/primitives в пустом компоненте. Это не включает загрузку файлов переводов. Это показывает, насколько дорогостоящей является библиотека до того, как ваш контент вступит в игру.
JavaScript на странице: Для каждого маршрута бенчмарка — сколько скрипта браузер загружает при посещении, усредненное по страницам в наборе (и по языкам, где отчет их объединяет). Тяжелые страницы — медленные страницы.
Утечка из других языков: Это контент той же страницы, но на другом языке, который может быть случайно загружен на проверяемую страницу. Этот контент является ненужным и должен быть избегнут. (например, содержимое страницы
/fr/aboutв пакете страницы/en/about)Утечка из других маршрутов: То же самое для других экранов приложения: загружается ли их контент вместе с ними при открытии только одной страницы. (например, содержимое страницы
/en/aboutв пакете страницы/en/contact). Высокий результат указывает на слабое разделение или слишком широкие пакеты.Средний размер пакета компонента: Общие элементы пользовательского интерфейса измеряются по одному вместо того, чтобы скрываться внутри одного огромного числа приложения. Это показывает, незаметно ли интернационализация увеличивает повседневные компоненты. Например, если ваш компонент перерисовывается, он загружает все эти данные из памяти. Присоединение большого JSON к любому компоненту похоже на подключение большого хранилища неиспользуемых данных, которое замедлит производительность ваших компонентов.
Отзывчивость переключения языка: Я переключаю язык с помощью элемента управления приложением и отсчитываю время до четкого переключения страницы, что заметит посетитель, а не микрошаг в лаборатории.
Работа отрисовки после смены языка: Более узкое продолжение: сколько усилий потребовалось интерфейсу на перерисовку для нового языка после инициирования переключения. Полезно, когда "субъективное" время и затраты фреймворка расходятся.
Время начальной загрузки страницы: От навигации до того, как браузер считает страницу полностью загруженной для проверенных сценариев. Хорошо подходит для сравнения холодных запусков.
Время гидратации: Когда приложение это раскрывает, сколько времени клиент тратит на преобразование HTML сервера в то, на что вы фактически можете щелкнуть. Прочерк в таблицах означает, что эта реализация не предоставила надежное значение гидратации в этом бенчмарке.
Звезды на GitHub
Звезды на GitHub - это сильный индикатор популярности проекта, доверия сообщества и долгосрочной актуальности. Хотя они не являются прямым показателем технического качества, они отражают, сколько разработчиков считают проект полезным, следят за его прогрессом и, вероятно, будут его использовать. Для оценки ценности проекта звезды помогают сравнивать популярность альтернатив и дают представление о росте экосистемы.
Результаты в деталях
1 - Решения, которых следует избегать
В экосистеме Solid нет однозначных решений, которых следует избегать.
2 - Приемлемые решения
(solid-i18next) (solid-i18next@17.0.2):
solid-i18next, вероятно, является самым популярным вариантом, так как был одним из первых решений для нужд i18n в JavaScript-приложениях. У него также есть широкий набор плагинов от сообщества для конкретных задач.
Пакет тяжелый (~14.6 КБ, что примерно в 4.7 раза больше solid-intlayer).
Тем не менее, у него те же основные недостатки, что и у стеков, построенных на t('a.b.c'): оптимизация возможна, но отнимает очень много времени, а большие проекты рискуют столкнуться с плохими практиками (пространства имен + динамическая загрузка + типы).
(@solid-primitives/i18n) (@solid-primitives/i18n@2.2.1):
Solid primitive чрезвычайно легкий и эффективный. Я рекомендую это решение для небольших проектов, но ему может быстро перестать хватать функций для профессиональных решений, включая управление куки, перенаправление прокси, форматировщики и т. д. В нем также отсутствует ленивая загрузка и разделение пространств имен для оптимизации размера страницы.
(Paraglide) (@inlang/paraglide-js@2.17.0):
Paraglide предлагает инновационный, хорошо продуманный подход. Тем не менее, в этом бенчмарке рекламируемый ими tree-shaking не сработал для моей реализации. Процесс работы и DX также сложнее, чем у других вариантов.
Лично мне не нравится необходимость регенерировать JS-файлы перед каждым пушем, что создает постоянный риск конфликтов при слиянии в PR.
Наконец, по сравнению с другими решениями, Paraglide не использует стор (например, Solid signal) для получения текущей локали для рендеринга. Для каждого обработанного узла он запрашивает локаль из localStorage / куки и т.д. Это приводит к выполнению ненужной логики, что влияет на реактивность компонентов.
3 - Рекомендации
(Intlayer) (solid-intlayer@8.7.12):
Я не буду лично оценивать solid-intlayer ради объективности, так как это мое собственное решение.
Личное примечание
Это примечание является личным и не влияет на результаты бенчмарка. Тем не менее, в мире i18n часто можно встретить консенсус вокруг паттерна типа const t = useTranslation('xx') + <>{t('xx.xx')}</> для переведенного контента.
В Solid-приложениях внедрение функции в качестве JSX.Element является, на мой взгляд, антипаттерном. Это также добавляет лишнюю сложность и накладные расходы на выполнение JavaScript (даже если это почти незаметно).