Веб-страница
22.3K subscribers
2.14K photos
559 videos
2 files
4.4K links
Всё по фронтенду, бэкенду и девопсу в одном месте

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Сайт: https://tprg.ru/site

Регистрация в перечне РКН: https://tprg.ru/64ai
Download Telegram
SvelteMap умеет создавать значение при первом обращении

Чтобы сгруппировать элементы по ключу, часто приходится сначала вызвать has(), затем создать пустой массив через set() и снова получить его через get(). Этот шаблон повторяется в кэшах и коллекциях интерфейса.

В Svelte 5.57 у реактивной SvelteMap появились getOrInsert и getOrInsertComputed. Первый возвращает существующее значение или вставляет переданное. Второй вызывает функцию создания только для отсутствующего ключа.

Например, groups.getOrInsertComputed(category, () => []) вернёт массив нужной группы, создав его при первом обращении. При этом значения внутри SvelteMap не становятся глубоко реактивными автоматически: если меняете содержимое массива, нужно отдельно продумать, как интерфейс узнает об обновлении.
🔥2❤1👍1
Почему мы пишем своё, когда браузер уже умеет

Разработчик ищет компонент модального окна, хотя в HTML есть <dialog>. Или подключает библиотеку для поведения, которое можно описать в CSS. За этим выбором бывают вполне понятные причины.

В эссе Nolan Lawson разобраны привычки, качество документации и удобство интеграции. Готовая библиотека может предлагать знакомый интерфейс и подробные примеры, а самостоятельная реализация — давать возможность разобраться в механике и попробовать свои идеи.

Автор отмечает и обратную сторону: знание платформы помогает убрать лишний код и снизить стоимость сопровождения. На примере диалога хорошо видно, сколько поведения придётся учесть вручную: клавишу Esc, удержание фокуса внутри окна и его возврат после закрытия.
❤5
Как удержать иконку у первой строки длинной подписи

В списке с align-items: center иконка выглядит нормально, пока подпись занимает одну строку. После переноса она оказывается посередине всего текста. Переключение на start поднимает её вверх, но не центрирует относительно первой строки.

Ахмад Шадид предлагает рассчитывать смещение через высоту строки и размер иконки: calc((1lh - var(--size)) / 2). Значение передают в translateY(). При изменении шрифта или размера значка отступ пересчитывается вместе с ними.

Для иконки в псевдоэлементе дополнительно нужны flex-shrink: 0 и квадратное соотношение сторон через aspect-ratio: 1: длинная подпись не должна сжимать значок.

В разборе с интерактивными примерами можно менять ширину списка, шрифт и размер иконки. Удобный способ проверить компонент на длинных названиях и увеличенном тексте.
🔥5
CSS-значения можно читать в JavaScript как объекты

getComputedStyle() возвращает строки. Чтобы прибавить отступ или изменить размер, приходится разбирать число и единицу измерения. С calc() и трансформациями такая обработка быстро усложняется.

CSS Typed OM представляет значения объектами. Через computedStyleMap() можно получить CSSUnitValue с полями value и unit, а через attributeStyleMap — записать значение, созданное с помощью CSS.px() или CSS.number().

Брамус выпустил полифилл css-typed-om. Его можно подключить глобально или импортировать отдельные классы в модуль. По замерам автора, реализация проходит около 95% подтестов Web Platform Tests для Typed OM.

Поддержка API и отдельных классов различается между браузерами. Полифилл использует CSS-парсер браузера для проверки свойств, поэтому результат зависит и от его возможностей. Перед внедрением стоит проверить именно те значения, с которыми работает ваш компонент.
🔥4👍1
Как перенести сайт на Astro, сохранив React-компоненты

Evil Martians перенесли сайт с Gatsby на Astro, сохранив существующие React-компоненты и обработку содержимого блога. Content collections заменили GraphQL-слой, а новые маршруты постепенно появлялись рядом со старыми в одном репозитории.

Быстрый перенос подготовили заранее. Обработку изображений сначала вынесли в imgproxy ещё на Gatsby: холодная сборка сократилась с 18 до 4 минут. Затем создали воспроизводимую сборку и снимки результата, чтобы сравнивать страницы после изменений.

В разборе миграции команда объясняет, как использовала Claude и проверяла его работу. Сравнение готового HTML помогало замечать изменения, которые легко пропустить при чтении сгенерированного кода.

Новый фреймворк позволил отдельно управлять гидратацией компонентов. Но описанные две недели переноса стали возможны после нескольких месяцев аудита, подготовки и уменьшения зависимости кода от Gatsby.
🔥1
Поле ввода, которое помнит формулу и показывает ответ

В форму нужно внести число, которое сначала приходится вычислить. После копирования ответа из калькулятора исходные значения теряются: при повторной проверке непонятно, откуда взялся результат.

Компонент calc-input позволяет написать 2 + 3 прямо в поле. Пока оно в фокусе, видна формула; после потери фокуса — ответ 5. При возвращении к полю выражение снова доступно для редактирования.

Внутри используются обычные текстовые input в Light DOM и отдельный парсер выражений без eval(). Незаконченная формула вызывает setCustomValidity() и блокирует обычную отправку формы.

Атрибут submit определяет, что попадёт на сервер: формула, результат или оба значения. Это стоит настроить явно: по умолчанию в основном поле отправляется формула. Компонент пригодится в интерфейсах с размерами, количествами и расчётными параметрами.
👍2❤1
Что проверить после автоматической миграции на SvelteKit 3

Команда sv migrate sveltekit-3 выполняет большую часть обновления, но поведение приложения после неё стоит проверить на целевом адаптере.

У Node изменилось обслуживание статических файлов: доступны только ресурсы, существовавшие при сборке. Их проверяют через ETag на основе хеша содержимого, а запросы принимают только с методами GET и HEAD.

В адаптере Cloudflare удалён объект platform: bindings теперь получают из модуля cloudflare:workers. Ещё одно изменение касается single-flight mutations: сервер сообщает об ошибке, если запрошенное клиентом обновление данных не обработано. Намеренный пропуск обозначают через ignore() или ignoreAll().

В октябрьском обзоре Svelte собраны эти изменения и ссылки на руководство по миграции. После обновления проверьте раздачу файлов, доступ к bindings и обновление данных после действий пользователя.
🔥1
Мобильное меню Starlight работает даже без JavaScript

Если скрипт не загрузился, меню документации всё равно должно позволять перейти на другую страницу. В Starlight 0.42 управление мобильным меню перенесли на Popover API. В браузере с поддержкой API оно открывается и при отключённом JavaScript.

В разборе релиза есть демонстрация и ссылка на реализацию. Для своего меню можно начать с той же проверки: отключить скрипты и пройти основные действия с клавиатуры.

В npm-пакете Starlight при этом стало больше JavaScript: исходные TypeScript-файлы теперь компилируются, а типы поставляются отдельно. Это избавляет пользователей от проверки чужих .ts-файлов со своей конфигурацией tsc.

У этих изменений разные адресаты: Popover API уменьшает зависимость интерфейса от клиентского кода, а формат пакета влияет на работу инструментов разработчика. Объём JavaScript в npm сам по себе не говорит, сколько кода получит браузер.
🔥2
Как найти компонент, который тормозит сборку Astro

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

В Astro 7.4 появился `astro build --timings`. Отчёт показывает этапы сборки, плагины Vite, обработку Markdown, изображения и самые медленные страницы.

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

Запросы собрали в родительском компоненте, где данные получали через Promise.all(), а профили передавали вниз. Генерация страниц в этом примере сократилась с 2,10 до 1,13 секунды.

Отчёт помог выбрать место исправления. Сам по себе новый флаг сборку не ускоряет.
👍2🔥2
Свой чекбокс без переписывания его поведения на JavaScript

У чекбокса нужен особый вид, но переключение с клавиатуры, фокус и участие в форме хочется сохранить. Для этого внутри компонента можно оставить настоящий input.

В примере Энди Белла поле лежит в label, занимает всю площадь своей обёртки и получает appearance: none. Рядом находится SVG-галочка, скрытая от вспомогательных технологий через aria-hidden.

Состояние по-прежнему хранит браузер. Селектор input:checked + svg показывает галочку, а :has(input:checked) меняет фон обёртки. Само поле остаётся доступным для фокуса.

Размеры заданы в em, поэтому компонент масштабируется вместе со шрифтом. Для радиокнопок автор показывает тот же подход с другим индикатором. В статье есть живые примеры и полный CSS.
🔥5
Где именно прокрутка должна запустить анимацию? Теперь это видно в DevTools

Анимация срабатывает раньше нужного, а по нескольким CSS-значениям трудно понять почему. Брамус выпустил Scroll-Triggered Animations Debugger — расширение с отдельной панелью в Elements.

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

Есть поддержка scroll(), view() и элементов с position: sticky.

У инструмента есть ограничения: относительные единицы отображаются как вычисленные пиксели, а выбор элемента внутри iframe мешает получить нужные данные. Поэтому для примеров CodePen автор рекомендует отдельный Debug View.
🔥4
GitHub ускорил страницы, отправляя больше готового CSS

При CSS-in-JS часть работы со стилями выполняется во время рендеринга. В большой системе компонентов эта цена повторяется на множестве страниц.

GitHub рассказал о переходе на CSS Modules. Команда переносила стили компонентов и заменяла использование свойства sx отдельными CSS-файлами. Переходные обёртки позволяли продолжать пользоваться компонентами, пока их потребителей обновляли по частям.

Отдельно пришлось отвязать темы от styled-components. Миграцию раскатывали постепенно, с флагами и проверками перед включением.

На части страниц команда наблюдала сокращение времени серверного рендеринга на 1–22%. Это результаты конкретных этапов переноса, а не обещание одинакового ускорения любому проекту после замены библиотеки.
👍1🔥1
Двойное нажатие на кнопку приближает страницу? Есть точечное исправление

Пользователь быстро переключает станции в веб-плеере, а Safari на iPhone принимает нажатия за жест увеличения. Запрещать масштабирование всей страницы ради одной кнопки не требуется.

Энди Белл показал решение через `touch-action`:

.button {
touch-action: manipulation;
}


Значение разрешает перемещение страницы и увеличение двумя пальцами, но отключает двойное касание для зума на этом элементе.

В отличие от user-scalable=no в метатеге viewport, здесь сохраняется возможность приблизить содержимое. Это пригодится кнопкам, которые часто нажимают подряд: переключателям, счётчикам и игровым контролам.

В статье есть два интерактивных примера для сравнения на телефоне.
❤3🔥3👍2
Переходы из Internet Explorer вернулись через View Transition API

Шахматная сетка, жалюзи, растворение пикселями — в старом IE такие эффекты включали метатегом при входе на страницу или выходе с неё.

Брамус воссоздал все 23 эффекта RevealTrans в библиотеке ie-page-transitions. Она читает прежние Page-Enter и Page-Exit, а небольшой скрипт переводит настройки в типы современных View Transitions.

Дальше работает CSS: снимки старой и новой страницы анимируются через clip-path, маски и зарегистрированные пользовательские свойства. На демосайте можно переключать эффекты и смотреть варианты для SPA и обычного многостраничного сайта.

Поддержку нужно проверять для выбранного режима: переходы между документами требуют Cross-Document View Transitions. Библиотека не добавляет этот API браузерам, где его нет.
❤2
Nuxt вводит собственный серверный API поверх Nitro

Серверный код Nuxt-проекта часто импортирует функции из h3 и nitropack. Когда эти зависимости меняют API, обновление затрагивает и приложение, и модули экосистемы.

В Nuxt 4.6 появился `nuxt/server`. Фреймворк предоставляет свои серверные утилиты и типы: события запроса, правила маршрутов и типизированный $fetch.

Это даёт Nuxt возможность адаптироваться к изменениям нижележащих библиотек за собственным интерфейсом. В статье команда объясняет, как такой слой упрощает дальнейший переход к Nitro 3 и h3 2.

Nitro остаётся серверной реализацией по умолчанию. Альтернатива @nuxt/vite-server пока экспериментальная, и команда по-прежнему рекомендует Nitro большинству проектов.
❤2
Как закончить фон целым узором, даже если высота блока меняется

Повторяющийся фон обрезается снизу, потому что текст задаёт произвольную высоту секции. background-repeat: round убирает обрезку, но меняет размер самих плиток.

Ахмад Шадид предлагает округлять высоту блока. calc-size() получает размер, рассчитанный для auto, а round(up, …) увеличивает его до ближайшего значения, кратного высоте узора.

Так при переносе текста меняется высота секции, а размер рисунка остаётся прежним. В статье разобраны внутренние отступы и разница между округлением вверх и вниз: уменьшение высоты может оставить контенту слишком мало места.

На момент публикации автор отмечает поддержку решения только в Chrome. Для остальных браузеров стоит сохранить обычную автоматическую высоту как базовый вариант.
🔥3
Почему запись глубины в шейдере может заставить GPU делать лишнюю работу

GPU умеет отбрасывать скрытые фрагменты до запуска дорогого фрагментного шейдера. Но если шейдер сам меняет глубину, драйверу трудно понять заранее, останется ли такая оптимизация корректной.

В обзоре WebGPU для Chrome 155–156 показано расширение WGSL fragment_depth. Режимы less и greater позволяют явно описать отношение выходной глубины к интерполированной. Это даёт GPU информацию для сохранения ранней проверки глубины.

Наличие расширения проверяется через navigator.gpu.wgslLanguageFeatures. В коде шейдера автор рекомендует явно указать requires fragment_depth;.

Это возможность для конкретного графического алгоритма. Перед использованием нужны проверка поддержки и замеры на целевых устройствах.
🔥2
Как Next.js разобрал полторы тысячи старых issues

Старый отчёт может описывать актуальный баг. Или уже исправленный. Одной даты последнего комментария недостаточно, чтобы решить, пора ли его закрывать.

Команда Next.js создала исследовательского агента `closability`. В отдельной песочнице он читает обсуждение, ищет связанные изменения и при необходимости запускает воспроизведение на разных версиях фреймворка.

На выходе — заключение со ссылками на доказательства. Агент не может сам комментировать, закрывать issues или отправлять код; результаты проверяют мейнтейнеры.

За описанный период в репозитории закрыли 1462 отчёта, включая часть вне этого разбора. Среди причин были уже внесённые исправления, дубликаты и ожидаемое поведение. Это уборка и проверка backlog, а не 1462 новых исправления ошибок.
❤3
Как назвать компонент, чтобы команда понимала одно и то же

Box почти ничего не говорит о назначении. Название по цвету или месту на экране быстро устаревает, когда компонент переносят или меняют тему.

В подборке Виталия Фридмана собраны подходы и справочники для названий компонентов, классов, цветов и дизайн-токенов.

Для интерфейсных элементов есть Component Gallery: примеры из реальных дизайн-систем и альтернативные названия одного компонента. Для классов и функций — Classnames со словами, сгруппированными по поведению, порядку и связям.

Общая рекомендация к именам: понятная структура, конкретный смысл и знакомый команде словарь. Для названий пользовательских функций автор советует сначала узнать, какими словами люди сами описывают задачу и ожидаемый результат.
🔥4
Горячие клавиши для демо можно показывать прямо во вкладке

Системная утилита выводит нажатия поверх рабочего стола. Но при демонстрации только одной вкладки зрители могут не увидеть этот слой.

Брамус сделал веб-компонент `<show-keystrokes>`. Он рисует сочетания клавиш внутри самой страницы, по умолчанию показывая горячие клавиши и навигационные кнопки, без обычного набора текста.

Всплывающий слой использует Popover API, поэтому не прячется за соседними элементами. CSS Anchor Positioning размещает его в углу или рядом с курсором и помогает переворачивать расположение у края окна.

Есть настройки оформления, режим всех нажатий, bookmarklet и расширение для подключения на чужих сайтах. При записи демонстрации полезно проверить, какой режим включён, прежде чем вводить данные.
🔥2