Настя Котова // Frontend & Node.js
503 subscribers
37 photos
1 file
101 links
Фронтендерица с лапками 🐾
Посты каждый понедельник 💃 Копаюсь во внутрянке технологий и рассказываю вам
Download Telegram
#startpoint_dev_nodejs
Как-то вечером я задумалась: мне ведь нравится Node.js, но я знаю о нём далеко не всё. Так зародилась идея копнуть глубже — разобраться в таинственных механизмах, которые заставляют эту систему работать на благо разработчиков.

Поэтому приглашаю вас в увлекательное путешествие по просторам вечных циклов макро- и микротасок, setTimeout-ов и nextTick-ов. Мы будем постепенно погружаться, в частности, в работу Event Loop — от базового “что это вообще такое” до фундаментальных вещей, на которых строится Node.js.

P. S. Я пишу эти посты прямо сейчас и, как истинный писатель, сама не знаю, куда заведёт меня эта история и чем закончится путь её героев. Так что если у вас есть интересные темы или экзистенциальные вопросы про Node.js — пишите, будем разбираться вместе!)

Event Loop крутится, Node.js мутится. Часть 1. Браузер VS сервер.
👍4
Я долго к этому шла и наконец пришла!

Первое (и я надеюсь, не последнее) мое выступление в этом году как спикера. На митапе MinskJS я буду рассказывать про пугающую ошибку с node-gyp, как её одолеть и прийти к победе.

Подключайтесь в эту среду сюда 👉 https://youtube.com/live/ILRrXYSthsA
(запись будет!)
🔥3
Недавно решила переименовать локальный домен для проекта. Всё выглядело логично и красиво, но при запуске браузер выдал ошибку net::ERR_CERT_COMMON_NAME_INVALID и отказался доверять соединению.

Проблема оказалась в сертификате.

Для локальной разработки мы используем local-ssl-proxy и сертификат, выписанный на local.yandex.ru. Старый домен попадал под *.local.yandex.ru, и всё работало. А вот новый оказался на уровень глубже — и браузер это не простил.

Дело в том, что такие сертификаты (*.example.com) покрывают только один уровень поддоменов.
То есть api.local.yandex.ru — ок, а something.api.local.yandex.ru — уже нет.

Полезное напоминание: при работе с HTTPS даже локально лучше учитывать такие нюансы, иначе можно долго искать, почему всё сломалось, хотя раньше работало 🤡
👍2
Сегодня исполняется ровно год этому каналу!

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

1️⃣ Первое место — серия постов про подкапотную работу Node.js в контексте Event Loop, но не только. Над ней я продолжаю работать прямо сейчас. Уже вышло три статьи, и на подходе еще три.
Event Loop крутится, Node.js мутится. Часть 1. Браузер VS сервер.
Event Loop крутится, Node.js мутится. Часть 2. Нюансы работы Event Loop.
Event Loop крутится, Node.js мутится. Часть 3. За пределами Event Loop.

UPD: Оставшиеся три статьи из цикла:
Event Loop крутится, Node.js мутится. Часть 4. HTTP-сервер.
Event Loop крутится, Node.js мутится. Часть 5. Настоящая многопоточность.
Event Loop крутится, Node.js мутится. Часть 6. Профилировать и замерять.

2️⃣ Две части про pnpm — лично я, после подготовки этих статей стала сильным фанатом pnpm, присоединяйтесь, если ещё нет)
Pnpm: чем он так хорош?
Pnpm: особенности peer dependencies при работе над проектом

3️⃣ Пошаговая инструкция с примером, как настроить обвязку всех нужных линтеров в проекте с нуля — на мой взгляд, получился очень полезный гайд
Как настроить Prettier, ESLint, Stylelint и Husky в проекте с нуля

4️⃣ Статья с гифками про работу breakpoints в Chrome — хорошо визуализирует все основное, что нужно знать про дебаг в браузере
Инструменты отладки: точки останова и дебаг в DevTools

5️⃣ Рассказ про JWT и его использование — дает базовое overview этого инструмента
JWT - что это такое и с чем его едят

6️⃣ Отличия Webpack, Babel, Vite, Esbuild и других инструментов — для тех, кто устал путаться, как и я в своё время
Webpack, Babel, Vite и другие инструменты: что, зачем и в чем отличия

7️⃣ Небольшая заметка с примерами про useLayoutEffect — для понимания, когда этот React-хук может пригодиться
Что такое useLayoutEffect?

А также не могу не отметить появившуюся запись моего недавнего выступления с докладом на MinskJS. Там я развеиваю страхи вокруг ошибки с node-gyp. Приятного просмотра!)
🔥9
Недавно мне понадобилось быстро прогнать нагрузочный тест для одной гипотезы в духе: “а что будет, если на сервер одновременно упадёт 1765323 запроса?”

Так я познакомилась с autocannon.
Установка — одна команда, запуск — в одну строку.
Результат — удобная табличка со всеми нужными метриками. Подходит и для локальной проверки, и для CI.
Кастомизировать тоже можно, но в моём случае хватило дефолта.

Люблю инструменты, которые делают много, а требуют мало.
npx autocannon https://localhost:3000
🔥6👍3
За последнее время в канал добавилось много новых людей — добро пожаловать! 💫

Здесь я в основном выкладываю статьи и посты с разбором всяких интересных технологических загогулин (в последнее время особенно много по Node.js). Но сегодня решила разбавить контент мемом)

У меня, признаюсь, есть одна проблема — я не очень хорошо знаю английский. Поэтому иногда, чтобы побыстрее найти ответ, перевожу статьи или куски документации через переводчик. И конечно, он часто выдает перлы. Подвезла вам некоторые из них (последний не имеет ничего общего с разработкой, но тоже смешон).
13😁5👏3🔥1😢1
Сборка мусора в Node.js

Когда мы говорим о сборке мусора в JavaScript, мы имеем в виду то, как это реализовано в движке. В случае и Node.js, и большинства браузеров (например, Chrome) речь идёт про один и тот же механизм: сборку мусора в V8.

Сердцем движка V8 является Generational GC — поколенческая сборка мусора. Её основная идея: объекты, которые живут долго, — редкость, большинство умирает вскоре после появления (феномен “высокой детской смертности”). Чтобы использовать это наблюдение, V8 делит память (heap) на поколения:
- New space — молодое поколение. Здесь появляются все новые объекты. Это небольшая область памяти, которую можно быстро и часто очищать.
- Old space — старое поколение. Если объект прожил несколько циклов сборки в New space и всё ещё нужен — его «повышают» и переносят сюда. Эта область больше по размеру и чистится реже.

Внутри New space работает Scavenge — быстрый алгоритм копирования. Его реализация основана на двух зонах:
- From-space — где живут текущие объекты.
- To-space — пустая зона, куда будут скопированы только «живые» объекты.

Когда запускается сборка, GC перебирает объекты из from-space, и те, которые всё ещё достижимы (то есть на них есть ссылки), копируются в to-space. Остальные просто забываются — они исчезают вместе со старой областью. Затем роли зон меняются. Такой подход прост и быстр: не нужно ничего удалять, достаточно скопировать нужное.

Но этот трюк работает, пока объектов немного — он отлично подходит для New space, где всё ещё «свежее». А вот для Old space он неэффективен: там уже много данных, копировать всё — слишком дорого.

Для старого поколения V8 использует алгоритмы Mark-Sweep и Mark-Compact:
- Mark-Sweep: сначала проходит по графу объектов, помечая «живые». Потом всё, что не помечено, удаляется. Это экономно по времени, но может оставить фрагментированное пространство.
- Mark-Compact: дополнительно уплотняет память, передвигая объекты в один конец heap-а, чтобы не оставалось дыр. Это происходит небыстро, но снижает фрагментацию.

Обе эти стратегии медленнее, чем Scavenge, но подходят для устойчивых структур данных, которые не хочется копировать по несколько раз.

Чтобы сборка не вызывала внезапных тормозов, V8 применяет ещё и инкрементальные и конкурентные оптимизации:
- Incremental GC разбивает большие этапы сборки на мелкие порции и выполняет их между основными задачами.
- Concurrent GC работает в отдельных потоках, параллельно с кодом, стараясь вообще не останавливать исполнение.

Таким образом, сборка мусора в V8 — это не один алгоритм, а комбинация техник, каждая из которых применяется в нужное время и в нужном месте.
И, в отличие от браузеров, в Node.js у нас есть возможность чуть больше контролировать процесс: если запустить скрипт с флагом --expose-gc, можно вручную вызывать в коде global.gc() — это бывает полезно, например, в нагрузочных тестах, о которых мы, кстати, говорили совсем недавно)

#startpoint_dev_nodejs
👍11🔥41
Недавно увидела в одной статье аббревиатуру REPL, которая оказалась для меня на первый взгляд незнакомой. Но на самом деле, я знаю, что это такое, и хочу, чтобы теперь знали и вы)

REPL — это Read–Eval–Print–Loop: интерактивная оболочка, в которой можно писать JavaScript-код построчно, и он сразу выполняется. Похоже на консоль в инструментах разработчика в браузере.

Когда мы просто запускаем node в терминале и дальше можем писать разные команды вида 2 + 2 — вот это и есть REPL.

Неожиданность для меня была в другом. В Node.js есть отдельный модуль для REPL. С его помощью можно встроить собственный REPL прямо в код, например, для дебага приложения.

Такой подход используется и в NestJS. Запустить REPL там можно командой npm run start -- --entryFile repl, если заранее настроен файл repl.ts (документация). Там можно получить доступ к инстансам сервисов и вызывать их методы руками. И для реализации такого механизма NestJS как раз использует модуль repl, исходники можно посмотреть тут.

А волшебный доступ ко всем сервисам приложения реализуется с помощью дополнения контекста repl. Вот так можно сделать свой микро-repl с доступными в контексте переменными и функциями:

import repl from 'node:repl';

const context = {
hello: 'world',
add: (a, b) => a + b,
};

const r = repl.start('> ');
Object.assign(r.context, context)


Вывод будет вот такой:

node repl-test.js
> hello
'world'
> add(2, 3)
5
>


#startpoint_dev_nodejs
🔥17👍42
Что происходит при старте Node.js?

Когда мы запускаем node index.js, Node проходит несколько этапов:

1. Инициализация C++-окружения
Node настраивает V8 (движок JavaScript) и инициализирует libuv (который отвечает, в частности, за event loop). Также здесь парсятся аргументы командной строки (--inspect, --require и др.).

2. Передача управления JS-модулям
Далее Node загружает свои «системные» JS-модули — те, что реализуют, как работать с require и import, как находить зависимости, как всё это грузить. Он также создаёт JS-контекст: тут появляются global, process, console и прочие глобальные объекты и функции, которые всегда доступны.

3. Выполнение скрипта
Теперь Node готов исполнить index.js. Всё, что мы написали (включая синхронные импорты), выполняется сразу, до того, как event loop заработает.

4. Запуск Event Loop
Когда синхронная часть кода отработала, Node передаёт управление libuv: стартует event loop, который начинает обрабатывать таймеры, сетевые события и т.д.

#startpoint_dev_nodejs
115🔥4👍1
Из чего состоит память в Node.js?

Любой процесс в Node.js использует несколько разделов памяти:
- Стек (stack) — область для хранения вызовов функций и локальных переменных, управляется ОС.
- Куча (heap) — основная память для JS-объектов, управляется движком V8 и сборщиком мусора (GC).
- Нативная память — сюда входят буферы (Buffer в Node.js), C++-addons, другие служебные сущности (для libuv, Event Loop и т.д.).

Все эти разделы вместе образуют RSS (Resident Set Size) — общий объём памяти, выделенный процессу ОС.

Чтобы посмотреть, сколько памяти сейчас используется, можно вызвать process.memoryUsage().

Этот метод возвращает объект с такими полями:
- rss — вся память процесса, включая всё нативное.
- heapTotal — объём JS-кучи, зарезервированный V8.
- heapUsed — реально используемая память в куче.
- external — нативная память.
- arrayBuffers — конкретно память ArrayBuffer и Buffer (часть external).

#startpoint_dev_nodejs
9👍8
Вы не ждали, а мы припёрлись тут опять с циклом статей.

Как же мне понравилось разбираться в каком-то вопросе путём ресёрча и написания статьи на эту тему. Так я, после цикла про Event Loop, когда меня в очередной раз занесло в исходники Node.js, решила чуть лучше познакомиться с libuv — той самой культовой библиотекой, на которой, кажется, построен весь Node.js. На этот раз, по моим планам, он должен получиться короче, буквально на 3 (может 4) статьи.
Как принято говорить на ютубе, заваривайте себе чаёк или кофеёк, и присоединяйтесь, будем постигать libuv вместе 💫

Погружение в libuv. Часть 1. Зачем он нужен?

#startpoint_dev_nodejs
15🎉4🔥1