⚡️ Прощай, FID. Привет, INP: Главная метрика Core Web VitalsFirst Input Delay (FID) официально ушел на пенсию в марте 2024 года. На его место пришел INP (Interaction to Next Paint). Если вы всё еще оптимизируете старую метрику, самое время пересмотреть свои подходы.В чем был обман FID?FID измерял только задержку (Input Delay) от клика до того момента, как браузер начал выполнять ваш обработчик событий.Если ваша функция onClick после старта зависала на 2 секунды, перебирая огромный массив, FID всё равно мог быть идеальным (например, 3 мс), хотя пользователь видел намертво зависший интерфейс.Что измеряет INP?INP фиксирует всё время до появления визуального отклика на экране:1. Ожидание освобождения Main Thread (Input delay)2. Выполнение вашего JS-кода (Processing time)3. Пересчет стилей, Layout и саму отрисовку (Presentation delay)Хороший INP - это меньше 200 мс. Причем берется не среднее значение, а один из худших результатов за сессию (98-й перцентиль).🛠 Как спасать INP (Senior level):1. Разбивайте Long Tasks (Yield to Main Thread)Не заставляйте браузер делать всю тяжелую работу за один присест. Дайте ему возможность «вздохнуть» и отрисовать кадр. В современных браузерах для этого внедряется scheduler.yield().async function handleHeavyClick() { // 1. Показываем лоадер (синхронно, легко) showSpinner(); // 2. Отдаем управление браузеру, чтобы он успел отрисовать лоадер! // Если scheduler.yield недоступен, используем await new Promise(r => setTimeout(r, 0)) if ('scheduler' in window && 'yield' in scheduler) { await scheduler.yield(); } else { await new Promise(resolve => setTimeout(resolve, 0)); } // 3. Теперь делаем тяжелую работу processHugeData();}2. Используйте startTransition в React 18+Если клик вызывает обновление состояния, которое требует тяжелого рендера (например, фильтрация большого списка), React может заблокировать отрисовку того же чекбокса, на который вы нажали.Оберните тяжелое обновление стейта в startTransition - React пометит его
Frontend разработчик
@frontend_1
Полезные материалы для фронтендера по HTML, CSS, JS, React.js, Angular.js, Vue.js, TypeScript, Redux, MobX, JavaScript, NodeJS. По всем вопросам @evgenycarterРКН clck.ru/3KoFrk
Последние посты
Нативный View Transitions APIАнимация перехода между страницами (или состояниями приложения) всегда была болью. Чтобы картинка из карточки товара плавно перелетела на страницу деталей, мы тянули тяжелые framer-motion, react-spring и писали горы логики, чтобы держать старый DOM-узел живым во время анимации.Теперь это делает сам браузер на уровне движка с помощью View Transitions API.В чем суть?Когда вы вызываете API, браузер буквально делает скриншот текущего состояния, замораживает его, дает вам обновить DOM, делает скриншот нового состояния и автоматически создает CSS-анимацию (по умолчанию crossfade) между этими двумя «кадрами».🚀 Как это выглядит в коде (SPA):Вместо синхронного изменения стейта оборачиваем апдейт в один метод:// Функция, которая меняет DOM (например, рендер нового роута)function updatePage() { renderNewRoute();}// ❌ Как было:// updatePage();// ✅ Как теперь:if (!document.startViewTransition) { updatePage(); // Фолбэк для старых браузеров} else { // Браузер сам создаст плавный переход document.startViewTransition(() => updatePage());}🧠 Senior-уровень: Анимация конкретных элементовДефолтный crossfade всей страницы это скучно. Самое крутое, это Hero-анимации (когда элемент перелетает на новое место с изменением размера).Чтобы браузер понял, что маленькая аватарка в списке и большая аватарка в профиле - это один и тот же элемент, им просто нужно дать одинаковое CSS-свойство view-transition-name:/* На странице списка */.user-avatar-small { view-transition-name: user-avatar;}/* На странице профиля (после апдейта DOM) */.user-avatar-large { view-transition-name: user-avatar;}Всё! При вызове startViewTransition браузер сам рассчитает траекторию, скейл и плавно переместит аватарку.🔥 А что с классическими многостраничниками (MPA)?Это самая бомба. Chrome уже поддерживает кросс-документные переходы (между реальными HTML-страницами вашего сайта). Не нужно никакого JS!Просто добавляем в CSS:@view-transition { navigation: auto;}И страницы начнут плавно
🧬 Иммутабельность из коробки: toSorted(), toSpliced() и with()Сколько раз вы ловили трудноуловимые баги в React или Redux из-за того, что методы sort(), reverse() или splice() незаметно мутируют оригинальный массив?Раньше, чтобы обновить состояние, нам приходилось плодить поверхностные копии через спред-оператор.// ❌ Старая школа (много шума)const sortedUsers = [...users].sort((a, b) => a.age - b.age);// А замена элемента по индексу вообще выглядела как пытка:const updatedUsers = [...users];updatedUsers[index] = newUser;В стандарте ES2023 (Baseline 2023) JavaScript наконец-то получил нативные иммутабельные методы массивов. Они делают то же самое, но возвращают новый массив, оставляя оригинал нетронутым.🚀 Как пишем теперь:1. Сортировка и разворот// ✅ Оригинал цел, получаем новый массивconst sorted = users.toSorted((a, b) => a.age - b.age);const reversed = users.toReversed();2. Удаление/вставка (вместо splice)const months = ["Jan", "Mar", "Apr", "May"];// Вставляем "Feb" на индекс 1 (ничего не удаляя)const fixedMonths = months.toSpliced(1, 0, "Feb");// ["Jan", "Feb", "Mar", "Apr", "May"]3. 🔥 Метод with() - киллер-фича для ReactЗаменяет элемент по индексу без мутаций. Идеально для обновления конкретного элемента в массиве состояния.const state = ['apple', 'banana', 'cherry'];// Меняем 'banana' на 'mango'const newState = state.with(1, 'mango'); // ['apple', 'mango', 'cherry']💡Методы работают не только с массивами, но и с TypedArrays (например, Uint8Array). А метод with() отлично справляется с отрицательными индексами - arr.with(-1, newItem) заменит последний элемент массива без вычисления его длины!📲 Мы в MAX👉 @frontend_1
🚀 Подборка полезных IT каналов в MaxСистемное администрирование, DevOps 📌https://max.ru/i_odmin Все для системного администратораhttps://max.ru/bash_srv Bash Советыhttps://max.ru/sysadminof Книги для админов, полезные материалыhttps://max.ru/i_odmin_book Библиотека Системного Администратораhttps://max.ru/i_devops DevOps: Пишем о Docker, Kubernetes и др.1C разработка 📌https://max.ru/odin1c_rus Cтатьи, курсы, советы, шаблоны кода 1СПрограммирование C++📌https://max.ru/cpp_lib Библиотека C/C++ разработчикаПрограммирование Python 📌https://max.ru/python_of Python академия. https://max.ru/BookPython Библиотека Python разработчикаJava разработка 📌https://max.ru/bookjava Библиотека Java разработчикаGitHub Сообщество 📌https://max.ru/githublib Интересное из GitHubБазы данных (Data Base) 📌https://max.ru/database_info Все про базы данныхФронтенд разработка 📌https://max.ru/frontend_1 Подборки для frontend разработчиковБиблиотеки 📌https://max.ru/programmist_of Книги по программированиюhttps://max.ru/proglb Библиотека программистаhttps://max.ru/bfbook Книги для программистовПрограммирование 📌https://max.ru/bookflow Лекции, видеоуроки, доклады с IT конференцийhttps://max.ru/itmozg Программисты, дизайнеры, новости из мира IThttps://max.ru/php_lib Библиотека PHP программиста 👨🏼💻👩💻Шутки программистов 📌https://max.ru/itumor Шутки программистовЗащита, взлом, безопасность 📌https://max.ru/thehaking Канал о кибербезопасностиhttps://max.ru/xakkep_1 Хакер FreeКниги, статьи для дизайнеров 📌https://max.ru/odesigners Статьи, книги для дизайнеровМатематика 📌https://max.ru/Pomatematike Канал по математикеhttps://max.ru/phismat_1 Обучающие видео, книги по Физике и МатематикеВакансии 📌 https://max.ru/progjob Вакансии в ITМир технологий 📌 https://max.ru/mir_teh Канал для любознательныхБонус 📌 https://max.ru/piterspb_78 Свежие новости Санкт-Петербургаhttps://max.ru/mockva_life Свежие новости Москвы

Этот пост выкуплен под рекламную интеграцию. Но здесь будут скрины от участников frontend-менторства Тихона Галактионова и подборка полезных материалов:👉100 вопросов, которые точно помогут тебе на собеседовании: ссылка👉Подборка из 100+ каналов с вакансиями для разработчиков: ссылка👉10 задротских вопросов про JavaScript, после которых ты усомнишься, что вообще знаешь JS: ссылка👉Чек лист проверки своего резюме: ссылка👉Разбор самых популярных и каверзных вопросов на собесах: ссылка👉Лайфхак как аккуратно “пинговать” рекрутеров: ссылкаСсылка на канал Тихона, там же можно найти больше материалов для подготовки к собеседованиям в Big Tech: ссылкаРеклама, erid: 2W5zFGy2Ay7 ИП Галактионов Тихон Витальевич, ИНН 771618975809Этот пост выкуплен под рекламную интеграцию. Но здесь будут скрины от участников frontend-менторства Тихона Галактионова и подборка полезных материалов:👉100 вопросов, которые точно помогут тебе на собеседовании: ссылка👉Подборка из 100+ каналов с вакансиями для разработчиков: ссылка👉10 задротских вопросов про JavaScript, после которых ты усомнишься, что вообще знаешь JS: ссылка👉Чек лист проверки своего резюме: ссылка👉Разбор самых популярных и каверзных вопросов на собесах: ссылка👉Лайфхак как аккуратно “пинговать” рекрутеров: ссылкаСсылка на канал Тихона, там же можно найти больше материалов для подготовки к собеседованиям в Big Tech: ссылкаРеклама, erid: 2W5zFGy2Ay7 ИП Галактионов Тихон Витальевич, ИНН 771618975809
🧬 Нативные операции с множествами (Set Methods)Классическая задача на собеседовании: «Найди общие элементы в двух массивах».Обычно мы писали arr1.filter(x => arr2.includes(x)). Это O(N*M) по сложности (медленно) и выглядит многословно.Начиная с ES2024 у объекта Set появились полноценные математические методы. Больше никаких lodash.intersection или самописных хелперов.🔥 Как это работает теперь:Допустим, у нас есть права доступа пользователей:const editors = new Set(['read', 'write', 'comment']);const admins = new Set(['read', 'write', 'delete', 'ban']);1. Пересечение (Intersection)Найти, что общего (какие права есть у обоих).const common = editors.intersection(admins);// Set(2) { 'read', 'write' }2. Разность (Difference)Найти уникальные права (что есть у админа, чего нет у редактора).const uniqueAdmin = admins.difference(editors);// Set(2) { 'delete', 'ban' }3. Объединение (Union)Слить всё в одну кучу без дублей.const allRights = editors.union(admins);// Set(5) { 'read', 'write', 'comment', 'delete', 'ban' }4. Симметричная разность (Symmetric Difference)Найти всё, что НЕ пересекается (уникальное для каждой из групп).const uniqueToEach = editors.symmetricDifference(admins);// Set(3) { 'comment', 'delete', 'ban' }Почему это круто:1. Читаемость: Код говорит сам за себя.2. Скорость: Нативная реализация на C++ в движке браузера всегда быстрее JS-циклов.3. Гибкость: Методы принимают не только Set, но и любые итерируемые объекты (массивы, генераторы), автоматически преобразуя их при необходимости (в зависимости от реализации, но лучше передавать Set для гарантии).📲 Мы в MAX👉 @frontend_1
Почему z-index: 9999 не работает (и как перестать страдать)Знакомая ситуация? У вас есть модалка, которая почему-то перекрывается хедером. Вы ставите ей z-index: 100. Не помогает. Ставите 1000. Тишина. В ярости пишете 999999... и всё равно хедер сверху.Добро пожаловать в ад Контекстов наложения (Stacking Contexts).Главная ошибка джунов (и не только) — думать, что z-index - это глобальная очередь, где у кого цифра больше, тот и король.☝️ Суровая реальность:z-index работает только внутри своего контекста наложения.Представьте, что ваша верстка - это стопка книг.1. Хедер - это книга. У неё z-index: 2.2. Сайдбар - это книга. У неё z-index: 1.Внутри Сайдбара лежит ваша модалка. Вы даете ей z-index: 9999. Но модалка - это страница внутри книги "Сайдбар".Неважно, какой номер страницы вы ей дадите. Если вся книга "Сайдбар" лежит ПОД книгой "Хедер" (1 < 2), то и ваша модалка навсегда останется под хедером.🛠 Кто создает новый контекст наложения?Это не только z-index + position. Контекст создают свойства, на которые вы могли даже не подумать:• opacity меньше 1• transform (любой, кроме none)• filter• will-change• isolation: isolateПример из жизни:Вы добавили красивую анимацию появления на родительский блок (opacity: 0.99), и вдруг все тултипы внутри него провалились под соседние блоки. Потому что opacity создала новый контекст, и дочерние элементы оказались заперты в нем.💡 Как лечить?1. Не участвуйте в "Войне Девяток". Если вы пишете z-index: 1000, скорее всего, у вас архитектурная проблема. Обычно хватает 1, 2, 3.2. Проверяйте родителей. Если элемент не всплывает, идите вверх по DOM-дереву и ищите того, кто создал новый контекст (обычно это transform или overflow: hidden).3. Используйте Порталы (React Portals / Vue Teleport). Модалки, тултипы и дропдауны должны жить в корне body, а не глубоко в верстке. Это единственный надежный способ вырваться из контекста родителя.4. isolation: isolate - супер-свойство. Оно принудительно создает новый контекст наложения. Полезно, когда ну
Синхронизация React с API браузера📲 Мы в MAX👉 @frontend_1
Идеальные заголовки без JS: text-wrap: balanceДизайнеры ненавидят «висячие» слова. Когда длинный заголовок переносится так, что на второй строке остается одно короткое слово - это боль.Раньше мы решали это костылями:1. Вставляли неразрывные пробелы .2. Ставили <br> (ломая адаптив).3. Тянули JS-библиотеки типа React-Text-Balancer.В CSS Text Module Level 4 появилась нативная поддержка балансировки текста.Как это работает:h1 { /* Браузер сам перенесет слова так, чтобы строки были примерно равны */ text-wrap: balance;}Разница наглядно:❌ Обычный перенос (wrap):Супер важный и очень длинныйзаголовок✅ Сбалансированный (balance):Супер важный и оченьдлинный заголовок🧠 Senior-нюанс: balance vs pretty1. text-wrap: balance• Для чего: Заголовки, цитаты (короткий текст).• Как работает: Пытается сделать все строки одинаковой ширины.2. text-wrap: pretty • Для чего: Основной текст (Body), длинные статьи.• Как работает: Оптимизирует только конец абзаца, чтобы не оставлять «сироту» (одно слово) на последней строке.• Производительность: Быстро, можно использовать везде.Итог: В дизайн-системе для h1-h6 ставим balance, для p - pretty. И удаляем JS-хелперы для типографики.📲 Мы в MAX👉 @frontend_1

Cовет💡Быстрый и простой совет для вложенных радиусов: ваши углы будут выглядеть намного лучше, если вы установите внешний радиус на сумму внутреннего радиуса + отступы.📲 Мы в MAX👉 @frontend_1