melikhov.dev @melikhov_dev Channel on Telegram

melikhov.dev

@melikhov_dev


Фронтенд, фронт-бек и около. Всё, что в голову пришло. Иногда котики.

melikhov.dev (Russian)

Добро пожаловать на канал melikhov.dev! Здесь вы найдете всю информацию о фронтенде, фронт-беке и многом другом. Наш канал предназначен для всех, кто интересуется веб-разработкой и хочет быть в курсе последних технологий. Мы делимся полезными советами, обзорами инструментов и техниками программирования. А иногда мы радуем вас милыми котиками, чтобы сделать ваш день ярче. Не пропустите новые записи и подпишитесь на наш канал melikhov.dev прямо сейчас! Погрузитесь в мир веб-разработки вместе с нами!

melikhov.dev

14 Feb, 19:51


Уф... Мы готовы. Ждём завтра всех в онлайне, а кому хватило билета — и в оффлайне.

https://ilovefrontend.ru

melikhov.dev

06 Feb, 10:31


Так, важное. Мы заканчиваем подготовку CTF 2025 в рамках Я💛Фронтенд!
Старт 8 февраля в MTk6MDMgVVRDKzM=

Эксклюзивно сливаю ссылку до начала. Осторожно, жёсткий инсайд!

Ссылки на предыдущие CTF тут: https://events.yandex.ru/events/ya-love-frontend-2025

melikhov.dev

19 Jan, 14:37


А вот и запилил лонгрид с картинками
https://teletype.in/@melikhov_dev/S9A-YnENHZs

melikhov.dev

18 Jan, 13:37


А не написать ли пост про мою коллекцию бестолковых часов?

melikhov.dev

06 Jan, 08:02


Пост любви к зиме

melikhov.dev

02 Jan, 14:39


Наверное самая впечатлившая (и даже пугающая) меня технология из 2024 — это нейропереводы видео в Яндекс Браузере. Да, в 2023 уже был у нас крутейший HeyGen, который даже оставлял голос и синхронизировал движение губ. За деньги. Но вот у нас массовый и бесплатный перевод закадровым голосом по кнопке. Всё ещё не могу отделаться от ощущения, что на самом деле это сидят синхронисты на зарплате и никакой технологии под капотом нет.

Вот открываю свежее видео от MPJ (да, он вернулся и запустил курс по D3.js и data visualization), хохмы ради жму кнопку перевода и меня взрывается голова, потому что так не может быть, потому что ещё вчера мы максимум могли получить только корявеший перевод субтитров, а сегодня робот читает с выражением и не пасует перед техническими терминами.

Думаю, что смотреть так англоязычные видео по кодингу пока не стоит, но вот когда этот пока закончится и дети даже не будут думать учить языки? Когда я сам сдамся и перестану слушать в оригинале, потому что ну зачем?

melikhov.dev

31 Dec, 20:53


Новогодний выпуск №455. Вадим, Алексей, Юля, Полина, Никита, Андрей кормят белок, играют колмимейби, красят плитку, ждут группу, спрашивают шляпу и атакуют титанов.

— Видео на Ютубе
— Слушайте на Ютубе
— Ссылки на сайте

melikhov.dev

31 Dec, 19:39


Личные итоги года

В комментах просят не только техническими делиться. Я конечно тот ещё блогер и не думаю, что стоит выносить личное в публичное, но как элемент саморефлексии попробую.

Очень многое изменилось в мой жизни этом году. Тектонические потрясения просто. Меньше котов, больше семьи. Меньше свободного времени, выше цена свободной минуты, что заставляет лучше фокусироваться на важном.

Студия и дом разделились на две не связанные сущности, что наверное даже хорошо. Были бы они ещё бы географически ближе друг к другу.

Было много новых городов, от Гонконга до Гаваны. Но и без дальних поездок старался и стараюсь проводить каждое воскресенье подальше от города. Спонтанно ездил в Выборг микротрипом по утрам, открывал новые веломаршруты мимо Сестрорецких болот. Ночевали в домиках в Ленобласти и Карелии. Катались на моторке по ладожским шхерам и на сапе по Вуоксе, ловили последние летние закаты с островов. Сейчас зима, а значит машину не покидает сноуборд и нужно ещё найти место для горных лыж и может быть даже не для одной пары. Постоянно мысли о машине с большим багажником.

Кстати, о машинах — одно из классных впечатлений этого года это перегон Логана на ручке из Орла в Петербург. Отличная машина оказалась, тем более на палке-то. Балдел всю тысячу километров, в том числе и на пассажирском кресле.

Велосипед не обновлял, всё так же Topstone младшей модели. Но поставил слики чтобы дольше и дальше накручивать по шоссе. Всё ещё не знаю ничего лучше для перезагрузки после рабочей недели чем рано утром в воскресенье укатить из города в сосновый лес. А самое прекрасное — это встать совсем рано и успеть вернуться в дом, где тебя ждут и все только недавно проснулись.

Помните, что люди рядом с вами — они важнее всего остального происходящего в мире. И если рядом с вами таких людей нет, то желаю вам найти их в новом году. Я вот нашёл.

melikhov.dev

31 Dec, 07:41


Технические итоги года

Мне в Яндексе повезло попасть в команду, которая живёт в Гитхабе. Редкий случай для компании, мы не держим код в огромном общем монорепозитории (но мне иногда хочется переехать в свой маленький). И всё то бесконечное количество работы, сделанное за год — вот оно, на зелёном ковре с серыми клеточками отпусков и выходных. Было много работы, было много кода.

Основным рабочим направлением в этом году стала изоляция пользовательских (чужих) скриптов в node.js и в браузере. Копал весь год, пробовал, собирал знания в доклады. Начал обкатывать тему ещё весной в Алматы, бета-версию прокатил в Уфе и финализировал уже как надо в Петербурге на юбилейном Субботнике. Редкий случай для меня, когда за доклад совершенно не стыдно.

В конце года пошёл закрывать пробелы в знаниях, прохожу на Практикуме курс по веб-пентестингу. Рядом лежит незаконченный курс на инженера облачных сервисов, надо и его добить. На следующий год у нас запланировано много Кубернетиса, фронтенд стал совсем не простым. И кто же его таким сложным сделал, кто, я спрашиваю?

Гаджеты года

В конце прошлого года купил стимдек. Железка очень прикольная, но игры опять меня не затянули. Продал. Уж не знаю, хорошо это или плохо, но игры скорее меня утомляют, чем дают удовольствие. Впрочем, Portal 2 был не плох и не забрал много времени.

Весной немного сломался айфон. Телефон уехал на пару месяцев в гарантийный ремонт и пришлось выбирать с чем теперь ходить. Выбрал Pixel 7 и стойко держался. Как только ремонт закончился — тут же перепрыгнул обратно. Причины: ну во-первых Pixel 7 это лопата. Большая и скользкая. А я люблю пользоваться телефонами без чехла (в чехле это какая-то мега-лопата уже). Во-вторых интерфейсы какие-то... ну вот чуть чуть не доделанные. Тут бы шрифт покрупней, тут бы отступы побольше, тут бы анимации плавнее — и другое дело было бы. Кажется, можно сделать ещё один заход, но нужно выбрать что-то поменьше и поприятнее. В том числе тактильно поприятнее (как же хорош простой айфон 15 без чехла: матовая спинка, алюминиевые боковинки).

Оставшись без телефона я тут же лишился и часов. Умные часы мне не нужны, а вот трекать физическую активность я люблю. Пришлось окунуться в мир Garmin и теперь у меня на полочке стоят ряды коробочек с велокомпьютером, нагрудным датчиком и часами. Часами — потому что начал с Vivomove Trend. Красивые, но достаточно бесполезные часы без GPS. Зато со стрелками, которые вечно сбиваются со своих позиций когда трясёшься на велосипеде по гравийным дорогам. Поменял на Forerunner 255 на MIP. Что хочу сказать: заряжать часы не каждый день, а иногда — это свобода почище скайпа. Реально классно. Кнопки на часах это тоже очень здорово. Из минусов — относительно красивые часы Garmin делает только за очень большие деньги, даже думать страшно. Красивые интерфейсы Garmin не делает никогда. Так что хочу посмотреть ещё на Suunto Race S. Финны, не подкачайте.

Купил в этом же году Kindle Scribe на замену вечно разряженному айпаду. Scribe хорош всем, кроме веса. Если вам не нужно читать PDF, то лучше смотреть на версии поменьше. Перо в комплекте прикольное, но с каждым днём я достаю его всё реже. Не стоит того.

Рюкзак года

Достал с антресолей старенький Pacsafe Vibe 40 и так он мне зашёл в поездках! Фактически это чемоданчик на лямках, без кучи карманов, но с очень удобным большим отделением, которое открывается как тот самый чемодан. А большего мне и не нужно.

Что по фитнесу?

Отчаянно борюсь с возрастным замедлением метаболизма. Несмотря на две тренировки в зале в неделю плюс велосипед/сноуборд по выходным, буксую на месте, медленно подползая к психологической отметке в 100 кг. В принципе-то нормально на мои 190 см роста, если бы это были мышцы. Успокаиваю себя, что без спорта было бы хуже. Не затягивайте до 40, с нашей-то сидячей работой и вечными переработками.

Ну вот кажется и всё. За кадром осталось куча важного, про которое вам знать не нужно, да и не место этому в технических итогах.

Всех с наступающим, остаёмся на связи, держимся!

melikhov.dev

29 Dec, 08:15


Зачем писать итоги года, когда ответ есть на https://git-wrapped.com/

Ладно-ладно, чуть попозже напишу.

melikhov.dev

25 Dec, 13:39


Простой совет как драматически улучшить ваши Express-приложения.
Удалите миддлвары — хотелось бы, но не всегда возможно.

Но достаточно запретить передавать req и res дальше контроллера — и вот уже приятнейшие улучшения в нашем коде возникают сами по себе.

melikhov.dev

24 Dec, 11:43


А вот и доклады с Субботника

https://youtu.be/sW63V-B6HMc

Собрал в свой доклад примерно год копаний в теме сендбоксинга JS. Понимаю, что тема очень узкая, но и информации по ней очень мало, тем ценней каждый доклад.

melikhov.dev

15 Dec, 08:44


Начинаем через 15 минут https://www.youtube.com/watch?v=P_cOatmYIbU

melikhov.dev

07 Dec, 15:52


Вспомнил, что уже несколько дней как пора посмотреть доклад Вадима Макишвили «42».
Посмотрел, он не про 42.

melikhov.dev

01 Dec, 13:36


Заметил, что многие пропустили появление satisfies в TS 4.9, а штука-то классная.
Объясняю на пальцах. Иногда нам нужно убедиться, что объект соответствует какому-то типу, но при этом нужно сохранить специфичность типа.


type TestType = {a: number | string; b?: string};

const testObject = {a: 1} as TestType;

testObject.a.toFixed(); // Ошибка: Property 'toFixed' does not exist on type 'string'.



Используем satisfies



type TestType = {a: number | string; b?: string};

const testObject = {a: 1} satisfies TestType;

testObject.a.toFixed(); // Никаких ошибок

testObject.b?.toUpperCase(); // Ошибка: Property 'b' does not exist on type '{ a: number; }'

melikhov.dev

01 Dec, 13:11


Алло, москвичи и рядом! 14 декабря пройдёт ночь опенсорс библиотек, в которой будет участвовать в том числе и моя команда. Событие как минимум необычное.

Сам я туда, к сожалению, не попадаю, так как уже 15 декабря надо быть на Субботнике по фронтенду в Петербурге.

melikhov.dev

14 Nov, 08:22


Никита Прокопов негодует (как обычно). Обновил npm на минор и вылез ворнинг


(node:45421) ExperimentalWarning: CommonJS module /opt/homebrew/lib/node_modules/npm/node_modules/debug/src/node.js is loading ES Module /opt/homebrew/lib/node_modules/npm/node_modules/supports-color/index.js using require().
Support for loading ES Module in require() is an experimental feature and might change at any time
(Use node --trace-warnings ... to show where the warning was created)


Я мимо пройти не мог и решил разобраться. Первопричина понятна — node 23 включил экспериментальную поддержку синхронного require() для ESM-модулей. Зачем нужен ворнинг? Потому что поддержка неполноценная и если прилетит ESM c top level await то всё полетит к чертям (и это очень опасный момент с которым пока непонятно как жить).

Ладно, ясно-понятно, экспериментальная версия node.js споткнулась. Завтра починят. Вроде бы ничего такого. Получается, Никита не прав, у нас всё относительно хорошо? Ну, не совсем.

Интересен другой момент — почему это случилось на миноре npm и как оно работает в обычной node без реквайра? А разгадка простая:

Во-первых supports-color апнули на мажор. Это модуль от Синдре. Ну вы понимаете. Синдре опять переписал всё на pure ESM

Второй момент, как же оно работает сейчас? А никак не работает. Там внутри в debug/src/node.js — try catch


try {
require('supports-color')
} catch (error) {
// Swallow - we only care if `supports-color` is available; it doesn't have to be.
}


И вот это уже печально. Апнули на сломанную версию, ошибок нет (они заглушены).

https://github.com/npm/cli/issues/7857

melikhov.dev

08 Nov, 13:05


Традиционно вылетаю в родную Уфу на Ufadevconf. Наконец-то нашёл куда пристроить доклад про песочницы на node.js-бэкенде. Везу мерч, подходите с вопросами. Трансляции не будет.

Зато будет трансляция на юбилейном Я.Субботнике по фронтенду 15 декабря (что? да, Субботник будет в воскресенье!). Там и зафиналю тему. Непривычно делать так мало докладов за год, но что-то времени не хватает катастрофически.

melikhov.dev

04 Oct, 19:27


Нужен ли режим сепии по умолчанию?

Татьяна Фокина на примерах очень хорошо объясняет, почему тёмной и светлой тем недостаточно для комфортной работы с сайтом.

Часто при разработке темы для сайта тестируют контрастность — и это уже хорошо. Но есть люди с астигматизмом, для которых повышенная контрастность вызывает гало-эффект, то есть буквы и строки начинают двоиться. Эффект сепии как раз убирает излишнюю контрастность, поэтому на тексте проще сфокусироваться.

Многие операционные системы поддерживают похожий режим для всего интерфейса сразу, когда цвета становятся более тёплыми.

Астигматизм — очень распространённая особенность зрения у взрослых, поэтому, возможно, не помешает в браузерах добавить какую-то дополнительную настройку доступности. Но пока такого нет, есть смысл для заботы о пользователях добавить третью тему. Таня верно в статье замечает, что менеджеры такому «обрадуются», конечно. К тому же кому-то тёмная тема как раз более комфортна для зрения, чем режим сепии. Но задуматься о том, что доступность — это не только про контрастность, важно.

https://a11y-blog.dev/ru/articles/is-sepia-mode-essential/

melikhov.dev

04 Oct, 19:27


Ух, да, как довольно сильный астигматик я не переношу высокий контраст тёмных тем и почти всегда выбираю светлые — на них мои глаза болят меньше. Эстетически мне тоже нравятся тёмные, но они просто не совместимы для меня с долгой работой с текстом.

Продолжаю и буду продолжать настаивать, что тёмная тема не может автоматически рассматриваться как «лучше для глаз, лучше ночью». Если запилили только тёмную, то пилите и светлую, пожалуйста.

melikhov.dev

19 Sep, 09:38


HTTP 301/302 vs 307/308

Разницу между этими кодами кажется знают все, кто однажды менял домен в большом популярном сервисе :) Живёте вы годами на одном домене, копите внешние ссылки, прорастают приложения и виджеты. А в один прекрасный день едете на другой домен и вам нужно сохранить всё богатство в рабочем состоянии.

И вот тут появляется вроде бы мелочь (совсем нет) — 307/308 сохраняют оригинальный метод запроса и его body(payload). Ну а 301/302 уходят на новый адрес через GET, теряя всё тело и разрушая все ваши апишки.

melikhov.dev

01 Sep, 07:30


https://youtu.be/DH9vEW5_PiY

Осень — это время когда проекты оживают. Запуски, презентации, становится снова интересно в индустрии.

Я побежал, у меня сентябрь горит.

melikhov.dev

18 Aug, 14:49


Полтора часа с Кириллом хоронили ноду на бэкенде.

https://youtu.be/98qu3CqRNb8

melikhov.dev

17 Aug, 12:27


Не считаю себя адептом свидетелей превосходства отражённого света над излучённым и вообще нахожу, что читать pdf на iPad очень даже приятно. Но iPad для чтения это:

- Вечно севшая батарейка
- Отвлекающие факторы
- Не слишком приятные рукописные заметки

Насмотревшись на хвалебные отзывы на reMarkable 2 проверил его ценник, взгрустнул и взял Amazon Kindle Scribe меньше чем за половину его (reMarkable) цены.

Очень даже доволен. Книги легко загружаются и прекрасно читаются. Размер экрана позволяет почти с комфортом айпада читать и pdf (да, скорость листания пониже и нет цвета). Батарейка вечная. Ну а самое интересное — ручка работает прекрасно, никакие листочки больше не нужны. Ощущения абсолютно бумажные. Перебросил туда все свои тудушники, выписываю задачи рукой и стираю сделанное. Чистый кайф.

Вот размерчик бы ешё поменьше, забить на PDF и оставить только читалку/писалку в корпусе Kindle Oasis — и была бы совсем красота.

Если кому-то довелось вживую сравнивнить reMarkable 2 и Scribe — делитесь в комментах.

melikhov.dev

12 Aug, 21:22


А вот и продолжение истории поддержки TypeScript в Node.js подоспело. Был добавлен флаг --experimental-transform-types, который добавляет возможность запускать файлы с TypeScript-only (требующем трансформации) синтаксисом (Enum, namespace, module с поддержкой source-map). Однако Node.js всё ещё не читает ваш tsconfig.json.

Из интересного: чтобы импортировать (import, require) файл, вам необходимо будет указать расширение .ts, которое включается в TS-конфиге опцией allowImportingTsExtensions. А ещё появилась целая команда для поддержки TypeScript в Node.js.

Кроме того, импорты типов должны быть помечены как type импорты, как при включенном verbatimModuleSyntax в TS-конфиге, иначе вы получите ошибку в рантайме.

import type { Type1, Type2 } from './module.ts';
import { fn, type FnParams } from './fn.ts';



Также предлагается добавить в feature флаги информацию о возможности импортировать файлы с типами или TypeScript-only синтаксисом.

process.features.typescript
// ^? "strip" | "transform"


Всего 4 дня назад в eslint появилась поддержка `.ts` конфигов благодаря jiti, поэтому нововведения в Node.js по импорту .ts файлов облегчат жизнь всему нашему сообществу.

Очень советую к прочтению этот README и ROADMAP, а ещё спасибо @melikhov_dev за упоминание!

Pull Request

melikhov.dev

02 Aug, 11:40


Простой лайфхак как сделать звук на созвоне значительно лучше (причём с обеих сторон), если у вас под рукой только bt-наушники.

Выберите источником звука микрофон ноута и не насилуйте пропускную способность bt-канала.

melikhov.dev

29 Jul, 07:36


Typescript теперь и в Node.js?

В свежем выпуске мы затронули нашумевший PR. Что случилось то? А случилось такое, что в Node.js подвезли в экспериментальном режиме загрузчик для ts файлов. Работает он очень просто (правда просто). В ноду вшивается SWC в виде скомпиленного для WASM бинаря. TS файлы прогоняются через SWC и из них отстреливаются типы. Всё. Enum и namespace не работают (о счастье). Никакие транспиляции трансформации не производятся. Просто отстреливаются типы.

Есть ли проблемы? Конечно есть. Например, нужно писать расширение файлов в импортах. Потому что импорт так работает бай дизайн.

Почему это круто и важно? Потому что транспиляция раздражает. Потому что хочется всё иметь из коробки и без настроект. Накидать ts-файлик и запустить.

В общем, неожиданно и очень приятно.

UPD
Почитайте роадмап обязательно (спасибо @kravetsone, что напомнил)

melikhov.dev

02 Jul, 20:57


Николас Закас (автор ESlint) поделился своими размышлениями про безопасное использование Bun и Deno. Хорошие поинты:

1 Не используйте API, специфичные для Deno или Bun. Это затруднит смену рантайма если что-то пойдёт не так с этими двумя. Придерживайтесь Node.js API, которые уже поддерживаются в Deno и Bun.

2 Используйте префикс 'node:' для внутренних модулей Node.js. И Deno, и Bun поддерживают большую часть внутренних модулей Node.js, но они могут идентифицировать эти модули только при наличии префикса 'node:'. Node.js прекрасно работает при использовании префикса 'node:', поэтому вы можете обеспечить совместимость во всех трех средах выполнения.

3 В Deno используйте пакеты из npm и JSR, а не спецификаторы HTTP-модулей. Одним из первых нововведений в Deno была возможность указывать модули с помощью URL-адресов. Deno по-прежнему остается единственным рантаймом, поддерживающим такой способ загрузки модулей, поэтому лучше всего использовать npm и JSR пакеты, которые можно использовать во всех трех рантаймах.

4 Используйте package.json для указания зависимостей. Deno рекомендует вам использовать deno.json или jsr.json для указания ваших зависимостей, но он также может использовать package.json.

5 Также всегда запускайте на CI проверки совместимости с Node.js. Node.js это отличный запасной вариант, если вы используете Deno или Bun, поскольку не привязан к какой-либо одной компании. Чтобы оставить возможность быстрой смены рантаймов полезно всегда запускать тесты в CI в Node.js даже если вы переходите на Deno или Bun.

Благодаря отличной совместимости Deno и Bun с Node.js API, сейчас проще, чем когда-либо писать единый код для всех трёх сред выполнения. Трюк заключается в том, чтобы нацелиться на Node.js, а затем использовать функции совместимости Deno и Bun. Таким образом, если в любое время произойдет смена рантайма, ваше приложение сможет работать без особых проблем.

melikhov.dev

27 Jun, 13:06


CodeRun. Большой запуск

Делюсь с вами сокровенным. Я в прошлом году писал в этот канал, что мы с большой командой неравнодушных к кодерским соревнованиям людей запустили бету нового сервиса, CodeRun. Мы тогда собрали много полезного фидбека, в том числе от вас.

Сегодня мы выходим из беты! Случилось то, к чему я шёл несколько лет. Очень волнительно 🙂

Теперь у нас есть свой маскот Кодерун, новый брендинг, мультифайловые задачи, подборки, переработанная навигация, профиль участника. И будет ещё больше, бэклог ломится от интересных идей!

Так как я вообще-то фронтендер и хочу больше фронтендерских челленджей, то помимо нового сезона CodeRun мы запускаем скриншотные задачи — задачи, где надо подобрать вёрстку под картинку. Как иногда в проектах бывает, только ещё более пиксель-пёрфект.

Собрал для вас авторскую подборку задач, решать можно туть. Надеюсь, вам понравится сражаться с субпиксельными артефактами в градиентах 😉

А всей большой команде CodeRun хочу выразить огромную благодарность за то, что помогли реализовать мою старую мечту — сделать классный тренажёр с интересными задачами для тех, кто хочет развиваться и прокачиваться. Люблю вас! 💛

https://coderun.yandex.ru/

melikhov.dev

27 Jun, 13:06


Никита молодец, будь как Никита и его команда!

melikhov.dev

12 Jun, 08:21


Бэкстейдж, кстати. В этот раз сильно меньше недоволен результатом, получилось упихнуть в полтора часа больше полезного и гораздо меньше воды. Уже не медь, но до золота ещё пара итераций нужна.

melikhov.dev

09 Jun, 12:51


Очередной забавный кейс с npm

Есть у нас приложение, которое поднимает стенды с приложеньками, «ферма» называется. Вот просто, качает нужную ветку из git, делает условно npm ci && npm run build && npm run start и поднимает инстанс, на который мы натравливаем E2E. Да-да, мы знаем про докер, но пока не успели.

И вот буквально позавчера ловим странный баг. В одной из веток не устанавливается несколько зависимостей. Просто нет их node_modules. Локально не повторяется. Захожу на ферму, дёргаю npm ci из консоли — всё ок. Зависимости не ставятся:

1) только когда npm ci вызывается из самой фермы через child_process.exec,
2) только на конкретной ветке.

Ооок. Я магию не люблю, потому сажусь разбираться. Посмотрим что там в env. Ого, а там npm_config_legacy_peer_deps: 'true' . П-нятненько почему зависимости не ставятся, они же peerDeps.

Две загадки:

1) Откуда legacy-peer-deps залетает в env,
2) Почему он влияет не всегда.

Что ж, ответ на первую. В папке самой фермы в .npmrc лежит legacy-peer-deps=true. Когда мы её запускаем через npm run start npm читает .npmrc и прокидывает в env всю свою лабуду в npm_config_*. А child_process.exec запускает дочерние процессы с process.env родителя.

Ответ на вторую загадку. npm ci --legacy-peer-deps не разрушал приложение, потому что ставил все зависимости как и было написано в package-lock.json. Но в конкретной ветке случилась коллизия, зависимость поставили и в devDependencies и в просто dependencies. Вот после этого npm ci перестал доверять package-lock.json и пересчитал всё дерево, уже тихо применяя к нему правило --legacy-peer-deps.

Люблю я эту работу.

melikhov.dev

07 Jun, 14:33


Скоро запускается открытый лекторий летних школ. Заглядывайте 10-го, кто хочет послушать как я буду 2 часа нудеть про Node.js. Другие лекции тоже интересные!

melikhov.dev

22 May, 21:00


Готовил на Субботник классный доклад про песочницы на Node.js (vm, vm2, v8 isolates, wasm QuickJS и т.д.) и их проблемы. Но, к сожалению, накладка, не попадаю физически. Зато будут другие классные доклады, а свой расскажу как-нибудь попозже.

melikhov.dev

11 May, 19:21


WASM и Докер

Есть одна штука в андроид смартфонах, которая мне бесспорно нравится — это бесконечная лента интересных ссылок по свайпу влево с главного экрана. Буквально вчера подкинули статейку. Оказывается, в оригинальном Docker Engine (который на containerd), можно красиво запускать упакованные в контейнер wasm-приложения. Из уже поддерживаемых рантаймов: WasmEdge, Spin, Slight и Wasmtime.
Штука эта есть в Docker Engine в бета-режиме достаточно давно. Но я-то на OrbStack ушёл. И там пока из поддержки только такой ишью https://github.com/orbstack/orbstack/issues/585

Так ли оно нужно, я пока честно говоря не понял. Но прикольно смотреть куда идёт WASM.

melikhov.dev

01 May, 09:11


Блуждающий ECONNRESET

Достаточно частый кейс в node.js-разработке, когда мы видим в логах блуждающую ошибку ECONNRESET при запросах в другой бэкенд. Начинаем искать, идём на вторую машинку, а там тишина, ошибок в логах нет. Как обычно отвечают — у нас всё хорошо, проблемы на вашей стороне.

Одна из причин это включенный keepalive. Идея keepalive в том, что мы можем переиспользовать коннекшены, не создавать новый коннекшн на каждый запрос. Клиент стучится на сервер, открывает коннекшн, удерживает его и при следующем заходе обращается к уже созданному коннекшену. А что произойдёт, если клиент удерживает коннекшн дольше, чем сервер? Т.е. сервер имеет например keepalive_timeout 4, а клиент создал http.Agent с timeout: 5? Мы и получим тот самый ECONNRESET.

И даже при равных значениях можно достаточно легко войти в состояние гонки:


import http from 'node:http';

const server = http.createServer((req, res) => { res.end('some stuff') });

server.keepAliveTimeout = 5000; //default

server.listen(1337, '127.0.0.1', startSendingRequests);

function startSendingRequests() {
const keepAliveAgent = new http.Agent({keepAlive: true, timeout: 5000});

setInterval(() => {
http.get('http://127.0.0.1:1337', {agent: keepAliveAgent}, (res) => {
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
}).on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
}, 5000)
}


Как решить проблему? Во-первых, если это возжно нужно покрутить таймауты. На клиенте таймаут должен быть меньше чем на сервере. Это даст возможность клиенту закрыть соединение самостоятельно, не дожидаясь ошибки.

Во-вторых, документация node.js предлагает такой паттерн ретрая:


.on('error', (err) => {
// Check if retry is needed
if (req.reusedSocket && err.code === 'ECONNRESET') {
retriableRequest();
}
});


UPD

И конечно важно помнить, что причины, по которым коннекшен может быть закрыт со стороны сервера — разные. Таймаут keepalive лишь один из случаев.