gram news
Аватар канала Настя Котова // Frontend & Node.js

Настя Котова // Frontend & Node.js

@startpoint_dev

Фронтендерица с лапками 🐾 Посты каждый понедельник 💃 Копаюсь во внутрянке технологий и рассказываю вам

1,410подписчиков

Открыть канал

Последние посты

  • Настя Котова // Frontend & Node.js

    21 сент., 14:26

    Я к вам с новым анонсом. Этот год я заканчиваю выступлением на HolyJS! Конференция пройдёт 23–24 октября в Санкт-Петербурге и онлайн.Мой доклад называется «Добро пожаловать на сервер: где в Next.js App Router прячутся уязвимости». Будем разбирать архитектуру App Router и смотреть, как из самого её устройства вырастают слабые места.Как всегда, ссылки на все полезные материалы и слайды после доклада тоже опубликую тут.А если вы планируете покупать билеты сами, то можете прийти ко мне в личку @startpoint_forl за специальными условиями.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
    5752155Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    14 сент., 15:31

    В прошлый раз разбирали, зачем нужны using и await using и где они работают. Теперь посмотрим, во что этот синтаксис разворачивается.Если очень грубо, то блок с объявлениями превращается в try/finally, где в finally вызываются собранные методы очистки. Но интересно не это, а детали, которые спрятаны в спецификации.Самое неочевидное: метод очистки берётся у объекта в момент объявления, а не при выходе из блока. Рантайм сразу достаёт [Symbol.dispose], запоминает ссылку на функцию и кладёт её во внутренний стек области. Поэтому подмена метода после объявления ни на что не влияет.const res = { Symbol.dispose { console.log('первый'); } }; { using r = res; res[Symbol.dispose] = () => console.log('второй'); } // первыйОттуда же следует и то, что если у объекта нет нужного метода, TypeError прилетит сразу на строке объявления. При этом null и undefined тоже разрешены, чтобы можно было
    9121131Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    7 сент., 15:45

    В JavaScript регулярно появляются новые возможности, и не про все из них мы вообще узнаём. Так, недавно я познакомилась с using и await using. Мне не довелось их применять на практике, но выглядит это интересно.Смысл в том, чтобы привязать освобождение ресурса к границам блока. Обычно, если мы открыли файл или установили какое-то соединение, то обязаны не забыть всё это закрыть. Сейчас такой код пишется через try/finally, и выглядит примерно так:const file = await open('data.txt'); try { const data = await file.read(); } finally { await file.close(); }Здесь важно, что open стоит до try. Если убрать его внутрь блока, переменную придётся объявлять снаружи через let, а в finally добавлять ?., потому что при падении open значения там ещё нет. С await using всё это пропадает:await using file = await open('data.txt'); const data = await file.read();Файл закроется при любом выходе из
    1,24030322Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    31 авг., 15:14

    В цикле про рендеринг мы разбирали конвейер: стили, лейаут, отрисовка, композитинг. Всё это браузер делает для всего документа сразу, не разбираясь, видит ли пользователь эту часть страницы. На длинной ленте или в большой таблице это значит, что основной поток считает геометрию для того, до чего в этой сессии пользователь может так и не доскроллить.Свойство content-visibility: auto позволяет эту работу отложить. Элемент с таким значением, пока он далеко от вьюпорта, не рендерит своё содержимое, а когда пользователь подбирается ближе, браузер рендерит его вовремя. Важно, что узлы остаются в DOM, ничего не удаляется и не пересоздаётся, в отличие от виртуализации списка на JavaScript..card { content-visibility: auto; contain-intrinsic-size: auto 600px; }Пропущенный элемент с точки зрения лейаута пустой, с нулевой высотой, и без подсказки о размере скроллбар начнёт прыгать. Поэтому
    1,310154431Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    24 авг., 15:25

    Весной мы обсуждали работу с сырыми данными: ArrayBuffer, Buffer в Node.js, SharedArrayBuffer и Blob. Но кое-какие инструменты мы тогда не обсудили, а именно TextEncoder и TextDecoder, пару, которая переводит строки в байты и обратно.API у них достаточно простое: у одного есть encode(), у другого decode(). Однако своих нюансов в их работу добавляет то, что строки в JavaScript хранятся в UTF-16, а данные вокруг (файлы, сеть и т.д.) почти всегда в UTF-8. Поэтому TextEncoder умеет кодировать только в UTF-8, и других вариантов у него нет, а вот TextDecoder принимает десятки кодировок.Дальше начинаются суррогатные пары. Символы выше U+FFFF (эмодзи, редкие иероглифы, некоторые математические знаки) не помещаются в один 16-битный код и хранятся как два. Отдельного внимания заслуживает случай, когда суррогат остался без пары, например, строку обрезали ровно посередине символа. Тогда
    1,5201153Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    17 авг., 15:39

    Когда я готовила материал для цикла про Next.js, то неожиданно для себя узнала, что в нём есть встроенный MCP, который dev-сервер поднимает сам по умолчанию.Начиная с 16-й версии next dev отдаёт MCP-эндпоинт по адресу /_next/mcp, настраивается это поведение флагом experimental.mcpServer. То есть прямо сейчас у любого запущенного на 16-й версии npm run dev этот эндпоинт открыт.Внутри обычная middleware ловит всё, что начинается с /_next/mcp, и передаёт запрос в McpServer. Он живёт ровно там же, где HMR, так что в проде его не существует.Тулов сейчас девять: get_project_metadata, get_routes, get_errors, get_page_metadata, get_logs, get_server_action_by_id, get_request_insights (требует experimental.requestInsights), плюс get_compilation_issues и compile_route — только для Turbopack.Интересное устройство у get_errors. MCP-клиент дёргает тул → dev-сервер генерит request id и шлёт
    1,82011531Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    10 авг., 15:39

    Заключительная часть цикла про Next.js наконец-то здесь! Обобщим всё, о чём говорили до этого, и посмотрим на оптимизации.Next.js изнутри. Часть 9. Способы оптимизации.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
  • Настя Котова // Frontend & Node.js

    3 авг., 15:24

    На прошлой неделе я читала студентам лекцию про настройку инфраструктуры и рассказывала в том числе про кэширование слоёв при сборке Docker-образа.Как всегда, стало интересно, как это работает под капотом?Сборкой занимается BuildKit — компонент Docker, который исполняет Dockerfile. Он преобразует инструкции в граф операций и для каждой вычисляет ключ кэша. Ключи образуют цепочку: ключ текущей операции считается из её описания и ключа предыдущей. Если это COPY, к ним добавляется контрольная сумма копируемых файлов. Например, изменение базового образа меняет ключ FROM, вслед за ним — ключ следующего RUN и так далее.Если подходящий ключ уже есть в кэше, операция не выполняется, а BuildKit использует сохранённый результат. Если ключ изменился, операция выполняется заново. Следующие операции тоже получают другие ключи, поскольку зависят уже от нового результата.Сам результат хранится
    2,1002532Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    27 июл., 14:50

    Отдельно поговорим про dev-mode в Next.js и особенности его работы.Next.js изнутри. Часть 8. Dev-mode.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
    1,97091Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    20 июл., 15:52

    Потихоньку подходим к завершению цикла про Next.js (осталось немного!), и теперь на очереди сборка: Webpack, Turbopack, SWC и не только — что это такое, как оно всё работает и с чем его едят.Next.js изнутри. Часть 7. Сборка.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
    2,1001921Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    13 июл., 15:47

    А вот и моя самая любимая (или нет)) вещь в приложениях на Next.js — кастомный сервер! Посмотрим, что это такое, как он настраивается, и я даже поделюсь историей из своего рабочего проекта.Next.js изнутри. Часть 6. Кастомный сервер.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
    2,140652Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    6 июл., 15:33

    Не останавливаем своё погружение в Next.js! Сегодня поговорим про серверный слой и то, как вообще запрос доходит до рендера.Next.js изнутри. Часть 5. Серверный слой.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
  • Настя Котова // Frontend & Node.js

    29 июн., 15:30

    В продолжении разговора про App Router обсудим prefetch, Server Actions, клиентскую навигацию и даже немного затронем тему безопасности.Next.js изнутри. Часть 4. App Router: навигация, кеш и мутации.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
    2,27073331Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    22 июн., 15:01

    На очереди App Router, и материал получается такой плотный, что я решила разбить его на две части. В первой посмотрим на ключевые концепции и разберём момент первого рендеринга, без клиентской навигации и server actions.Next.js изнутри. Часть 3. App Router: от запроса до гидратации.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
    2,28095532Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    15 июн., 15:35

    Продолжаем погружаться в Next.js. Сегодня разбираем Pages Router: что создаёт next build, как сервер рендерит HTML при первом заходе и что происходит при клиентской навигации.Next.js изнутри. Часть 2. Как работает Pages Router.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
    2,2601844Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    8 июн., 14:51

    А вот и обещанный новый цикл про Next.js под капотом.И в первой части разберём, из каких слоёв состоит Next.js как система, как они связаны друг с другом и почему архитектура стала именно такой.Next.js изнутри. Часть 1. Архитектура Next.js.
    Иллюстрация к посту канала Настя Котова // Frontend & Node.jsИллюстрация к посту канала Настя Котова // Frontend & Node.js
    2,3603282111Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    15 мая, 15:03

    Недавно на рабочем проекте я обновляла Next.js с 12-й на 16-ю версию. Далось непросто, так как были кастомный сервер на NestJS и связка через пакет nest-next, который последний раз обновлялся три года назад. Больно и неприкольно, но мы справились 💪Этот опыт вдохновил меня наконец заняться тем, что я так долго откладывала — сходить в отпуск. Ну и написать цикл статей про Next.js)Так что впереди нас ждёт трёхнедельный перерыв на канале, а после него — новый цикл, не переключайтесь!
    2,36050166111Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    11 мая, 15:45

    Продолжая тему с небольшими оптимизациями в браузере — сегодня поговорим про заголовок stale-while-revalidate.Полностью он используется так: Cache-Control: max-age=600, stale-while-revalidate=30Что здесь происходит: - 0–600 сек — ресурс свежий, отдаётся из кэша - 600–630 сек — ресурс устарел, но браузер всё равно отдаёт его мгновенно, а в фоне идёт за новой версией - после 630 сек — кэш полностью стух, пользователь ждётКлючевой момент: пользователь, попавший в stale-окно, видит старую версию. Фоновый запрос незаметно обновляет кэш, и уже в следующий раз посетитель получит свежие данные.Где его используем, а где нет? - Нехешированная статика (/logo.png, /fonts/custom.woff2) — используем, потому что URL не меняется при обновлении файла. - API-ответы и HTML, которые меняются нечасто (каталог, лендинг, результаты поиска) — тоже используем, это даёт мгновенный ответ, а данные отстают
    2,5602211Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    4 мая, 15:17

    Что такое back/forward cache (bfcache)Когда пользователь нажимает «назад» или «вперёд», браузер может не загружать страницу заново, а достать из памяти полный снимок: DOM, JS-кучу, состояние скролла — всё. Страница замораживается при уходе и размораживается при возврате. Переход ощущается мгновенно, потому что это не навигация в привычном смысле — это restore.Браузер делает эту оптимизацию автоматически, но страница должна соответствовать определённым условиям. Она не попадёт в bfcache, если:- есть listener на unload - открыт WebSocket - на документе стоит Cache-Control: no-store - есть незавершённая IndexedDBтранзакция - и другие причиныПолный список можно посмотреть на MDN.Диагностировать всё это можно прямо в DevTools: вкладка Application → Back/forward cache. Там можно протестировать, попадает ли страница в bfcache, и если нет — увидеть конкретный список блокеров.Для прод
    2,150384411Открыть в Telegram
  • Настя Котова // Frontend & Node.js

    27 апр., 16:10

    Почему JSON.parse() может быть быстрее объектного литералаКазалось бы, const config = {a: 1, b: 2, c: 3} — это самый прямой способ создать объект. Но если объект достаточно большой (от ~10 KB), JSON.parse('{"a":1,"b":2,"c":3}') окажется быстрее. На бенчмарке от GoogleChromeLabs на файле в 7 МБ JSON.parse оказался в 1.7× быстрее объектного литерала в V8, в Safari разница доходила до 2×.Причин несколько. Во-первых, грамматика JSON тривиальна по сравнению с JS — у движка для неё отдельный, более простой и быстрый парсер. Объектный литерал — это полноценный JS-код, который проходит весь путь: токенизация → AST → байткод. Так же, как описано в блоге V8, большие объектные литералы могут парситься дважды — сначала при preparsing, потом при lazy-parsing. Строка внутри JSON.parse этой проблемы лишена.В реальном кейсе с SSR-приложением на Redux такая замена дала улучшение Lighthouse-скора с
    2,160309321Открыть в Telegram