Как браузер рисует кадры и где теряется плавность
Экран с частотой 60 Гц обновляется каждые 16,66 мс. С учётом работы браузера нужно уложиться в 10 мс: иначе частота кадров падает, а движение начинает дёргаться.
В разборе web.dev путь визуального изменения разделён на расчёт стилей и геометрии, отрисовку пикселей и сборку слоёв. Свойства
Если анимация дёргается, проверьте в DevTools, какие этапы запускают её CSS-свойства. Начните с тех, что меняют размеры и положение: сокращение лишней работы освобождает время внутри кадра.
Экран с частотой 60 Гц обновляется каждые 16,66 мс. С учётом работы браузера нужно уложиться в 10 мс: иначе частота кадров падает, а движение начинает дёргаться.
В разборе web.dev путь визуального изменения разделён на расчёт стилей и геометрии, отрисовку пикселей и сборку слоёв. Свойства
width, height, left и top заставляют браузер пройти все эти этапы. Для цвета, фонового изображения или тени пересчёт геометрии не нужен. Если свойство не требует и новой отрисовки, браузер сразу собирает готовые слои.Если анимация дёргается, проверьте в DevTools, какие этапы запускают её CSS-свойства. Начните с тех, что меняют размеры и положение: сокращение лишней работы освобождает время внутри кадра.
❤1👍1
Почему CORS устроен именно так и как с ним работать
CORS проще отлаживать, если начать не с заголовков ответа, а с границы, которую охраняет браузер. Страница может загрузить картинку, скрипт или стиль с другого источника, но её код не может прочитать DOM чужой страницы или тело ответа. Источник здесь — сочетание схемы, хоста и порта.
Даже если не отправлять cookie, этого недостаточно. Внутренние панели, роутеры и устройства умного дома могут считать защитой саму локальную сеть, поэтому сервер должен явно разрешить чужой странице читать ответ.
Я сохранил разбор CORS с интерактивной песочницей как карту для отладки трёх слоёв: источников, учётных данных и разрешения сервера.
CORS проще отлаживать, если начать не с заголовков ответа, а с границы, которую охраняет браузер. Страница может загрузить картинку, скрипт или стиль с другого источника, но её код не может прочитать DOM чужой страницы или тело ответа. Источник здесь — сочетание схемы, хоста и порта.
Даже если не отправлять cookie, этого недостаточно. Внутренние панели, роутеры и устройства умного дома могут считать защитой саму локальную сеть, поэтому сервер должен явно разрешить чужой странице читать ответ.
Я сохранил разбор CORS с интерактивной песочницей как карту для отладки трёх слоёв: источников, учётных данных и разрешения сервера.
👍3❤1
Как кэшировать HTML, CSS и JavaScript без рассинхронизации
Короткий
Для неизменяемой статики надёжнее менять URL вместе с содержимым, например добавлять хеш, и задавать
Подробный разбор кэширования пригодится перед настройкой заголовков и service worker. Проверьте, не получают ли изменяемые файлы короткий
Короткий
max-age для изменяемых файлов выглядит компромиссом. Но браузер может оставить старые HTML и JavaScript, удалить CSS из кэша и запросить его заново. Если сервер уже отдаёт новые стили, страница соберётся из несовместимых версий. В тестах это легко пропустить.Для неизменяемой статики надёжнее менять URL вместе с содержимым, например добавлять хеш, и задавать
max-age=31536000. Для HTML подходит no-cache: браузер хранит ответ, но перед использованием сверяет его с сервером через ETag или Last-Modified. Название меткое: кэшировать оно как раз разрешает.Подробный разбор кэширования пригодится перед настройкой заголовков и service worker. Проверьте, не получают ли изменяемые файлы короткий
max-age, а для статики версионируйте URL.❤3
Forwarded from Сохранёнки программиста
Cloudflare автоматизировала обмен ключами с серверами сайтов
Cloudflare включила Automatic Key Exchange по умолчанию для доменов. Функция касается защищённого соединения между прокси Cloudflare и сайтом. Раньше Cloudflare начинала обмен по TLS 1.3 с X25519; при другом выборе сервера повтор добавлял полный сетевой круг.
Теперь сервис ежедневно проверяет серверы отдельно от рабочего трафика и первой предлагает сильнейший поддерживаемый алгоритм, прежде всего постквантовый X25519MLKEM768. Изменение развёртывают на части трафика и отменяют, если число повторов растёт.
При развёртывании доля повторов снизилась примерно с 52% до 3,7%, а задержка на 90-м процентиле сократилась более чем на 150 мс. Сотни тысяч доменов получили постквантовые соединения без ручной настройки. Разбор Cloudflare пригодится тем, кто отвечает за TLS: в панели можно проверить режим и ограничения по стандартам.
Cloudflare включила Automatic Key Exchange по умолчанию для доменов. Функция касается защищённого соединения между прокси Cloudflare и сайтом. Раньше Cloudflare начинала обмен по TLS 1.3 с X25519; при другом выборе сервера повтор добавлял полный сетевой круг.
Теперь сервис ежедневно проверяет серверы отдельно от рабочего трафика и первой предлагает сильнейший поддерживаемый алгоритм, прежде всего постквантовый X25519MLKEM768. Изменение развёртывают на части трафика и отменяют, если число повторов растёт.
При развёртывании доля повторов снизилась примерно с 52% до 3,7%, а задержка на 90-м процентиле сократилась более чем на 150 мс. Сотни тысяч доменов получили постквантовые соединения без ручной настройки. Разбор Cloudflare пригодится тем, кто отвечает за TLS: в панели можно проверить режим и ограничения по стандартам.
❤1
Почему большой z-index не поднимает подсказку над шапкой
У подсказки может быть
Контекст появляется не только из-за сочетания
В разборе Josh W. Comeau есть интерактивные примеры и схемы контекстов. При отладке пройдите по предкам проблемного элемента: найдите предка, который создал новый контекст, и проверьте его порядок среди соседних контекстов.
У подсказки может быть
z-index: 999999, а у шапки всего 2, но шапка всё равно окажется сверху. Значения сравниваются не по всей странице, а только внутри одного контекста наложения. Если main создал отдельный контекст с z-index: 1, его дочерняя подсказка не сможет обойти соседний header с z-index: 2.Контекст появляется не только из-за сочетания
position и z-index. Его могут создать opacity меньше единицы, transform, will-change, фиксированное или липкое позиционирование и другие свойства. Поэтому увеличение числа порой напоминает торг с браузером: ставка растёт, результата нет.В разборе Josh W. Comeau есть интерактивные примеры и схемы контекстов. При отладке пройдите по предкам проблемного элемента: найдите предка, который создал новый контекст, и проверьте его порядок среди соседних контекстов.
🔥7
Короткая хронология:
2001 — появился SpaceWeb, в аське живёт весь рунет
2005 — Живой Журнал, гостевые книги, счётчики посещений
2010 — торренты, флеш-игры, первые айфоны у всех
2016 — все бегают за покемонами
2020 — жизнь переезжает в Zoom
2026 — SpaceWeb исполняется 25
Анкета проводит по всей этой линии — от первой страницы до промокода в конце.
2001 — появился SpaceWeb, в аське живёт весь рунет
2005 — Живой Журнал, гостевые книги, счётчики посещений
2010 — торренты, флеш-игры, первые айфоны у всех
2016 — все бегают за покемонами
2020 — жизнь переезжает в Zoom
2026 — SpaceWeb исполняется 25
Анкета проводит по всей этой линии — от первой страницы до промокода в конце.
😁2❤1🔥1
Как браузер мгновенно восстанавливает страницу при возврате
Кэш переходов назад и вперёд, или bfcache, сохраняет в памяти снимок всей страницы вместе с состоянием JavaScript. Когда пользователь уходит, браузер приостанавливает выполнение кода, а при возврате показывает страницу без запроса к сети. Механизм поддерживают все основные браузеры.
Начните проверку с обработчика
Разбор web.dev пригодится перед аудитом навигации: в нём есть механика кэша, события страницы и ограничения встроенных фреймов.
Кэш переходов назад и вперёд, или bfcache, сохраняет в памяти снимок всей страницы вместе с состоянием JavaScript. Когда пользователь уходит, браузер приостанавливает выполнение кода, а при возврате показывает страницу без запроса к сети. Механизм поддерживают все основные браузеры.
Начните проверку с обработчика
unload: на компьютерах Chrome и Firefox он исключает страницу из bfcache. Используйте pagehide, а восстановление отслеживайте через pageshow: свойство event.persisted будет равно true. В одностраничном приложении кэш не ускоряет внутренние переходы без перезагрузки, но помогает при возврате к приложению с другой страницы.Разбор web.dev пригодится перед аудитом навигации: в нём есть механика кэша, события страницы и ограничения встроенных фреймов.
❤2👍1
Как собрать современный CSS reset для нового проекта
В наборе Josh W. Comeau сохранены разумные браузерные стили и добавлена база для предсказуемой вёрстки.
Для текста задан межстрочный интервал 1,5 и более аккуратное распределение строк в абзацах и заголовках. Формы наследуют шрифт. Так меньше базовых исключений приходится исправлять в стилях компонентов.
Используйте набор при старте нового проекта. Для существующей кодовой базы автор предупреждает о риске незаметно сломать интерфейс изменением базовых стилей. Если всё же добавляете reset, тщательно протестируйте результат. Код и объяснение каждого правила есть в разборе Josh W. Comeau.
В наборе Josh W. Comeau сохранены разумные браузерные стили и добавлена база для предсказуемой вёрстки.
box-sizing: border-box включает границы и внутренние отступы в заданную ширину элемента, а внешние отступы сбрасываются у всех элементов, кроме dialog.Для текста задан межстрочный интервал 1,5 и более аккуратное распределение строк в абзацах и заголовках. Формы наследуют шрифт. Так меньше базовых исключений приходится исправлять в стилях компонентов.
Используйте набор при старте нового проекта. Для существующей кодовой базы автор предупреждает о риске незаметно сломать интерфейс изменением базовых стилей. Если всё же добавляете reset, тщательно протестируйте результат. Код и объяснение каждого правила есть в разборе Josh W. Comeau.
❤1
Когда в CSS нужны контейнерные запросы
Медиазапрос смотрит на окно браузера. Поэтому условие
Контейнерный запрос проверяет ширину родительской обёртки. Порог 450 пикселей переводит карточку в горизонтальную раскладку. Такой компонент можно переносить в сайдбар, не переписывая условие под ширину окна.
В разборе Smashing Magazine тот же принцип применяют к шрифту:
Медиазапрос смотрит на окно браузера. Поэтому условие
min-width: 1024px сработает на экране шириной 1920 пикселей даже для карточки шириной 300 пикселей. Тесному компоненту достанется раскладка для широкого экрана.Контейнерный запрос проверяет ширину родительской обёртки. Порог 450 пикселей переводит карточку в горизонтальную раскладку. Такой компонент можно переносить в сайдбар, не переписывая условие под ширину окна.
В разборе Smashing Magazine тот же принцип применяют к шрифту:
cqi вместе с clamp() масштабирует его относительно контейнера. Оставляйте медиазапросы для структуры страницы, а контейнерные используйте для карточек, форм и виджетов.❤5
Как проверить ограничитель запросов в многопроцессном Node.js
Локальный ограничитель показывает идеальные интервалы, пока сервер получает пачку запросов. В эксперименте с Bottleneck шесть воркеров при настройке на два запроса в секунду сообщали о паузах 495,8 мс, но вместе выдавали серверу 14,04 запроса в секунду.
Библиотека работала по документации:
Если приложение запущено через Node.js cluster, PM2 в cluster-режиме или несколько контейнеров, проверяйте не отчёт ограничителя, а интервалы прихода на HTTP-сервер. Намеренно отключите координацию и убедитесь, что тест замечает всплеск. Иначе заданный предел окажется пределом для каждого процесса.
Локальный ограничитель показывает идеальные интервалы, пока сервер получает пачку запросов. В эксперименте с Bottleneck шесть воркеров при настройке на два запроса в секунду сообщали о паузах 495,8 мс, но вместе выдавали серверу 14,04 запроса в секунду.
Библиотека работала по документации:
local не синхронизирует процессы. Контрольный запуск через Redis удержал суммарную частоту на двух запросах в секунду.Если приложение запущено через Node.js cluster, PM2 в cluster-режиме или несколько контейнеров, проверяйте не отчёт ограничителя, а интервалы прихода на HTTP-сервер. Намеренно отключите координацию и убедитесь, что тест замечает всплеск. Иначе заданный предел окажется пределом для каждого процесса.
❤2
Большая ИИ-подборка о разном. В ней прикладные задачи, фреймворки и модели, а также немного о том, как ИИ повлиял на информационную безопасность. (И мем)
ИИ в разных прикладных задачах:
Как ML вычисляет фейковые отзывы и накрутку рейтингов
15 бизнес-задач для автоматизации через ИИ
ИИ в работе мобильного банкира
Как финансовые организации сокращают расходы и убирают ручной ввод документов
Распознавание документов в браузере
Как распознать паспорт на Python за 5 минут
Про модели, фреймворки и работу с ИИ:
Модели для кода в 2026: Claude, GPT, Gemini, DeepSeek, Qwen
Вайб-кодинг в терминале: настраиваем OpenCode с Claude, GPT и Gemini
Как выбрать фреймворк для ИИ-агентов
Почему ИИ-агент тупеет на большом проекте
Что меня ждало, когда я решил стать вайб‑кодером
Можно ли аналитику в 2026 году положиться на ИИ и агентов или ещё нет?
Инфобез и ИИ:
Вайб-кодинг как мечта хакера: какие уязвимости плодит код, сгенерированный ИИ
Ваш ИИ-агент видит лишнее: пять атак, которые превращают помощника в канал утечки
ИИ в ИБ: где он реально работает, а где — просто модный ярлык
ИИ в разных прикладных задачах:
Как ML вычисляет фейковые отзывы и накрутку рейтингов
15 бизнес-задач для автоматизации через ИИ
ИИ в работе мобильного банкира
Как финансовые организации сокращают расходы и убирают ручной ввод документов
Распознавание документов в браузере
Как распознать паспорт на Python за 5 минут
Про модели, фреймворки и работу с ИИ:
Модели для кода в 2026: Claude, GPT, Gemini, DeepSeek, Qwen
Вайб-кодинг в терминале: настраиваем OpenCode с Claude, GPT и Gemini
Как выбрать фреймворк для ИИ-агентов
Почему ИИ-агент тупеет на большом проекте
Что меня ждало, когда я решил стать вайб‑кодером
Можно ли аналитику в 2026 году положиться на ИИ и агентов или ещё нет?
Инфобез и ИИ:
Вайб-кодинг как мечта хакера: какие уязвимости плодит код, сгенерированный ИИ
Ваш ИИ-агент видит лишнее: пять атак, которые превращают помощника в канал утечки
ИИ в ИБ: где он реально работает, а где — просто модный ярлык
❤1
Почему font-family не берёт запасной шрифт у родителя
Если на body задан стек
Если у шрифтов различаются ширина и высота символов, замена запасного шрифта веб-шрифтом может сдвинуть элементы и ухудшить CLS, показатель неожиданных смещений макета.
Исправление: задавайте полный стек при каждом переопределении, например
Если на body задан стек
system-ui, sans-serif, а на h1 только «Open Sans», браузер не вернётся к стеку body. Объявление заголовка самодостаточно: пока веб-шрифт грузится, браузер исчерпает его список и возьмёт свой шрифт по умолчанию, часто Times New Roman.Если у шрифтов различаются ширина и высота символов, замена запасного шрифта веб-шрифтом может сдвинуть элементы и ухудшить CLS, показатель неожиданных смещений макета.
Исправление: задавайте полный стек при каждом переопределении, например
font-family: "Open Sans", sans-serif;. Harry Roberts объясняет механику на CSS Wizardry. Проверьте переменные дизайн-системы: после имени веб-шрифта нужен хотя бы общий запасной вариант вроде sans-serif.❤5
Облачная подборка. В ней поговорим о том, любят ли сейчас компании облака так же как раньше, что делать с S3-хранилищами и где можно добыть GPU-мощностей!
Почему компании возвращают нагрузки из публичного облака в 2026 году
Гибридное облако: что оставить у себя, а что вынести в публичный контур
Облако или свои серверы: почему бизнес выбирает гибридную инфраструктуру
Кто отвечает за работу облачной инфраструктуры: бизнес или провайдер
VPS или облачный IaaS в 2026: когда дешёвый сервер перестаёт справляться
Где арендовать GPU в 2026
GPU-серверы для LLM-инференса
S3 в инфраструктуре: где объектное хранилище помогает, а где не заменит файловую систему
Как хранить бэкапы в S3, чтобы их не удалил сбой или вирус
Почему компании возвращают нагрузки из публичного облака в 2026 году
Гибридное облако: что оставить у себя, а что вынести в публичный контур
Облако или свои серверы: почему бизнес выбирает гибридную инфраструктуру
Кто отвечает за работу облачной инфраструктуры: бизнес или провайдер
VPS или облачный IaaS в 2026: когда дешёвый сервер перестаёт справляться
Где арендовать GPU в 2026
GPU-серверы для LLM-инференса
S3 в инфраструктуре: где объектное хранилище помогает, а где не заменит файловую систему
Как хранить бэкапы в S3, чтобы их не удалил сбой или вирус
❤1
Курсорная пагинация для API: когда она надёжнее OFFSET
OFFSET удобен, пока выборка невелика и не меняется между запросами. На таблице из 1,2 млн строк в PostgreSQL 15 выдача 20 строк с OFFSET 1 000 000 заняла 2,4 секунды, а запрос по курсору выполнялся за 3 мс.
База читает пропущенные строки и отбрасывает их. OFFSET каждый раз отсчитывает позиции от текущего начала выборки, поэтому вставки и удаления между запросами дают дубликаты или пропуски. Курсор хранит ID последней полученной записи и продолжает после неё.
В примере на FastAPI запрос выбирает на одну строку больше лимита: она показывает, есть ли продолжение. При сортировке по времени создания нужен курсор и индекс из двух полей, created_at и ID, иначе записи с одинаковым временем могут пропасть.
Оставляйте OFFSET для небольших стабильных данных и перехода к странице N. Для растущей ленты или синхронизации выбирайте курсор.
OFFSET удобен, пока выборка невелика и не меняется между запросами. На таблице из 1,2 млн строк в PostgreSQL 15 выдача 20 строк с OFFSET 1 000 000 заняла 2,4 секунды, а запрос по курсору выполнялся за 3 мс.
База читает пропущенные строки и отбрасывает их. OFFSET каждый раз отсчитывает позиции от текущего начала выборки, поэтому вставки и удаления между запросами дают дубликаты или пропуски. Курсор хранит ID последней полученной записи и продолжает после неё.
В примере на FastAPI запрос выбирает на одну строку больше лимита: она показывает, есть ли продолжение. При сортировке по времени создания нужен курсор и индекс из двух полей, created_at и ID, иначе записи с одинаковым временем могут пропасть.
Оставляйте OFFSET для небольших стабильных данных и перехода к странице N. Для растущей ленты или синхронизации выбирайте курсор.
❤4
Почему box-shadow не заменяет outline для фокуса
CSS-тень даёт больше свободы в оформлении фокуса. Но в режиме принудительных цветов браузер вычисляет
Простой вариант: обычный
Проверить компонент можно в Chromium DevTools: вкладка Rendering, параметр
CSS-тень даёт больше свободы в оформлении фокуса. Но в режиме принудительных цветов браузер вычисляет
box-shadow как none. Пользователь не видит, какая кнопка в фокусе.Простой вариант: обычный
outline. Если нужна тень, не отключайте контур через outline: none: задайте outline: 2px solid transparent и outline-offset: 2px. В обычном режиме контур прозрачен, а при принудительных цветах становится видимым в палитре пользователя.Проверить компонент можно в Chromium DevTools: вкладка Rendering, параметр
forced-colors со значением active. Добавьте сценарий в чеклист доступности, а разбор Manuel Matuzović используйте как памятку с двумя вариантами CSS.👍4❤1
Как заблокировать отрисовку JavaScript, не останавливая HTML-парсер
Когда компоненту нужно измерить размеры и переставить элементы до первого отображения, блокировка парсера не гарантирует результат: браузер может показать полученный HTML, а скрипт перед компонентом ещё не увидит его узлы.
Атрибут
В разборе Джея Фристоуна скрипт измеряет место в навигации и перед показом переносит лишние пункты в дополнительное меню. Так нет вспышки исходной вёрстки и видимого сдвига. Используйте приём точечно, когда компонент зависит от размеров элементов.
Когда компоненту нужно измерить размеры и переставить элементы до первого отображения, блокировка парсера не гарантирует результат: браузер может показать полученный HTML, а скрипт перед компонентом ещё не увидит его узлы.
Атрибут
blocking="render" у script задерживает отрисовку, но не мешает парсеру читать HTML дальше. Работает с модулями и внешними файлами, но сетевой запрос увеличит задержку. Поэтому скрипт лучше сделать маленьким и встроить в HTML.В разборе Джея Фристоуна скрипт измеряет место в навигации и перед показом переносит лишние пункты в дополнительное меню. Так нет вспышки исходной вёрстки и видимого сдвига. Используйте приём точечно, когда компонент зависит от размеров элементов.
❤1👍1
Как защитить API от повторной оплаты
Клиент не получил ответ и повторил
В разборе на DEV Community показаны три подхода. Клиент создаёт ключ один раз и передаёт его при каждом повторе. Сервер атомарно сохраняет ключ, HTTP-статус и идентификатор платежа, а при дубле возвращает их без нового списания. Если запись определяет адрес почты, из него получают стабильный идентификатор и обновляют одну строку. Проверка версии защищает от одновременных изменений, но сама не делает запрос идемпотентным.
Начните с методов API с побочным эффектом: разделяйте ключи по пользователю и операции, отклоняйте тот же ключ с другими данными и отправьте 50 одновременных запросов, чтобы убедиться, что списание происходит один раз.
Клиент не получил ответ и повторил
POST. Сервер мог уже списать деньги, поэтому повтор может привести ко второй оплате. Идемпотентность решает это: несколько одинаковых запросов дают тот же результат, что один.В разборе на DEV Community показаны три подхода. Клиент создаёт ключ один раз и передаёт его при каждом повторе. Сервер атомарно сохраняет ключ, HTTP-статус и идентификатор платежа, а при дубле возвращает их без нового списания. Если запись определяет адрес почты, из него получают стабильный идентификатор и обновляют одну строку. Проверка версии защищает от одновременных изменений, но сама не делает запрос идемпотентным.
Начните с методов API с побочным эффектом: разделяйте ключи по пользователю и операции, отклоняйте тот же ключ с другими данными и отправьте 50 одновременных запросов, чтобы убедиться, что списание происходит один раз.
🔥1
Как анимировать перестройку CSS Grid без JavaScript
В разборе приёма содержимое каждой плитки привязывают к её ячейке через CSS Anchor Positioning. Перемещение при изменении ширины контейнера анимирует обычный переход свойства
Ячейка Grid виртуальна, поэтому якорем служит дополнительная обёртка. Она получает
Анимацию можно прервать: плитки сразу направятся к новым позициям, не дожидаясь предыдущего перехода. JavaScript не нужен. В Firefox приём сейчас не анимируется, поэтому для интерфейса во всех браузерах понадобится запасной вариант.
В разборе приёма содержимое каждой плитки привязывают к её ячейке через CSS Anchor Positioning. Перемещение при изменении ширины контейнера анимирует обычный переход свойства
inset.Ячейка Grid виртуальна, поэтому якорем служит дополнительная обёртка. Она получает
anchor-name, а anchor-scope позволяет повторять это имя в других ячейках без конфликтов. Блоку с контентом задают абсолютное позиционирование и фиксированные размеры, чтобы он не растягивался при движении.Анимацию можно прервать: плитки сразу направятся к новым позициям, не дожидаясь предыдущего перехода. JavaScript не нужен. В Firefox приём сейчас не анимируется, поэтому для интерфейса во всех браузерах понадобится запасной вариант.
🔥3
Как защитить списание кредитов в Django от гонки запросов
У аккаунта один кредит. Два запроса читают баланс до первого сохранения, оба проходят проверку и записывают ноль. Сервис принимает две генерации, хотя баланс не уходит в минус. Поэтому проверка на отрицательный баланс баг не ловит.
В руководстве ошибку воспроизводят, затем закрывают транзакцией базы данных и блокировкой строки аккаунта. Проверку баланса, списание и запись принятого запроса объединяют в одну защищённую операцию. Пример работает на Django 5.2, Django REST Framework 3.16 и PostgreSQL 17. SQLite не подходит: он не реализует нужную блокировку строк.
В разборе freeCodeCamp есть настройка проекта и тест двух запросов, которые претендуют на последний кредит. Открывайте его перед ревью логики лимитов: найдите разрыв между чтением и записью, затем перенесите решение внутрь транзакции.
У аккаунта один кредит. Два запроса читают баланс до первого сохранения, оба проходят проверку и записывают ноль. Сервис принимает две генерации, хотя баланс не уходит в минус. Поэтому проверка на отрицательный баланс баг не ловит.
В руководстве ошибку воспроизводят, затем закрывают транзакцией базы данных и блокировкой строки аккаунта. Проверку баланса, списание и запись принятого запроса объединяют в одну защищённую операцию. Пример работает на Django 5.2, Django REST Framework 3.16 и PostgreSQL 17. SQLite не подходит: он не реализует нужную блокировку строк.
В разборе freeCodeCamp есть настройка проекта и тест двух запросов, которые претендуют на последний кредит. Открывайте его перед ревью логики лимитов: найдите разрыв между чтением и записью, затем перенесите решение внутрь транзакции.
❤2
Как проверять CSS после рефакторинга с ИИ
Пять ИИ-инструментов получили HTML и CSS карточки и одинаковый запрос на рефакторинг. Все убрали очевидные повторы, но хуже справились с каскадом: чистка могла менять оформление и поведение компонента.
Одна из ловушек:
После рефакторинга проверяйте наведение, динамические классы, обрезку текста и границы селекторов. В тесте LogRocket Blog собраны семь ловушек, таблица результатов для пяти инструментов и файлы всех вариантов.
Пять ИИ-инструментов получили HTML и CSS карточки и одинаковый запрос на рефакторинг. Все убрали очевидные повторы, но хуже справились с каскадом: чистка могла менять оформление и поведение компонента.
Одна из ловушек:
.promo-active .card .badge имеет ту же специфичность, что и .card .badge.badge-new. Здесь !important гарантирует оранжевый цвет промобейджа независимо от порядка правил. Без него результат зависит от порядка. В обычном состоянии карточки ошибка не видна.После рефакторинга проверяйте наведение, динамические классы, обрезку текста и границы селекторов. В тесте LogRocket Blog собраны семь ловушек, таблица результатов для пяти инструментов и файлы всех вариантов.
❤3