S
SuperOleg dev notes
@super_oleg_dev1.8K подп.
1.6Kпросмотров
91.8%от подписчиков
7 мая 2025 г.
Score: 1.8K
Привет! Продолжая кейс с высоким потреблением памяти, обнаружили таки утечку в приложении, и она довольно интересная. Есть такая либа day.js, и ее система плагинов - https://day.js.org/docs/en/plugin/plugin В этой документации рекомендованный подход к расширению - перезапись прототипа класса dayjs: // overriding existing API // e.g. extend dayjs().format() const oldFormat = dayjsClass.prototype.format dayjsClass.prototype.format = function(arguments) { // original format result const result = oldFormat.bind(this)(arguments) // return modified result } У приложения - своя обертка над day.js где как раз есть такой плагин, перезаписывающий метод прототипа. Далее, что мы имеем: - эта обертка и сам day.js вынесены в shared Module Federation чанк - хостовое приложение поставляет этот чанк - в приложении загружается код микрофронта, который использует этот чанк Код микрофронта имеет такой жизненный цикл на сервере: - загружаем код микрофронта как строку - компилируем строку и получаем JS модуль с экспортами - сохраняем этот модуль в LRU кэш (микрофронтов может быть много, новые версии появляются, старые становятся не нужны) - инициализируем Module Federation Проблема - код микрофронта и его скомпилированный результат многократно дублируются в памяти, при этом прослеживается очень длинный трейс - ссылка на метод dayjs. После долгой отладки мы обнаружили, что: - код микрофронта в какой-то момент вытесняется из кэша и загружается заново - код микрофронта инициализируется и вызывает shared модуль - обертку над day.js, что бы получить его экспорты - shared модуль переиспользуется тот же самый, но заново выполняется код плагина через dayjs.extend(plugin) Только на этом вызове, метод в прототипе const oldFormat = dayjsClass.prototype.format - это уже тот метод, который один раз мы заманкипатчили на предыдущем вызове плагина! В итоге на каждое вытеснение микрофронта из кэша мы получаем матрешку перезаписи метода в прототипе, если визуализировать это в псевдокоде: dayjsClass.prototype.format = myFnc - dayjsClass.prototype.format = myFnc(myFnc) - dayjsClass.prototype.format = myFnc(myFnc(myFnc)) - dayjsClass.prototype.format = myFnc(myFnc(myFnc(myFnc))) ... Наглядный кейс про сайд-эффекты, shared зависимости и синглтоны. Что осталось не до конца понятным - как именно утекает ссылка на исходники микрофронта в контекст условной myFnc в коде shared чанка.
1.6K
просмотров
2409
символов
Нет
эмодзи
Нет
медиа

Другие посты @super_oleg_dev

Все посты канала →
Привет! Продолжая кейс с высоким потреблением памяти, обнару — @super_oleg_dev | PostSniper