Свежие статьи
structuredClone() — правильное копирование объектов в JavaScript
Копирование объектов в JavaScript — одна из тех тем, которые поначалу кажутся простыми, а потом преподносят неожиданные сюрпризы.
Присвоить объект через = — не копирование. Это просто ещё одна ссылка на тот же объект. Измените копию — изменится оригинал:
const original = { name: 'Иван', scores: [10, 20, 30] };
const copy = original;
copy.name = 'Пётр';
console.log(original.name); // 'Пётр' — изменился оригинал!
Для поверхностного копирования используют Object.assign() или spread-оператор {...obj}. Но они копируют только первый уровень. Вложенные объекты и массивы по-прежнему остаются общими.
В 2022 году JavaScript получил structuredClone() — стандартный способ сделать полную глубокую копию.
- 18 мая 2026
Умный перенос текста в CSS с text-wrap: balance и pretty
Перенос слов в заголовках и текстовых блоках — деталь, на которую пользователи не обращают внимания, когда она хороша, и сразу замечают, когда что-то не так. Одиноко висящее слово в последней строке заголовка, или строки разной длины там, где хотелось симметрии — такое встречается часто. CSS text-wrap предлагает два умных режима для решения этой проблемы.
- 17 мая 2026
http-server — быстрый локальный сервер для статики
Открыть HTML-файл двойным кликом — плохая идея. Браузер откроет его по протоколу file://, и сразу начнутся проблемы: не загружаются шрифты, блокируются запросы к API из-за CORS, не работают относительные пути к модулям. Чтобы страница вела себя как в интернете, ей нужен настоящий HTTP-сервер.
http-server — минималистичный статический сервер, который запускается одной командой и не требует настройки.
- 15 мая 2026
Вам срочно нужно освоить Prettier, и вот почему
В команде из нескольких человек, где пока не устаканились стандарты написания кода, этот самый код быстро превращается непонятно во что: один ставит одинарные кавычки, другой — двойные, третий делает отступы табами, четвёртый — пробелами. На ревью половина комментариев относятся не к логике, а к стилю, и это большая трата времени и для команды, и для компании.
Prettier решает проблему радикально: он берёт ваш код и переформатирует его по единым правилам. После этого весь код в проекте выглядит одинаково, вне зависимости от того, кто его написал.
- 13 мая 2026
git bisect, или как быстро найти сломавший всё коммит
Бывает такая ситуация: функциональность работала неделю назад, а сейчас — нет. За это время в репозитории накопилось сорок коммитов от разных людей. Просматривать каждый по очереди — долго и мучительно.
git bisect решает эту задачу умно: он делает бинарный поиск по истории коммитов. Вы говорите «вот этот коммит рабочий, а вот этот — нет», а Git сам переключает репозиторий на середину диапазона и спрашивает: «Здесь работает?» После нескольких ответов плохой коммит найден.
Работает бинарный поиск: сорок коммитов — шесть вопросов, восемьсот коммитов — десять вопросов.
- 13 мая 2026
Почему ESLint — это хорошо
Опечатка в имени переменной, использование == вместо ===, вызов функции до её объявления — всё это браузер обнаружит только в момент выполнения кода. В лучшем случае вы увидите ошибку сразу, в худшем — она всплывёт у пользователя в продакшене.
ESLint проверяет код до запуска. Он читает файл, анализирует структуру и сообщает о проблемах прямо в редакторе или в терминале. Это называется статическим анализом, или линтингом.
- 12 мая 2026
Как CSS subgrid спасает карточки на сайтах
Grid Layout решил много задач с раскладкой, но одна проблема долго оставалась без решения. Представьте три карточки в сетке. У каждой — заголовок, описание и кнопка. Высота заголовков разная: в одной карточке текст длиннее, в другой короче. В итоге кнопки стоят на разной высоте, и сетка выглядит неаккуратно.
Раньше это решали через JavaScript: вычисляли высоту заголовков и выставляли min-height. Или просто мирились с несовершенством.
Subgrid позволяет дочернему элементу участвовать в сетке родителя. Карточка занимает несколько строк родительской сетки — и все её внутренние блоки выравниваются по общим линиям.
- 2 мая 2026
Контейнерные запросы в CSS на одном простом примере
Долгое время адаптивная вёрстка строилась на медиавыражениях: браузер смотрит на ширину окна и применяет нужные стили. Это работало, но создавало одну постоянную проблему.
Представьте карточку товара. На широком экране она выглядит горизонтально: слева фото, справа текст. На узком — вертикально: фото сверху, текст снизу. Казалось бы, медиавыражение справится. Но что если эту же карточку нужно показать в узкой боковой колонке на широком экране? Медиавыражение видит только ширину окна — она большая, а значит, карточка будет горизонтальной, хотя места у неё нет.
Container queries решают именно эту задачу: элемент адаптируется под размер своего контейнера, а не под размер окна.
- 1 мая 2026
Наводим порядок в каскаде с использованием CSS @layer
Если вы когда-нибудь подключали стороннюю библиотеку стилей и потом пытались её переопределить — вы знаете эту боль. Пишете правило, оно не работает. Добавляете класс поконкретнее — всё равно не работает. В итоге пишете !important и расстраиваетесь, потому что теперь нужно всё время учитывать это в дальнейшей работе.
Это называют войной специфичности. Возникает она потому, что CSS решает конфликты через длину и конкретность селекторов, а не через то, кто написал правило позже и кто важнее по смыслу.
В 2022 году в браузерах появился @layer — способ самим расставить приоритеты между группами стилей.
- 30 апреля 2026
HTML-тег dialog — модальные окна без JavaScript-костылей
Запрограммировать модальное окно — одна из самых частых задач во фронтенде. Раньше для этого брали готовую библиотеку, писали десятки строк JavaScript, вручную блокировали прокрутку страницы, управляли фокусом и добавляли затемнение через отдельный div. Всё это работало, но требовало много кода и было легко сломать.
В HTML уже давно есть специальный элемент для этого — тег <dialog>. Долго его поддержка была неполной, но с 2022 года он работает во всех современных браузерах, и теперь им можно пользоваться без оговорок.
- 29 апреля 2026
Array.at() — удобный доступ к элементам массива с конца
Есть задача, которую каждый JavaScript-разработчик решает регулярно: получить последний элемент массива. Казалось бы, мелочь. Но стандартного красивого способа долго не было.
Можно писать arr[arr.length - 1] — работает, но громоздко. Можно использовать arr.slice(-1)[0] — ещё хуже. Оба варианта требуют знать длину массива или создавать промежуточный массив ради одного элемента.
В 2022 году в JavaScript появился метод .at(), который решает это элегантно.
- 27 апреля 2026
CSS :is() и :where(), делаем короткие селекторы вместо длинных списков
Бывает такая ситуация: нужно задать один стиль для нескольких разных элементов в разных контекстах. Например, сделать красными все ссылки внутри статьи, боковой панели и подвала. Без специальных псевдоклассов получается громоздко:
article a,
aside a,
footer a {
color: red;
}
Три строки ради одного правила. Если таких правил много — CSS превращается в простыню. :is() и :where() решают это элегантно.
- 25 апреля 2026
Когда разработчику НЕ нужно использовать ИИ? Большой разбор
Нейросеть умеет писать код быстрее вас. Это факт. Но скорость — не единственное, что важно в работе разработчика. Есть задачи, где нужно замедлиться, столкнуться с трудностью лицом к лицу и разобраться самому. Именно в таких задачах рождается настоящее понимание разработки, а не вот это всё.
- 19 апреля 2026
Практика в ИИ для фронтендеров: как генерировать хороший код с первого раза
Вы открываете проект утром, копируете в нейронку задачу, получаете красивый компонент — и начинаете его переделывать. Меняете названия переменных, добавляете проверку данных с сервера, убираете стили, которые конфликтуют с общей темой. Знакомо?
Дело не в том, что нейросеть плохо пишет код. Дело в том, что она пишет код для другой задачи — для той, которую вы описали, а не для той, которая есть на самом деле.
Эта статья о том, как правильно описывать задачу, чтобы получить рабочий код с первого раза. Разберём три главных направления: компоненты, стили и тесты. А ещё поговорим о том, как давать нейросети контекст — описание данных с сервера и правила дизайн-системы.
- 18 апреля 2026
Цифровой профессиональный след: как сделать, чтобы моё резюме заметили
Представьте ситуацию: компания N ищет разработчика. Пришло двести откликов. И у каждого кандидата — пять лет опыта. Но вы уже знаете, что у части из них этот опыт нарисован. Как понять, у каких именно?
Именно из этого тупика и выросло понятие цифрового профессионального следа (ЦПС). Суть простая: любое внешнее свидетельство вашей работы, которое существует независимо от вас и которое вы не можете подправить задним числом.
- 22 марта 2026
Вышел Vite 8
Вышел Vite 8 — самое крупное изменение архитектуры с версии 2. Главное: под капотом теперь работает единственный бандлер Rolldown, написанный на Rust. Раньше их было два — esbuild для разработки и Rollup для финальной сборки. Теперь один инструмент делает всё.
- 20 марта 2026
Popover API или Dialog API: что выбрать?
После продолжительного изучения темы выяснилось, что Popover API и Dialog API кардинально отличаются с точки зрения доступности. Если вы стоите перед выбором, придерживайтесь такого правила:
- Используйте Popover API для большинства поповеров.
- Используйте Dialog API только для модальных диалогов.
- 14 марта 2026
Прощай, innerHTML — привет, setHTML: усиленная защита от XSS в Firefox 148
Firefox 148 стал первым браузером, реализовавшим стандартизированный Sanitizer API — новый инструмент, который встраивает санитизацию HTML непосредственно в процесс вставки содержимого в DOM и делает защиту от XSS доступной по умолчанию.
Межсайтовый скриптинг (XSS) по-прежнему остаётся одной из наиболее распространённых уязвимостей в интернете. Новый стандартизированный Sanitizer API даёт веб-разработчикам простой способ очищать ненадёжный HTML перед его вставкой в DOM. Firefox 148 стал первым браузером, поставившим этот API в стабильную версию, — ожидается, что остальные браузеры последуют примеру в ближайшее время.
XSS-уязвимость возникает, когда сайт непреднамеренно позволяет злоумышленникам внедрять произвольный HTML или JavaScript через пользовательский контент. С её помощью атакующий может отслеживать и подменять действия пользователей и систематически похищать их данные — до тех пор, пока уязвимость не будет устранена. XSS исторически крайне сложен в предотвращении и на протяжении почти десяти лет стабильно входит в тройку самых опасных веб-уязвимостей (CWE-79).
Mozilla участвовала в борьбе с XSS с самого начала: ещё в 2009 году Firefox инициировал разработку стандарта Content-Security-Policy (CSP). CSP позволяет сайтам ограничивать, какие ресурсы (скрипты, стили, изображения и т. д.) браузер вправе загружать и исполнять, формируя надёжный рубеж обороны. Тем не менее, несмотря на постоянные улучшения, CSP так и не получил широкого распространения: его внедрение требует существенных архитектурных изменений и регулярного внимания специалистов по безопасности.
Sanitizer API призван заполнить этот пробел, предоставляя стандартизированный механизм преобразования вредоносного HTML в безопасный. Метод setHTML() встраивает санитизацию непосредственно в процесс вставки HTML, обеспечивая защиту на уровне умолчаний. Пример очистки небезопасного HTML:
document.body.setHTML(`<h1>Hello my name is <img src="x"
onclick="alert('XSS')">`);
При такой санитизации элемент <h1> будет сохранён, а элемент <img> вместе с атрибутом onclick — удалён, что устраняет XSS-атаку. В результате останется следующий безопасный HTML:
<h1>Hello my name is</h1>Разработчики могут усилить защиту от XSS с минимальными изменениями в коде, заменив подверженные ошибкам присваивания innerHTML на вызовы setHTML(). Если настройки по умолчанию окажутся слишком строгими или, напротив, недостаточно строгими для конкретного случая, можно передать пользовательскую конфигурацию, определяющую, какие элементы и атрибуты следует сохранить или удалить. Для экспериментов до внедрения API на продакшн-сайте рекомендуется воспользоваться песочницей Sanitizer API.
Для ещё более надёжной защиты Sanitizer API можно сочетать с
Trusted Types,
которые централизуют контроль над разбором и вставкой HTML. После перехода на setHTML() включить принудительное применение Trusted Types становится проще — зачастую без необходимости создавать сложные пользовательские политики. Строгая политика может разрешать setHTML(), блокируя остальные небезопасные способы вставки HTML, что помогает предотвращать регрессии в безопасности.
Sanitizer API упрощает замену присваиваний innerHTML на вызовы setHTML() в существующем коде, устанавливая новый безопасный стандарт и защищая пользователей от XSS-атак. Firefox 148 поддерживает как Sanitizer API, так и Trusted Types. Принятие этих стандартов позволит любому разработчику предотвращать XSS без выделенной команды безопасности и масштабных архитектурных изменений.
- 13 марта 2026
Что нового появилось в браузерах в феврале 2026
Февраль принёс несколько полезных обновлений: атрибут для передачи направления текста в формах получил поддержку во всех браузерах, появились удобные методы для работы с Map, а CSS обзавёлся новой функцией для сложных фигур. Разбираем, что уже можно использовать и что стоит взять на заметку.
- 12 марта 2026
Разбитое сердце
Или: как одна нелепая строка кода дала ускорение в 100 раз.
Всегда знаешь, что попался хороший баг, когда первая реакция — «как такое вообще возможно?»
Я дорабатывал панель управления одного веб-приложения и заметил, что она стала загружаться вечность. Раньше страница открывалась за секунду — теперь за десять. Что-то явно шло не так.
Естественно, я обвинил React.
Ну, конечно, в современном веб-приложении источников проблем с производительностью хватает: сторонний JavaScript, перегруженные серверы, раздутые ресурсы, отсутствующие индексы в базе данных — длиннющий список. Но десятилетия разработки для веба подсказывали: это проблема фронтенда. Я просто чувствовал это. Страница выглядела дёргающейся при загрузке. А экосистема React, при всей своей относительной приемлемости сегодня, полна способов превратить кодовую базу в запутанный тормозящий клубок.
Чтобы подтвердить теорию, я объяснил Claude, что панель загружается медленно, что наверняка виноват React, и попросил проанализировать проблемы и отсортировать их по серьёзности. И действительно, Claude нашёл кучу подозрительного в React: лишние перерисовки, пропущенные мемоизации. Выяснилось, что мы ещё не перешли на React Compiler. Я попросил Claude сделать первый проход по самым простым и серьёзным проблемам, и…
Это почти ничего не дало. Может, дело не в React?
Засучил рукава и начал разбираться по-настоящему.
- Может, сервер медленный? Немного — но фронтенд он не блокирует.
- Проблема во всех браузерах? Нет. Почему-то только в Safari.
- Значит, виноват сторонний JavaScript? Intercom? Нет. PostHog? Нет.
- Ладно, роем глубже — смотрим временную шкалу производительности.
Инспектор производительности Safari за последние годы заметно разошёлся с инструментами на основе Chromium и на этой странице работал капризно. Но картину он нарисовал вполне отчётливую: 7+ секунд тратились не на разбор JavaScript, не на вычисление стилей и не на загрузку сети. 94% процессора на M1 Max уходило на… компоновку вёрстки?
В подробностях было видно несколько проходов компоновки длительностью более 1600 мс каждый. Для сравнения: это примерно в 100 раз медленнее нормы. Что-то было серьёзно не так с тем, как браузер выстраивал страницу. Flexbox может чуть замедляться, но не настолько же.
- 11 марта 2026
