Библиотека Moment.js

Moment.js — одна из старейших JavaScript-библиотек для работы с датами. Она предоставляет функцию fromNow() для относительного времени, которая по функциональности близка к timeago.js, но существенно отличается по подходу.


Установка и базовое использование

npm install moment
npm install moment/locale/ru  # Не нужно отдельно — включено в пакет
import moment from 'moment';
import 'moment/locale/ru';

moment.locale('ru');

moment(new Date('2025-05-31')).fromNow();          // "1 день назад"
moment(new Date('2025-05-31')).fromNow(true);      // "1 день" (без "назад")
moment(new Date('2025-06-02')).toNow();            // "через 1 день"

moment(new Date('2025-01-01')).from(new Date('2025-06-01')); // "5 месяцев назад"

Сравнение API

Функция timeago.js Moment.js
Относительное время format(date, 'ru') moment(date).locale('ru').fromNow()
Будущее Автоматически через знак moment(futureDate).fromNow()
Кастомная база format(date, 'ru', { relativeDate }) moment(date).from(base)
Смена локали format(date, 'de') moment.locale('de'); moment(date).fromNow()
Автообновление DOM render(el) + cancel(el) Нет — самостоятельно

Размер бандла — критическое отличие

Библиотека Размер (gzip)
timeago.js ~2 KB + ~0.5 KB на локаль
Moment.js ~72 KB (с локалями — 540+ KB без минификации)

Moment.js с локалями — это один из главных антипаттернов в оптимизации фронтенда.


Почему Moment.js считается устаревшим

Официальная документация Moment.js содержит раздел “Project Status: Maintenance Mode”. Авторы признают:

  • Размер бандла нельзя уменьшить без кардинального рефакторинга.
  • API мутабельный — это источник скрытых ошибок.
  • Нет поддержки треешейкинга.

Рекомендованные альтернативы (от самих авторов): Day.js, date-fns, Luxon.


Конвертация moment в нативный Date

Если в проекте есть moment объекты и нужно передать их в timeago.js:

import moment from 'moment';
import { format } from 'timeago.js';

const m = moment('2025-05-31');

// Нельзя передать moment напрямую
// format(m, 'ru'); // Некорректно

// Правильно — конвертировать
format(m.toDate(), 'ru');       // Через нативный Date
format(m.valueOf(), 'ru');     // Через timestamp
format(m.toISOString(), 'ru'); // Через ISO строку

Совместное использование при миграции

При постепенном избавлении от Moment.js в пользу timeago.js:

// Уровень совместимости — обёртка
function formatDate(date, locale = 'ru') {
  // Поддержка как moment объектов, так и нативных дат
  const d = date && typeof date.toDate === 'function'
    ? date.toDate()  // Moment объект
    : date;          // Нативный Date, строка или число

  return format(d, locale);
}

Сравнение формулировок

moment.locale('ru');
const fiveMinAgo = new Date(Date.now() - 5 * 60_000);

moment(fiveMinAgo).fromNow();  // "5 минут назад"
format(fiveMinAgo, 'ru');      // "5 минут назад"

const thirtySecAgo = new Date(Date.now() - 30_000);

moment(thirtySecAgo).fromNow(); // "несколько секунд назад"
format(thirtySecAgo, 'ru');     // "только что" (или "30 секунд назад")

Миграция с Moment.js на timeago.js

# Установить timeago.js
npm install timeago.js

# Удалить moment
npm uninstall moment
// До
import moment from 'moment';
import 'moment/locale/ru';
moment.locale('ru');

function getRelative(date) {
  return moment(date).fromNow();
}

// После
import { format } from 'timeago.js';

function getRelative(date) {
  return format(date, 'ru');
}

Когда Moment.js может оставаться в проекте

  • Проект уже использует обширный момент API (парсинг, форматирование, арифметика).
  • Переход займёт слишком много времени и не является приоритетом.
  • Дата-зависимая логика сложная и Moment.js уже хорошо покрыта тестами.

В таком случае лучше не смешивать — оставить Moment.js для основной работы с датами и не добавлять timeago.js сверху.