При серверном рендеринге (SSR) работа с датами в JavaScript требует строгой предсказуемости: любое расхождение между серверным и клиентским временем приводит к гидрационным ошибкам, визуальным «скачкам» интерфейса и трудноуловимым дефектам отображения. Библиотека Day.js используется в SSR-средах как компактная альтернатива Moment.js, обеспечивая иммутабельную модель данных, детерминированное форматирование и минимальный размер бандла при сохранении расширяемости через плагины.
Среда выполнения на сервере и в браузере различается по нескольким критическим параметрам:
Intl API и его конфигурацииВ Node.js по умолчанию используется системный часовой пояс сервера, что может отличаться от часового пояса пользователя. Это создаёт риск несоответствия отображаемых дат между сервером и клиентом.
Day.js по умолчанию не изменяет системное время и опирается на
Date, что делает поведение предсказуемым при условии явного
управления часовыми поясами через плагины.
Для серверного рендеринга ключевым аспектом становится фиксация временной зоны.
Использование UTC как промежуточного формата снижает количество ошибок:
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
dayjs.extend(utc)
const now = dayjs().utc().format()
Переход на UTC позволяет устранить неоднозначность локального времени, особенно при обработке событий, поступающих из разных регионов.
При необходимости отображения локального времени используется явная конвертация:
const timestamp = '2026-05-23T10:15:00Z'
const local = dayjs(timestamp).local().format('YYYY-MM-DD HH:mm')
Основная проблема SSR заключается в совпадении HTML, сгенерированного на сервере, с DOM, созданным на клиенте.
Любая операция, зависящая от текущего времени, потенциально нарушает согласованность:
dayjs().format('HH:mm')
Если сервер и клиент выполняют этот код в разные моменты, результат различается.
Для устранения расхождений используется один из следующих подходов:
const serverNow = dayjs().valueOf()
// передача клиенту
const clientTime = dayjs(serverNow).format('HH:mm')
const formatted = dayjs(timestamp).format('YYYY-MM-DD HH:mm')
Сервер передаёт уже готовую строку, исключая повторное вычисление на клиенте.
Day.js использует неизменяемую модель данных: каждое преобразование возвращает новый объект.
const base = dayjs('2026-01-01')
const shifted = base.add(7, 'day')
const formatted = base.format('YYYY-MM-DD')
base остаётся неизменным, что критично для SSR, где
повторное использование объектов между запросами может приводить к
утечкам состояния при неправильной архитектуре.
В серверных приложениях важно избегать глобальных экземпляров с изменяемым состоянием:
// потенциально опасно при неправильном использовании
const shared = dayjs()
Правильная модель предполагает создание новых экземпляров для каждого запроса:
function renderPage() {
const now = dayjs()
return now.format('YYYY-MM-DD')
}
Day.js расширяется через плагины, каждый из которых должен быть зарегистрирован один раз в контексте процесса.
import utc from 'dayjs/plugin/utc'
dayjs.extend(utc)
import timezone from 'dayjs/plugin/timezone'
dayjs.extend(timezone)
const tokyo = dayjs().tz('Asia/Tokyo')
Важно учитывать, что плагин timezone опирается на Intl и
может вести себя по-разному в минимальных контейнерах или
edge-окружениях.
SSR требует строгой стабильности форматирования строк.
dayjs(timestamp).format('DD.MM.YYYY HH:mm:ss')
Любые локализованные форматы (.locale()) могут приводить
к расхождениям, если сервер и клиент используют разные языковые
настройки.
Пример фиксации локали:
import 'dayjs/locale/ru'
dayjs.locale('ru')
dayjs().format('D MMMM YYYY')
Использование dayjs() без входных данных привязывает
результат к моменту выполнения кода.
В SSR предпочтительнее работать с переданными timestamp:
const createdAt = 1716451200000
const formatted = dayjs(createdAt).format('YYYY-MM-DD')
Это устраняет вариативность между запросами.
В высоконагруженных SSR-системах форматирование дат может становиться затратной операцией при повторяющемся выводе одинаковых значений.
Применяется кэширование:
const cache = new Map()
function formatDate(ts) {
if (cache.has(ts)) return cache.get(ts)
const result = dayjs(ts).format('YYYY-MM-DD HH:mm')
cache.set(ts, result)
return result
}
В некоторых SSR-средах (serverless, edge runtime) доступность
Intl.DateTimeFormat может быть ограничена или урезана.
Day.js в таких условиях сохраняет базовую функциональность, но локализованное форматирование может отличаться.
Режим UTC становится наиболее стабильной базой:
dayjs.utc(timestamp).format()
При использовании React или Vue сервер формирует HTML, который затем «оживает» на клиенте.
Проблемные места:
dayjs() без фиксированного входаformat() с локальюКорректный подход:
function Component({ timestamp }) {
const formatted = dayjs(timestamp).format('YYYY-MM-DD')
return `<span>${formatted}</span>`
}
Day.js оптимизирован под tree-shaking: подключаются только используемые плагины.
Минимальный вариант для SSR:
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
dayjs.extend(utc)
Отсутствие тяжёлых зависимостей делает библиотеку пригодной для высокочастотного рендеринга.
API часто возвращают даты в разных форматах:
Унификация выполняется на входе:
const normalized = dayjs(Number(apiDate))
или
const normalized = dayjs(apiDate).utc()
Нормализация на сервере снижает вероятность расхождений при рендеринге.
SSR требует исключения побочных эффектов при вычислении дат:
Day.js поддерживает этот подход за счёт функциональной модели API и отсутствия внутреннего состояния, зависящего от времени выполнения между вызовами.