Галоўная / Артыкулы

Прысохнаеасць JavaScript адносіцца да меньшай колькасці работ, а не да меньшай колькасці ліній коду.

Работа з аптаймам значыць выбір тых вычысленняў, якія не трэба запускаць, адкрыта ацэнка показначыкаў Core Web Vitals, а таксі карэкцыя самых важлівых частак коду, а не проста зменшэння колькісці рядкоў коду зарады самай ці яе.

Выдавец: REACTAPP.TOP12 хв чытання2672 слоў

Крыніцы: JavaScript Performance Isn’t About Writing Fewer Lines

Сярод JavaScript-кода, які работаюць найшыбкая, частае ўсё той код, які вы ніколі не запускаеце

Работа над пасункамі часта асоцыюецца з напісаннем болей тэплых цыклаў. У прыглядніках найбольшыя пасункі зазвычай даходзяць ад таго, што выпрацоўваецца менш: меньш колькасць обработчыкаў, якія запускаюцца, меньш колькасць змян у DOM, меньш колькасць сеансаў з’язку, меньш часу на галоўнай вясі. Разглядзім поле для пошуку, якое перэфільтруецца пасля кожнага натыку клавішы:

input.addEventListener("input", () => {
    renderResults(filterUsers(input.value));
});

Уведзенне імені выклікае серыю промежуточных запитоў:

m
ma
mah
maha
mahad

Большая частка гэтых промежуточных рэзультатаў адкідаецца. Техніка debouncing скупчвае гэтыя запиты, так што выпрацоўваецца толькі адзін запит:

const debounce = (fn, delay = 250) => {
    let timer;
return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn(...args);
        }, delay);
    };
};
const search = debounce((query) => {
    renderResults(filterUsers(query));
});

Тэла функцыі не сталае болей розумным; змянюецца распорядак выпрацоўкі, і самэ гэта зазвычай вялічыць або пасляабюе пасунк прыглядніка. Гэты падход — утрыманне, адкладэнне, скупчэнне — кращы за мікрооптымізацію функцыі, якая не должна выпрацоўвацца так часта.

Узкі запиты не ўжо безкоштовны. Кожна натысканая клавіша може выдзеляць масівы, праходзіць па вялікіх спісах, апдэйтаваць вузлы React чытаў DOM, а таксама планаваць процесы атрыбутаў. У тэлефонах середньяго класу гэтыя витраты прыводзяць да помітных затрымкаў. Метод debouncing — толькі адна з апцыяў для кансалідацыі задач; обмежэнне працы хендлероў прасування, кансалідацыя абзэрвэраў змены размеру і пропуск виконання задач, калі вкладка схована, — гэта розныя способы адной і той жа ідеі: выконваць задачу тады, калі рэзультат усё ўсё мае значэнне.

Не оптымізавайце саму функцыю. Оптымізавайце саму роботу.

Прэобразаванне кожнага элемента за дапамою дорогай функцыі выглядае нейкша безнэпакойна:

items.map(item => transform(item));

З’ясавайце, чаму воўсе выконваецца гэта прэобразаванне, для якага экрана і як часта зміняюцыся рэзультаты. Якщо той самы корыстнік павтарае форматаванне, выкарыстоўваюце мемаізацыю:

const cache = new Map();
function getFormattedUser(id, user) {
    if (cache.has(id)) {
        return cache.get(id);
    }
    const result = formatUser(user);
    cache.set(id, result);
    return result;
}

Зберагчыце ідэнтычных даных пазбярогае павторны выкарыстоўванне CPU, не перапісваючы сам прыем для ператворэння. Той жа падход застосоўваецца да сортавання, фільтрацыі і стварэння модэляў відображэння: вырахоўвайце результаты, калі змянююцца даны, а не ў кожны момент рэндараўвання.

Мемоізацыя — гэта не безкоштовны раён. Неканчатковыя карты расшыроюцца, пакуль тэснае выкарыстоўванне памяці не спрычыняе проблемы з ўжоўтварэнням даных. Выбірайце ключы на аснове стабільных ідэнтыфікатораў, обмежыце размах кэшу і анулюйце даны, калі змянююцца выхідныя записі. Кращэ ствараць модэлі відображэння адно разу праз кожную змяну стана, чым перарахоўваць складныя структуры ў кожнай компаненте.

Ваш JavaScript можа быть быстрым, хоча UI будзе медленным

Дадаванне элементаў у DOM у рамках ціклу вымагае павторнай працы над лейаутам:

for (const item of items) {
    container.innerHTML += createCard(item);
}

Стварэнне строкі адно разу і ўсуненне яе адно разу — цэе дышэўней:

const html = items
    .map(createCard)
    .join("");
container.innerHTML = html;

Работа з DOM мае наследкіў, які выходзяць за межы самай стэтамента JavaScript, якая яе спрычыніла. Перасчыт стылю і макета може займаць значную частку часу адгуків фрэйму, нават калі лог скрыпты выглядае як «швыдкі».

Фрагменты дакумента і стварэнне DOM паўнасупрацоўна дапамагаюць, калі трэба стварыць многа вузлаў. Фрэймворкі автаматычна адрабоцують змяны пакетамі, калі вы яму на тое дазволяеце; борьба з фрэймворкам за дапамогою прымітных цыклаў innerHTML у важлівых частках коду знова прыносіць тыя самыя затраты, якія ціхі бібліятэкі існуюць для таго, каб ўтрымаць.

Макет можа стаць дорожэй, чым ваша функцыя

Чытанне атрыбутаў макета змушвае браузер вычысляць геаметрыю:

const height = element.offsetHeight;

Запіс стылю і праз час яго зноў чытанне спрычыняюць додатковыя навантажэння:

element.style.height = `${height + 20}px`;
const newHeight = element.offsetHeight;

Чытаць за раз, а потым запісваць за раз. Оядзець мераванне і змены ў важлівых частях коду, такіх як прыборкі прасування та анімазіі.

Прымусовая сінхронная структура ўлаштавання є распашчатым факторам у спецыяльных падказках, застывшых заголовках та HTML-контэнце, выравняваным па канвасу. Якщо біблія вынуждана выконваць меравання, яе трэба выконваць адна раз на кадр і зберагчы рэзультаты. requestAnimationFrame — гэта кращы спосаб выконання, чым простыя слухачы прасування, якія чытають геаметрыю пасля кожнай подіі.

Не прыменяйце галоўную нітку як свой ліст задач

Складныя перетворэння большых масів дадзеных блакуе ввод і адрасаванне элементаў на екране:

function processLargeDataset(data) {
    return data.map(expensiveTransformation);
}

З’ясавайце, чыякі робота прадтачыцца на галоўной нітцы. Рабочыя процесы пераносяць задачі, якія залежаць ад CPU, за межы інтерфейсу:

const worker = new Worker("processor.js");
worker.postMessage(largeDataset);
worker.onmessage = (event) => {
    updateUI(event.data);
};

Памяркуйце пра витраты на абмены дадзеннямі; намеравана перадавайце або клонуйце большыя об’емы дадзеных.

Рабочыя працэвнікі зменяюць прыналежнасць CPU, а не ступень складнасці продукту. Серыяванне можа знішчыць перавагі, якія ўтвараюцца пад час виканання дробных задач. Іспользуйце іх для парсінгу, шифравання, обробкі зображэнняў або великіх агрегацый — не для мікрозадач, якія завершаюцца быстрей, чым заўршаецца процес postMessage. SharedArrayBuffer і об’екты, якія можна перадаць, дапамагаюць, калі пакеты даных вельмі великі і налаштаванні безпекі це дазволяюць.

Lazy loading — это функцыя для пасібнасці

Не завантажуйце ўсё, калі толькі не патрэбна. Дынамічны імпорт відкладае виканання коду для рэдкасцейных маршрутаў:

async function openAnalytics() {
    const { Analytics } = await import("./analytics.js");
const analytics = new Analytics();
    analytics.open();
}

Пользоватары, якія ніколі не ачынаюць роздзел з аналітыкай, ніколі не завантажаюць той модуль. Спалюйце яго разам з роздзелаванням коду на рэвень маршрутаў, каб пачатковая навігацыя заставалася лёгкай.

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

Размер пакета — гэта не ўсё

Меньшыя пакеты дапамагаюць, але мінімальны пакет, які ўсё раве блакуе галоўную вяліну або выканае последовыя запрашэння, можа стварыць большыя проблемы, чым трохі большы пакет, які спачатку передае критычныя элементы інтэрфейсу. Меркуйце час до стварэння взаімадзея і затрымкі пад час взаімадзея, а не толькі кілабайты.

Прызначэння сеті — гэта таксама прызначэння JavaScript

Последовыя запрашэння з абявамі await паўтараюць затрымкі:

const user = await fetch("/api/user");
const posts = await fetch("/api/posts");
const notifications = await fetch("/api/notifications");

Незалежныя запрашэння павінны выконвацца паралельна:

const [user, posts, notifications] = await Promise.all([
    fetch("/api/user"),
    fetch("/api/posts"),
    fetch("/api/notifications")
]);

Последовыя запрашэння можу быць схаваныя ў функціях async так сама лёгка, як і ў некоректна аранжаваных тэгах скрыптам.

Сябрэйшы выкалека — гэта тая, якой вам не было трэба

У пачатковых экранах частаюць маленькія наборы даных, тады калі аплікацыя таксама актыўна запрашоўвае дадатковыя панелі. Лепей спачатку завантажыць галоўную панель керування, а рэшту заставіць на пазнейшы час:

await loadDashboard();
requestIdleCallback(() => {
    loadSecondaryData();
});

Не кожны завадзі заслуговае на аднаковую прыоритэтнасць. Бездзейныя вызовы, запрашанні з нижэйшай прыоритэтнасцю і явныя жесты корыстніка — гэта засобы для падбору роботы па ступеню трыбоці.

Кэшаванне можа быць важнейшым за мікрооптымаўванні

Кэші існуюць на роўні HTTP, сервісных працавнікаў, памяці і выведзеных станоў. Правильны ключ кэшу і правілы анвалідазаціі можу падрыхтаваць менш затрэмтання, чым перапісваўце сортаўвання. Документавайце правілы свежасці, каб застарэлая інтэрфейсная суперфіс не стала тыхой багом продукту.

Значкі памяці HTTP і ETags скарочваюць колькасць завантажэнняя; кэшы ў памяці скарочваюць колькасць парсаванняя JSON; сховішчы UI скарочваюць колькасць павтаральных вычыслаў. Кожны слой патрабуе чыстаако вялікога адпаведальнага за нейтрывацыю. Без такога адпаведальнага, каманды альбо запрашваюць занадто многа “для безпекі”, альбо паказваюць застарэлыя індыкаторы, якія разрушаюць довер’е.

Віртуалізацыя цэлкам зменяе проблему

Актыўнае атрыбутаванне тыяч рядоў не ўспівае:

rows.forEach(renderRow);

Віртуальныя спісы атрыбутаваюць толькі тое, што ўжо відразу видна. Складнасць пераходзіць з “зробіць кожны ряд дешавей” на “не ствараць рядоў за межамі екрана”, што зазвычай яе правильны выбар.

Бібліятэкі для вікнаў меняюць простата на правильнасць скроллу: неабходна старанна кераваць зменнымі высотамі рядоў, управленьнем фокусам і стыканням столбцоў. Усё-такі для большых набораў дадзеных яны працуюць краща, чым хіроўскія трюкі CSS. Їх трэба соедынаць з пагінацыяй на сервере, каб кліент ніколі не хаваў мільйоны записаў толькі для ўсунення іх у віртуальны формат.

Інструменты для аналізу працэздатнасці кращыя за здогадкі

Калі ўсё выглядае повольна, замерыце гэта. Chrome DevTools паказвае стан сеті, дуггі задачы на галоўнай вясці, проблемы з распакоўкай элементаў і адбіванне памяці. Здагадкі ведуць да праверкі неправильных функцый.

Простая перапытка аналізу працэздатнасці

Следавайце чартку, а не спешыце з прымусовым выборам мікро-оптых рашэнняў:

  1. Чы не повольна сеть?
  2. Чы завантажуецца занадто много JavaScript?
  3. Чы JavaScript блакуе галоўную вясь?
  4. Чы процес атрыбутавання элементаў ёсць даскладным?
  5. Чы мы паўтараем аднаковую роботу?
  6. Чы адбіваецца памяць?
  7. Чы проблема выступае толькі пад вялікім навантажэнням?

Адпавядаюце на пытанні на адной основе дадзеных, а не здагадкаў.

Найчастае падступленьне ў аналізе працэздатнасці

Команды выдваюць недзелі на оптымізацыю коду, які не ўчастковаў у стварэнні проблемы — прагледваючы мікросекунды на выкарыстоўванні певных функцый, тады калі чатырасекундны процес абрабоцкі зместу чы необмежаны список элементаў паслабляюць загалоўны адчутак. Апераду пераканайцеся, што прычына — самэ ў вузькай частцы.

Савэчасны JavaScript аддае кращыя інструменты

Ўжывайце можлівасці платформы, якія зменшаюць патрэбу ў самастайных рашэннях:

structuredClone(data);
const result = await Promise.allSettled(tasks);
const module = await import("./feature.js");
const controller = new AbortController();
fetch("/api/search", {
    signal: controller.signal
});

У інтэрфейсах пошуку часта патрабуюцца можлівасці абрання запускаемых запытак, каб застарэлыя адпаведзі не перакрылі результаты пошуку. Одна з надзеяных практык:

javascript
javascript performance
let controller;
async function search(query) {
    controller?.abort();
    controller = new AbortController();
    try {
        const response = await fetch(
            `/api/search?q=${encodeURIComponent(query)}`,
            { signal: controller.signal }
        );
        return await response.json();
    } catch (error) {
        if (error.name !== "AbortError") {
            throw error;
        }
    }
}

AbortController, дынамічныя імпорты та Promise.allSettled заменяюць многія ручна створаныя чергі та флагі.

Прыдатнасць мае аспект продукту

Перамога на розміре 100 мс не ўсегда ёсць цінна; важліва ўстановка. Скорачэнне часу адпаведнага прыемніка з 2 мс рэдка зміняе спрытакоўванне. Аднак скорачэнне часу першага завантажэння з чатырох секунд да двух секунд дзейсна мае значэнне. Мгновенная адпаведь на набіранне тексту можа быць важлівейшая, чым лёгкая праця фонавага процесу. Плавнае прасуванне можа маты большое значэнне, чым скорачэння часу перетварання дадзеных праз API. Аддача — это адчуткі, якія стварае система, а не элегантнасць мікротэсту.

Хавайце прабаваць ловіць цыфры, якія не адпраўляюць інформацыю пра корыстувальнікаў

Синтэтычныя тэсты дапамагаюць, але швайны ноутбук у локальной сеті з мінімальным обладнанням — гэта не реальная супрацоўка. Тэставайце репрезентатывныя прыстроі, сеті, размеры дадзеных і патэрны взаімадзеяння — іначы вы оптымаўліваеце вяртуальны прыкладак.

Як показнікі з лабараторыяў, так і з рэальных умоў ўжоць важлівы. Система Lighthouse выяўляе зворотныя явышчы ў процесе інтеграцыйных тэстаў; монітарынг рэальных корыстувачаў выяўляе асаблівасці прыстроёў і геаграфічных регіонаў. Калі ўсё гэта суперчыць, для праграмавання прыорітэтаў следзьце за показнікамі з рэальных умоў, а для відтворэння проблемы — за показнікамі з лабараторыяў. Бюджэты на працэсавую якасць, вырачаныя на адзнакі LCP, INP і час выканання дліжных задач, дапамагаюць заставаць дыскусіяў конкрэтнымі.

Мысленне пра працэсавую якасць

Лепш выкарыстоўваць такую параду запытанняў: Какія завады я можу ужо не робіць? Чаго можа выйсці пазней? Чаго можа выйсці рэдкае? Чаго можа выйсці ў іншым месца? Што на самай працэ ўплывае на корыстувача? Адказамі можуць быць застосаванне механізмаў debounce, кэшаванне, раздзелены код, віртуалізацыя, выкарыстоўванне працоўнікаў, змены ў API, паспакойванне запытоў — або ж выдалення непатрэбных функцый.

Заключныя мыслі

Найважнейшым урокам парадуксаў выконвання коду на JavaScript ня ёсць адзін API. Шырокі код — гэта не завжды код, які выконваецца быстра. Інодзе ён воўсе не выконваецца, выконваецца пазней, выконваецца адна раз у замяну на пяцьдесят, пакідае галоўную вясь і перестае прасіць іншыя системы аб непатрэбной роботе. Перастаньце спрабоўваць дасягнуць шырокаскорасці за счэт “меншых ліній” коду. Спрабоўваце зменшыць колькість непатрэбной роботы там, дзе яна вплывае на корыстніка.

Удаленне невыкорыстаных элементаў — гэта таксонамія парадуксаў выконвання. Кожная нерабочая бібліятэка дыяграм, автаматычны працоўнік медыя або спекулятивнае падготавленне дадзеных конкуруюць за пропускную здатнась і час галоўнай вясі. Кампаніі і інжынерныя падразумелыя слоўнае пераглядаць, якія функцыі ёшчэ маюць сенс. Найшырокаскорасцей JavaScript застаецца той JavaScript, які вы ніколі не завантажаеце, ніколі не парсуеце і ніколі не выкананяеце.

Рэагаванне на змены ў реальным часе: пошук, автазберэжчык і змена розмера

Пошук у рэальным часах — это прыклад для адукацыі, але тая ж самая дисцыпліна графіка прыменяецца і ў іншых ситуаціях. Автазберэжанне, якое запісвае кожны натыск клавішы, можа завантажыць сервер; кращэ чакаць, пакуль не будзе перервы у набіранні, і з точкі зору пользователя гэта частаўна тое ж самае. Функцыі resize і scroll вікна, якія перысчыляюць макет пасля кожнай подіі, ўзятыя як класычныя прычыны затрымакоў; обмежэнне ў колькасці кадраў анімацыі чы ў фіксаваным інтэрвале дапамагае падтрымаць рэактыўнасць галоўнага потока. Спаканная ідея не ў тым, каб «дадаць lodash», а ў тым, каб раз’яўліць намер (пользователь хоча фільтраваныя рэзультаты) ад графіка (як часта мы можамо выконваць вычысленні).

Калі вы выкаліце механізм debounce, выбірайце часовыя інтервалы в залежнасці ад патрабаванняў продукту: 150–300 мс падходзяць для пошуку, калі пауза здаецца мгновенной; дэльнейшыя інтервалы паслужаюць для дорогіх аналітычных сэнсараў. Анулюйце выконванне задачі, калі новы запит заменяе стары, ўбліжкі, каб пазнелія адпаведзі не давалі застарэлых рэзультатаў. Шаг анулювання настолькі ж важны, як і таймер.

Стратэгіі кэшавання за межамі Map

Map у памяці, ключаваны па id, — гэта толькі адна з роўней. Кэшы HTTP вырахоўваюць значэння Cache-Control і ETags, таму паўтарныя навігацыі прыменяюцься без перадачы даных. Сервісныя працоўнікі можу кэшаваць ресурсы шэлу і запыты API GET за дапамогою чысткіх правіл. Сховішчы аплікацый могу зберагаць нормалізаваныя ентыты, так што відворы списку і деталяў выкарыстоўваюць адну і тую ж звістку. Праектаваныя варыянты модэля відображэння — сортаваныя, фільтруваныя проекцыі — должны пераскладвацца, калі змянююцыся вхідныя даны, а не праз кожную некалязаную перрадка роднай структуры.

Анулюваньне ў дадзеныях — гэта складная частка. Параметр Time-to-live є простым і ясным. Анулюваньне на адпаведнасці з падзеямі („пользователь адкорэгаваў профіль“) є точным, калі вы контролюеце тыя, хто зменяе дадзеныя. Гібрыдныя падходы выкарыстоўваюць короткі тэрмін жыцця дадзенняў паўсцоўна ў поўнай меры, а таксама явныя способы анулювання пасля змін. Зазначыце, які слой керуе якімі дадзенымі, каб два кэшы не працавалі без адностайнасці.

Групаванне операцый DOM і саўместнае працаванне фрэймворкаў

Прямыя ціклы innerHTML += є анті-патэрном нават параду фрэймворкаў. Фрагменты дакументаў, метод replaceChildren аб стварэнне строкі ў адной моментзе — усё гэта зменшае некантрольаваныя переробкі лейауту. У React, Vue або Svelte кращэ выкарыстоўваць актуалізацію стану, якія дазволяюць бібліятэкам супрацоўваць з спискамі, адзначанымі ключамі. Звяршчаньне параметра offsetHeight пад час процеса рэндарування зноў створвае прымусовыя переробкі лейауту; кращэ выкарыстоўваць такія звяршчання ў эфектах лейауту аб спостерагачах, запланаваных пасля процесу атрыбута paint.

CSS containment і content-visibility могу абсалютваць работу з рэгіонамі за межама екрана, калі вярчуванне ўражае высокім навантажэнням. Адныя яны не ўсё: теставаць трэба на браузерах, якія вы падтрымляеце, і старацца разглядаць наследкі для доступнасці, калі контэнт прахоўваецца.

Бюджетаванне галоўнай вялі

Старацца, каб прыемнікі змаганняў залишаліся ў межах бюджету кадры — прыблізна 16 мс праз 60 Гц, менш, якщо кадру даваецца выкарыстоўваць для іншых задач. Разбіваць вялікія трансформацыі на часткі за дапамогою requestIdleCallback або асінхронных генератораў, якія періядычна выдаваюць данні. Для парсавання JSON паўмегабайтовага размеру кращэ вжываць стрімінгавыя парсеры або рабочыя процесы. Аналізаваць працэс за дапамогою роздзелу «Выконанасць» — якщо задача перавышае 50 мс, корыстувальнікі на слабейшых прыстроях будуць гэта відчуваць.

Рабочыя процесы павінны мець чыстае прыналежнасць: чыстыя функціі, залежныя ад CPU, — так; все, што патрэбуе DOM, — ні. Кост структураванага клонавання вырастае з розмеру графа об’ектаў; калі можна, выкорыстоўваюце ArrayBuffers. Кост запуску рабочых процесаў мае значэнне для разовых, мінімальных задач — інодзе кращэ выкорыстоўваць падход з основнай вяской.

Меры дадзеныя ў сеті і прыоритэты

await у последовасці є тым, што таямніча падвайшуе час адліку. Незалежныя запыткі павінны быць у Promise.all. Залежныя запыткі должны перадаваць толькі неабходныя ідэнтыфікаторы, а не весь пакет дадзеныя, каб зменшыць розмер паслядніх адпаведзей. Мультіксацыя HTTP/2 дапамагае, але не пазбавляе сервера часу на обробку; калі можна, зменшыце колькість пераходаў за дапамогою API, якія вяртаюць тое, што патрэбна на экране, за адні раз.

Прыорытет мае значэнне: спачатку контент-герой, пасля — дадзеные віджэты. Прыорытетныя парадксы функціі fetch, падготовка лінкаў і функцыі вызываў у стане без дзейнасці выражаюць гэты намер. Выконваць падготовку дадзеных пры наведэнні курсора для верагодных переходаў, якщо ўскладнення залишаюцца мерымі. Хадзіце ўхілівацца ад спекуляўнай падготовкі вялікіх сэтак дадзеных, якія корыстувач можа ніколі не ачыніць.

Вяртуалізацыя і формат дадзеных

Вяртуальныя спісы прыпускаюць або прибліжна аднаковыя высоты рядкаў, або рэгулярную кэшаванне ўзняценняў. Рядкі з мянючымся высотам трэбуе болей складнага калектавання дадзеных, але ўсё роўна лепшыя за адрасаванне дзесяці тысяч вузлаў DOM. Спалучайце кліентскую вяртуалізацыю з серверскай пагінацыёй або API-мі курсара, ўжо бы памяць заставалася стабільной. Функцыя бесканечнага прасування должна зупініцца, калі вкладка ўтаімаецца, і должна абавесці пра статус загрузкі для тэхналогій дапамогі.

Культура мэжавання

Інструменты лабараторыя выклікаюць адкрыцья зворотнага прыему ў процесе CI; інструменты на практыцы выклікаюць адкрыцья проблем, якія існуюць у самых прыстроях. Калі показнік INP низькі, трэба пераглядаць прыемнікі змагання і длігія задачы, а не толькі сеть. Калі показнік LCP низькі, трэба пераглядаць прыоритетаванне галоўнага зображэння і час адпаведзі цэнтра обробкі запытаў. Калі показнік CLS низькі, трэба звярнуць увагу на месца для пазнейшага адображэння кантэнту. Кожны показнік трэба прыясніць з адпаведным адпаведальным і бюджэтом, каб “работа над выконанасцю” не ператварылася на бесканечную правіка нерэльевантных элементаў.

Сінтэтычныя мікротесты чыстай функцыі рэдка калі можаюць прыведзці да правильнага прыкладзення ў рэальных умовах. Кращэ выкарыстоўваць даныя пра рэальныя взаімадзеі: падрыхтаванне запытаў у пошуку, ачынэнне модальных вікон, прасуванне столбцоў у ўжывучай табліцы. Зберагаюць такія даныя як доказы пад час адкарыцья багоў, каб дыскусіяй заставаліся конкрэтнымі.

Компрасы ў разработцы продукту

Не кожны мілісекунды ўсе роўнай цены. Мгновенная адзвечнасць пад час напісання чыя то ператасоввання мае большую цену, чым відмова ад тэкстуальнага звяртання, яке запускаецца раз у тыдзень. Інодзе найлепшая оптымізацыя — это адменшэнне функцый, якія спрацоўваюць за рахунак пропускной здатнасі та увагі, але даюць малая корысть. Працэздатнасць — это рашэнне, якое выражаецца чераз інжынерную роботу.

Запісваць падход у наклейку

Утримвацца ад роботы. Адкладаць роботу. Об’еднаваць роботу. Заносіць роботу з критычнага маршруту. Аналізаваць тое, што відчуваюць корыстувальнікі. Шэсць рядкоў кращыя, чым ста прытупных мікрооптымацый. Процэздатнасць JavaScript — это не столькі напісанне менша колькасць рядкоў, сколькі перакананне, што тыя рядкі, якія залишаюцца, заслуговуюць на месца на прыстрое корыстувальніка.