В Day.js расширение функциональности реализовано через плагины, которые подключаются к глобальному объекту и модифицируют его поведение через прототипные методы. Базовая архитектура предполагает одноразовую регистрацию расширений, однако в реальных проектах часто возникает пересечение ответственности плагинов, приводящее к конфликтам.
Плагины могут:
Основная проблема заключается в том, что Day.js не изолирует плагины друг от друга: они работают в общем пространстве расширения прототипа.
Наиболее частый тип конфликтов связан с ситуацией, когда несколько плагинов добавляют или переопределяют один и тот же метод.
Например, плагины isSameOrAfter и
isSameOrBefore расширяют цепочку сравнений, а сторонние
плагины могут добавлять собственные методы с пересекающимися
именами.
import dayjs from 'dayjs'
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
dayjs.extend(isSameOrAfter)
dayjs.extend(isSameOrBefore)
Если сторонний плагин вводит метод с тем же именем, происходит тихое перезаписывание:
dayjs.extend(function (option, Dayjs, dayjs) {
Dayjs.prototype.isSameOrAfter = function () {
return true
}
})
В этом случае исходная логика полностью теряется без предупреждений.
Порядок регистрации влияет на итоговое поведение. Некоторые плагины зависят от модификаций, внесённых другими расширениями.
Классический пример — взаимодействие utc,
timezone и advancedFormat.
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
import advancedFormat from 'dayjs/plugin/advancedFormat'
dayjs.extend(utc)
dayjs.extend(timezone)
dayjs.extend(advancedFormat)
При изменении порядка могут возникать следующие эффекты:
format().Некоторые плагины ожидают, что базовые преобразования уже выполнены, и не проверяют состояние входного объекта.
Плагины, работающие с форматированием и парсингом
(customParseFormat, advancedFormat,
relativeTime), часто пересекаются по зоне
ответственности.
import customParseFormat from 'dayjs/plugin/customParseFormat'
import advancedFormat from 'dayjs/plugin/advancedFormat'
dayjs.extend(customParseFormat)
dayjs.extend(advancedFormat)
Проблема возникает при обработке нестандартных форматов:
Особенно критично это проявляется при кастомных форматах вида:
dayjs('2024-01-01 12:00', 'YYYY-MM-DD HH:mm')
Если другой плагин вмешивается в parsing pipeline, результат может отличаться от ожидаемого без явной ошибки.
Плагины utc и timezone формируют одну из
наиболее конфликтных связок, поскольку оба влияют на базовое
представление времени.
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
dayjs.extend(utc)
dayjs.extend(timezone)
Типичные проблемы:
tz();format() и
valueOf().Если utc не подключён до timezone,
последний может работать поверх локального времени, что приводит к
смещению часов.
При использовании сборщиков модулей (Webpack, Vite, Rollup) возможна ситуация, когда один и тот же плагин подключается несколько раз через разные зависимости.
import utc from 'dayjs/plugin/utc'
import utcAgain from 'dayjs/plugin/utc'
Хотя Day.js частично защищён от повторной регистрации, в сложных сборках возможны побочные эффекты:
Особенно это проявляется в monorepo, где разные пакеты используют собственные зависимости Day.js.
Плагины Day.js не всегда синхронизированы по версии API. В экосистеме встречаются расширения, рассчитанные на разные версии ядра.
Основные проявления:
Dayjs.prototype;При подключении таких плагинов возможны ошибки:
TypeError: dayjs.extend is not a function
или скрытые дефекты поведения без явного падения.
Плагины Day.js работают через глобальную модификацию экземпляра, что создаёт эффект «общего состояния».
dayjs.extend(relativeTime)
После этого все экземпляры получают новый метод
fromNow().
Если в проекте несколько независимых модулей инициализируют разные плагины, возникает ситуация:
Плагины локализации (updateLocale,
localizedFormat) могут перекрывать форматирование, влияя на
результат format().
import localizedFormat from 'dayjs/plugin/localizedFormat'
dayjs.extend(localizedFormat)
При одновременном использовании нескольких локализационных расширений:
Некоторые плагины зависят от других, формируя цепочку инициализации. При нарушении порядка цепочка ломается.
Пример зависимости:
timezone зависит от utc;relativeTime зависит от локали;advancedFormat зависит от базового форматтера.Если зависимость не удовлетворена, плагин может:
Архитектурно конфликты уменьшаются за счёт строгого контроля инициализации и изоляции расширений.
Применяются следующие подходы:
Централизованная инициализация
Все плагины подключаются в одном модуле:
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
dayjs.extend(utc)
dayjs.extend(timezone)
export default dayjs
Фиксация порядка подключений
Порядок становится частью контракта приложения, а не имплицитным поведением модулей.
Изоляция сборок
В монорепозиториях используется единая версия Day.js и единый слой расширений, исключающий дублирование зависимостей.
Аудит плагинов
Плагины проверяются на:
Признаки конфликтов проявляются не всегда явно и часто выражаются в несоответствии временных значений или форматов.
Типичные симптомы:
format() и
toISOString();Для анализа используется временное отключение расширений и поэтапное добавление плагинов с фиксацией состояния API объекта Day.js.