React не следит за фокусом — useFocus из @reactuses/core делает это за него
В React нет состояния, которое говорит, активно ли сейчас поле ввода.
Хук
Для подсветки рамки хватит CSS
Я бы сохранил его для форм и модалок, где фокус важен для UX, а не только для стилей. Разобрали в статье.
В React нет состояния, которое говорит, активно ли сейчас поле ввода.
document.activeElement показывает ответ, но не перерендеривает компонент при смене фокуса, а autoFocus стреляет один раз и не даёт вернуть фокус программно. Приходится вешать onFocus и onBlur вручную.Хук
useFocus из @reactuses/core сворачивает это в [isFocused, setFocused]: первая часть отражает реальное состояние элемента, вторая вызывает focus() или blur() по вашей логике. Например, при программном фокусе на поиске.Для подсветки рамки хватит CSS
:focus, но как только фокус начинает управлять JSX через подсказки, плавающие лейблы или паузу тикера, хук убирает шаблонный код.Я бы сохранил его для форм и модалок, где фокус важен для UX, а не только для стилей. Разобрали в статье.
👍6❤2👎1
JWT-аутентификация: лучшие практики
LogRocket разобрал, как не уронить безопасность аутентификации одним неверным решением. Их вывод простой: access короткоживущий и живёт в оперативной памяти, а refresh длинноживущий — прячется в httpOnly-куках, куда JavaScript не достаёт. Даже при XSS атакующий получит только короткий токен, а не ключ к бесконечному входу.
В статье есть и менее очевидные моменты. Если сейчас проектируете аутентификацию или проверяете текущую схему, рекомендую разбор по ссылке.
LogRocket разобрал, как не уронить безопасность аутентификации одним неверным решением. Их вывод простой: access короткоживущий и живёт в оперативной памяти, а refresh длинноживущий — прячется в httpOnly-куках, куда JavaScript не достаёт. Даже при XSS атакующий получит только короткий токен, а не ключ к бесконечному входу.
В статье есть и менее очевидные моменты. Если сейчас проектируете аутентификацию или проверяете текущую схему, рекомендую разбор по ссылке.
👍3❤1
Forwarded from Типичный программист
Делаем из плоского фото 3D-сцену со светом и тенями
В новом туториале Codrops Dominik Fojcik показывает, как обычное 2D-изображение начинает отбрасывать настоящие тени: без 3D-модели, одной текстурой. Берёте картинку, генерируете карту глубины и пропускаете свет через WebGPU-шейдер в Three.js.
Фишка в том, что готовые карты глубины обычно 8-битные, всего 256 градаций, и на гладких поверхностях свет ловит ступеньки. Автор же разбирает, как конвертировать карту в float, слегка размыть и сохранить в half-float, чтобы шум исчез.
Работает пока только где есть WebGPU. Пошаговый туториал на Codrops.
В новом туториале Codrops Dominik Fojcik показывает, как обычное 2D-изображение начинает отбрасывать настоящие тени: без 3D-модели, одной текстурой. Берёте картинку, генерируете карту глубины и пропускаете свет через WebGPU-шейдер в Three.js.
Фишка в том, что готовые карты глубины обычно 8-битные, всего 256 градаций, и на гладких поверхностях свет ловит ступеньки. Автор же разбирает, как конвертировать карту в float, слегка размыть и сохранить в half-float, чтобы шум исчез.
Работает пока только где есть WebGPU. Пошаговый туториал на Codrops.
❤2🤔2🔥1
Один Vue-фронтенд для десктоп, Android и веб
Одна кодовая база, а на выходе программа для Windows, macOS и Linux, сборка для Android и обычный сайт. Так автор и собрал клиент Reddit: Tauri заворачивает фронтенд в десктоп, Capacitor в Android, а он же открывается как сайт.
За таким решением прячутся четыре счёта. Собрать .msi на маке не выйдет: Tauri опирается на нативный тулчейн каждой системы. На старых Windows программа может открыться белым окном. Дефолтный release-бинарник Rust выходит толстым. А с авторизацией вышла отдельная боль: в браузере OAuth возвращает пользователя на callback-адрес, а в упакованном виде отвечать по нему некому.
Подробности на dev.to.
Одна кодовая база, а на выходе программа для Windows, macOS и Linux, сборка для Android и обычный сайт. Так автор и собрал клиент Reddit: Tauri заворачивает фронтенд в десктоп, Capacitor в Android, а он же открывается как сайт.
За таким решением прячутся четыре счёта. Собрать .msi на маке не выйдет: Tauri опирается на нативный тулчейн каждой системы. На старых Windows программа может открыться белым окном. Дефолтный release-бинарник Rust выходит толстым. А с авторизацией вышла отдельная боль: в браузере OAuth возвращает пользователя на callback-адрес, а в упакованном виде отвечать по нему некому.
Подробности на dev.to.
👍5😁4
Вместо списка из .btn-primary, .btn-secondary и .btn-danger в CSS появится один .btn-*
Чтобы задать общий стиль всем кнопкам, сегодня приходится перечислять классы через запятую или вешать в разметку лишний общий класс. На августовской встрече рабочей группы CSS в Берлине приняли Class Prefix Selector:
Но радоваться рано: фича живёт только в тексте спецификации, ни один браузер её пока не умеет, и до реализации синтаксис ещё поменяется.
#css
Чтобы задать общий стиль всем кнопкам, сегодня приходится перечислять классы через запятую или вешать в разметку лишний общий класс. На августовской встрече рабочей группы CSS в Берлине приняли Class Prefix Selector:
.btn-* цепляет любой класс, начинающийся с этого префикса. Идею предложила Лея Веру ещё в 2024 году.Но радоваться рано: фича живёт только в тексте спецификации, ни один браузер её пока не умеет, и до реализации синтаксис ещё поменяется.
#css
👍8❤5🤩3
Что делать, если участники команды видят только свой участок работы, десятиминутный дейли незаметно растягивается на час, а стопперы всплывают слишком поздно, чтобы успеть на них среагировать? В статье смотрим на работу команды и путь задач от бэклога до релиза, и думаем какие коммуникации действительно нужны в этом процессе.
Отдельно о том, что именно должен проверить разработчик перед первым коммитом и как устроены quality gates перед выпуском версии в прод.
Отдельно о том, что именно должен проверить разработчик перед первым коммитом и как устроены quality gates перед выпуском версии в прод.
❤4👍3
JPEG XL к концу года будет во всех браузерах
Firefox опубликовал intent to ship, Chrome тоже собирается включить формат, у Safari частичная поддержка с 2023 года. За флагом в Firefox JPEG XL жил с 2021-го, но 100 000 строк многопоточного C++ в декодере сочли опасной поверхностью атаки. Mozilla предложила Google Research написать декодер на Rust, так появился
Главный аргумент за формат, по Джейку Арчибальду, прогрессивный рендеринг: картинка в 135 КБ узнаваема после первых килобайт. В Safari этого нет.
По размерам картина смешанная. Фото в вебовском качестве: AVIF 116 КБ против 134 у JPEG XL при SSIMULACRA 2 = 62,8. Без потерь впереди JPEG XL: 1,45 МБ против 1,76 у AVIF и 1,55 у WebP; скриншот 92 КБ против 164. Старые JPEG пережимаются в JPEG XL без потери качества.
Я бы прогнал свой набор картинок через оба кодека. Демо работает в Firefox Nightly, разбор с примерами у Mozilla.
#браузеры #перформанс
Firefox опубликовал intent to ship, Chrome тоже собирается включить формат, у Safari частичная поддержка с 2023 года. За флагом в Firefox JPEG XL жил с 2021-го, но 100 000 строк многопоточного C++ в декодере сочли опасной поверхностью атаки. Mozilla предложила Google Research написать декодер на Rust, так появился
jxl-rs, на нём держится реализация в Firefox.Главный аргумент за формат, по Джейку Арчибальду, прогрессивный рендеринг: картинка в 135 КБ узнаваема после первых килобайт. В Safari этого нет.
По размерам картина смешанная. Фото в вебовском качестве: AVIF 116 КБ против 134 у JPEG XL при SSIMULACRA 2 = 62,8. Без потерь впереди JPEG XL: 1,45 МБ против 1,76 у AVIF и 1,55 у WebP; скриншот 92 КБ против 164. Старые JPEG пережимаются в JPEG XL без потери качества.
Я бы прогнал свой набор картинок через оба кодека. Демо работает в Firefox Nightly, разбор с примерами у Mozilla.
#браузеры #перформанс
❤3👍3
Chrome 152: закрыть диалог кликом по подложке без вычисления координат
Раньше для «закрыть модалку при клике мимо» ловили клик на
Вторая новинка — CPU Performance API: возвращает «tier» производительности процессора, чтобы снижать детализацию графики на слабых устройствах; работает в связке с Compute Pressure API. Пользователь и админ могут переопределить уровень (политика
Третья — заголовок
Рейчел Эндрю собрала релиз по пунктам; origin trial Connection Allowlists шёл с Chrome 148 по 151, в 152 заголовок включён по умолчанию.
#браузеры #javascript #безопасность
Раньше для «закрыть модалку при клике мимо» ловили клик на
dialog и сверяли getBoundingClientRect с курсором. Теперь CSSPseudoElement в JavaScript, кроме ::before, ::after и ::marker, отдаёт ::backdrop, ::scroll-marker и ::view-transition. Клик по подложке становится обычным событием.Вторая новинка — CPU Performance API: возвращает «tier» производительности процессора, чтобы снижать детализацию графики на слабых устройствах; работает в связке с Compute Pressure API. Пользователь и админ могут переопределить уровень (политика
CpuPerformanceTierOverride), так что значение не истина.Третья — заголовок
Connection-Allowlist: список URL-паттернов, куда документу и его воркерам разрешено ходить. Браузер сам режет остальные исходящие запросы, включая те, что делают сторонние скрипты.Рейчел Эндрю собрала релиз по пунктам; origin trial Connection Allowlists шёл с Chrome 148 по 151, в 152 заголовок включён по умолчанию.
#браузеры #javascript #безопасность
❤2👍2
Safari расширяет случайность в CSS: random-item() и random() в custom properties
Сегодня WebKit выложил Safari Technology Preview 251.
Из той же сборки стоит примерить:
В JavaScript главное
Полный список в заметках к релизу.
#браузеры #css #javascript
Сегодня WebKit выложил Safari Technology Preview 251.
random() в Safari уже есть со стабильной 26.2, а теперь добавились random-item() для выбора из списка значений, random() внутри custom properties и ключевые слова кеширования property-scoped и property-index-scoped. Разброс блоков в галерее и вариации анимаций описываются в CSS без скрипта с инлайн-стилями.Из той же сборки стоит примерить:
corner-shape (скошенные и вогнутые углы поверх border-radius), @supports at-rule(...) и popover=hint для подсказок, которые не закрывают другие поповеры.В JavaScript главное
import defer: модуль грузится сразу, а выполняется при первом обращении, это ускорение старта без ленивых import(). Плюс Iterator.zip(), chunks(), windows() и WebAssembly Memory64. Убрали процентное значение -webkit-line-clamp: если оно есть в вашем CSS, вёрстка поедет.Полный список в заметках к релизу.
#браузеры #css #javascript
❤2👍2
Строгий CSP и nginx без пары заголовков ломают WebAssembly на проде
Распознавание паспорта в браузере без отправки фото на сервер делается WASM-модулем. У Smart ID Engine четыре сборки (
Серверные ловушки:
Камера: документу нужно не меньше 120 DPI, оптимальный кадр 1600×1200, веб-камерам ноутбуков на А4 разрешения не хватает, на трёхкамерных iPhone основной модуль не фокусируется ближе 20 см. Android и iOS стартуют камеру в разной ориентации, сверяйте
Пошаговая интеграция с конфигами для
#wasm #браузеры
Распознавание паспорта в браузере без отправки фото на сервер делается WASM-модулем. У Smart ID Engine четыре сборки (
nosimd.nothreads, simd.nothreads, simd.threads, nosimd.threads), нужную выбирают на лету через wasm-feature-detect. SIMD без потоков работает в Safari 17.1+, Chrome 91+ и Firefox 89+.Серверные ловушки:
.wasm отдаётся с Content-Type: application/wasm и сжимается; строгая CSP блокирует JIT, нужна директива wasm-unsafe-eval; многопоточная сборка требует COOP: same-origin и COEP: require-corp.Камера: документу нужно не меньше 120 DPI, оптимальный кадр 1600×1200, веб-камерам ноутбуков на А4 разрешения не хватает, на трёхкамерных iPhone основной модуль не фокусируется ближе 20 см. Android и iOS стартуют камеру в разной ориентации, сверяйте
matchMedia.Пошаговая интеграция с конфигами для
getUserMedia, CSP и nginx.#wasm #браузеры
❤4
Бэкенд для приложения в одном исполняемом файле
PocketBase — это один бинарник, внутри которого сразу SQLite, авторизация пользователей, хранение файлов, REST API, подписки в реальном времени и админка. Ни отдельной базы, ни очереди рядом ставить не нужно: приложение живёт одним файлом на одной машине.
23 августа вышла версия 0.40.0: удаление логов через
В нашем канале «Инструменты программиста» разобрали подробнее, чем PocketBase берёт против Supabase и где ломается совместимость.
PocketBase — это один бинарник, внутри которого сразу SQLite, авторизация пользователей, хранение файлов, REST API, подписки в реальном времени и админка. Ни отдельной базы, ни очереди рядом ставить не нужно: приложение живёт одним файлом на одной машине.
23 августа вышла версия 0.40.0: удаление логов через
DELETE /api/logs, ограничение размера Log.Data примерно 16 килобайтами, Cross-Origin-Opener-Policy: same-origin в заголовках по умолчанию. Порог входа при этом поднялся до Go 1.27.В нашем канале «Инструменты программиста» разобрали подробнее, чем PocketBase берёт против Supabase и где ломается совместимость.
❤1👍1
Плавающий виджет поверх всех окон одним вызовом API
Firefox 151 включил Document Picture-in-Picture API, до этого он был только в Chrome. В отличие от PiP для видео,
CSS-Tricks разобрал API на примере тикера акций. Стили в новое окно не наследуются:
#браузеры #css #javascript
Firefox 151 включил Document Picture-in-Picture API, до этого он был только в Chrome. В отличие от PiP для видео,
documentPictureInPicture.requestWindow() открывает окно поверх вкладок и других приложений с любым HTML внутри: тикер, чат, таймер, заметки. Раньше это требовало расширения или Electron.CSS-Tricks разобрал API на примере тикера акций. Стили в новое окно не наследуются:
<style> и <link rel=stylesheet> клонируют через querySelectorAll() в createDocumentFragment() и одним append кладут в <head>. Ширину и высоту задают только парой, иначе размер выбирает браузер. Фокус уходит в PiP-окно, поэтому кнопка-переключатель закрывает его со второго клика.@supports не поможет: at-rule() есть только в Chrome, остаётся "documentPictureInPicture" in window и скрытие кнопки. Стили под окно пишут через @media (display-mode: picture-in-picture). Только десктоп, Safari мимо, в iframe не запускается.#браузеры #css #javascript
👍2❤1🔥1
WebGPU в Unity вышел из эксперимента
Начиная с версии 6000.6 WebGPU в Unity — полноценный графический бэкенд с обычной поддержкой, а не экспериментальная опция. Для браузера это вычислительные шейдеры, а с ними отсечение невидимого на GPU, апскейлер STP, VFX Graph на миллионы частиц и скиннинг на GPU: на WebGL 2 всё это было недоступно.
Ловушка при выкладке чисто веб-разработческая: WebGPU браузер отдаёт только в защищённом контексте, поэтому сборка, открытая по обычному HTTP или файлом с диска, молча откатится на WebGL 2.
В нашем канале «GameDev» разобрали подробнее, как его включить и почему WebGL 2 нельзя убирать из списка.
Начиная с версии 6000.6 WebGPU в Unity — полноценный графический бэкенд с обычной поддержкой, а не экспериментальная опция. Для браузера это вычислительные шейдеры, а с ними отсечение невидимого на GPU, апскейлер STP, VFX Graph на миллионы частиц и скиннинг на GPU: на WebGL 2 всё это было недоступно.
Ловушка при выкладке чисто веб-разработческая: WebGPU браузер отдаёт только в защищённом контексте, поэтому сборка, открытая по обычному HTTP или файлом с диска, молча откатится на WebGL 2.
В нашем канале «GameDev» разобрали подробнее, как его включить и почему WebGL 2 нельзя убирать из списка.
❤4
Разница между «у нас есть бэкап» и «мы готовы к аварии» — примерно как между наличием огнетушителя и умением им пользоваться при пожаре. Первое не гарантирует второе, а узнают об этом обычно в момент, когда сервис лежит у всех на глазах, включая руководство и клиентов. На самом деле готовность инфраструктуры к сбою определяет не факт хранения копий, а расчёт допустимого времени простоя, структура плана восстановления и техническая настройка репликации, которую проверяют заранее регулярными учениями переключения на резервную площадку. Будет полезно инфраструктурным инженерам, техлидам и руководителям, которые хотят сделать свои системы реально устойчивыми к авариям.
Больше об аварийном восстановлении:
1. Почему бэкап есть, а восстановиться не получится: разбор точек отказа
2. Как должен выглядеть DR-план, который сработает в аварию
3. Аварийное восстановление до аварии: как настроить DRaaS, пока ничего не упало
Больше об аварийном восстановлении:
1. Почему бэкап есть, а восстановиться не получится: разбор точек отказа
2. Как должен выглядеть DR-план, который сработает в аварию
3. Аварийное восстановление до аварии: как настроить DRaaS, пока ничего не упало
❤3
htmx 4.0 вышел и намеренно не стал версией по умолчанию
Восемь месяцев работы, релиз сегодня. Для пользователя четвёртая версия почти совпадает со второй, но внутри библиотека переехала с
Главных изменений авторы называют три, и заметнее прочих наследование атрибутов. В htmx 2 атрибут на родителе по умолчанию действовал на потомков, как в CSS:
Тег
#javascript #фронтенд
Восемь месяцев работы, релиз сегодня. Для пользователя четвёртая версия почти совпадает со второй, но внутри библиотека переехала с
XMLHttpRequest на fetch() — ради этого всё и затевалось.Главных изменений авторы называют три, и заметнее прочих наследование атрибутов. В htmx 2 атрибут на родителе по умолчанию действовал на потомков, как в CSS:
hx-confirm на div спрашивал подтверждение у каждой кнопки внутри. В htmx 4 наследование включается явным суффиксом:<div hx-confirm:inherited="Точно?">
<button hx-delete="/item/1">Удалить</button>
</div>hx-disinherit при этом исчез, его следует убрать. Дальше — имена событий, приведённые к схеме htmx:<фаза>:<система>, и история навигации, которая перестала по умолчанию храниться локально: авторы называют старый кэш источником многих обращений в поддержку. Полный список несовместимостей длиннее трёх пунктов и лежит в руководстве по миграции.Тег
latest в npm остался на ветке 2.x примерно до начала 2027 года, чтобы не переключить силой тех, кто подключает htmx с CDN без указания версии; четвёртая ветка живёт под next. Места, которые надо чинить, ищет команда upgrade-check из комплекта.#javascript #фронтенд
🔥3👍2🥰2💩1
Файл про офисных котов прошёл все четыре «доказательства» пользы llms․txt
Последний год клиентам продают
Марк Уильямс-Кук проверил эту логику так: придумал стандарт
Все четыре «доказательства» файл прошёл, не запнувшись. Боты его скачали, Google проиндексировал, модели начали пересказывать подробности про кота Odd, который не существует нигде, кроме этого файла, а ChatGPT пространно подтвердил, что
Про сам
Вывод, который стоит забрать: набор наблюдений становится доказательством, только если он мог бы не случиться при ложной гипотезе. Скачали, проиндексировали, пересказали — происходит с любым текстовым файлом в корне.
#seo #ии
Последний год клиентам продают
llms․txt — файл в корне сайта, который якобы помогает попасть в ответы языковых моделей. Доказательства всегда одни и те же: ботам файл скачали, Google его проиндексировал, модель пересказала его содержимое, ChatGPT подтвердил, что это помогает ранжированию.Марк Уильямс-Кук проверил эту логику так: придумал стандарт
cats․txt, в котором сайт формально декларирует своих офисных котов — имена, должности, породы и обязательную метрику привязанности PurrLevel по десятибалльной шкале. Написал спецификацию, опубликовал в блоге и отдельно вынес в LinkedIn, потому что модели к этой площадке по непонятной причине благосклонны.Все четыре «доказательства» файл прошёл, не запнувшись. Боты его скачали, Google проиндексировал, модели начали пересказывать подробности про кота Odd, который не существует нигде, кроме этого файла, а ChatGPT пространно подтвердил, что
cats․txt может помочь ранжированию. Идею подхватили: кто-то добавил файл себе на сайт, кто-то поднял catstxt.org с более аккуратной спецификацией, чем оригинал.Про сам
llms․txt автор отдельно оговаривает: ни OpenAI, ни Anthropic, ни Google не документировали его использование в поиске. Джон Мюллер из Google высказался прямее: ни один чат-бот файл не скачивает, это видно по логам сервера. Ahrefs прогнал 100 000 доменов и увидел, что краулеры, ради которых файл кладут, в основном его игнорируют; отдельные крупные исследования не нашли и прироста цитирования.Вывод, который стоит забрать: набор наблюдений становится доказательством, только если он мог бы не случиться при ложной гипотезе. Скачали, проиндексировали, пересказали — происходит с любым текстовым файлом в корне.
#seo #ии
😁7❤1
Zod научился компилировать схемы и стал быстрее в разы
До версии 4.5 парсер интерпретировал схему прямо во время валидации: на каждый
Собирать ничего не нужно, всё происходит в рантайме:
Перед обновлением проверьте два места:
#javascript #перформанс
До версии 4.5 парсер интерпретировал схему прямо во время валидации: на каждый
parse() Zod обходил дерево и по ходу решал, что проверять. Во вчерашнем релизе появился z.compile() — он один раз проходит схему целиком и генерирует под неё плоский JavaScript без циклов, который выполняется через new Function(). На валидных данных срабатывает быстрый путь, на невалидных Zod возвращается к обычному парсеру за подробной ошибкой.Собирать ничего не нужно, всё происходит в рантайме:
import "zod/compile" в точке входа или флаг node --import zod/compile включают компиляцию для всех схем сразу. Ускорились и отказы — .safeParse() перестал захватывать стек-трейс и на неудачном пути стал быстрее примерно в 7,5 раза.Перед обновлением проверьте два места:
z.iso.datetime() больше не принимает время без секунд (2020-01-01T06:15Z теперь ошибка), а .min(), .max() и .length() у строк считают кодовые точки Unicode вместо кодовых единиц UTF-16.#javascript #перформанс
👍6❤3🔥2