Галоўная / Артыкулы / Чаму мікрооптымізацыі не можаюць паспакаваць проблемы справжней скорасці JavaScript

Чаму мікрооптымізацыі не можаюць паспакаваць проблемы справжней скорасці JavaScript

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

3977 слоў

На паперы прыёмнае запрасце выглядала адказальна.

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

Команда затвердзіла яе без жадных ваганоў.

Чырэх тыдзён пазней корыстувачы ўсё яшчэ казалі, што прыстрой запрацоўвае повольна.

Не тая повольнасць, калі „бенчмарк паказвае калькі дапаможных мілісэкунд“.

Не проблема з цыфрамі на панелі керування.

Тая сама повольнасць, якая насправды вплывае на людзей.

Яны нажымалі кнопку і не былі впэўнены, чы гэта было зафіксавана.

Яны ачынялі экран і сядзелі, чакаючы, калі ж з’явіцца ўсё неабходнае.

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

Команда вложыла рэальныя зусілля ў праблему павышэння каркаснасці.

Але яны нараблялі ўсё гэта на неправильных цялях.

Такі патэрн стаў стандартным у сучасных проектах на JavaScript.

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

Оптымізаваць тое, што лёгкае замерыць, а не тое, што на самай працэ пачуваюць корыстнікі.

JavaScript пропануе безліч элементаў, якія можна оптымізаваць.

Компонент перерысовываецца чатырнацать тысяч разоў.

Тады вы яго лагодзіце.

Зборка коду важыць 300 КБ.

Тады вы яе скрацваеце.

Функцыя выконуецца за 12 мілісекунд.

Тады вы яе перапісваеце.

Залежнасць займае 40 КБ.

Тады вы яе адмахваеце.

Мікро-тэст паказвае, што падход А перамагае падход Б на 7 процэнтаў.

Тады вы выбіраеце A.

Кожны з гэтых варыянтаў можа быць легітым спосабам работы.

Але ні адны з іх не прыносіць автаматычна кращага досвіду для чалавека, які викорыстоўвае вашу прыёмку.

Інодзе найшвэдчэйшы код, які вы напісалі, проста рашае проблему, якая нікога не турбавала.

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

Гэта неадпаведнасць — гэтая справжняя проблема, яю варыта расследаваць.

Прыдатнасць — гэта не тое ж самае, што і швальнасць

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

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

Уявіце старонку, якая праходзіць па гэтай последовальнасці:

  1. Завантажыце шэл прыемнікі.
  2. З’явіце калькі JavaScript.
  3. Запусціце фрэймворк.
  4. З’явіце даныя налаштаванняў.
  5. З’явіце текущага пользователя.
  6. З’явіце даныя прывілеў.
  7. З’явіце контэнт панелі керування.
  8. Атрыбутаваце панель керування.
  9. З’явіце паведамленні.
  10. Атрыбутаваце паведамленні.

Кожны з эых крокаў можа быць абсалютна швыры сам па сабе.

Асалодныя проблемы крыюцца ў самай ланцузе крокаў.

Карыстальнікам не важна, чыя кожны элемент быў незалежна налагоджаны.

Їм важна тое, што яны дзівіліся праз абраны экран, пакуль нічога не з’явілася.

Самэ таму кожная рэальная дакладнае выявленне працоўных характэраў павінна начыняцца адной запытаннем:

Чаго на самай працоўнай стороне насправды чакаюць?

А не:

Як мне скораць час выканання гэтай функцыі?

Это прынцыпова разныя направленнія даследавання.

Разработчык можа пасвяціць тры гадзіны на тое, каб зменшыць час выканання функцыі з 8 мс да 3 мс.

Тым часам сторанка застаецца недзейнаўчая прыблізна 700 мс, чакаючы на запит, які ніколі не быў неабходны.

Это не справжня оптымізацыя.

Это проста прыведчэнне ў порядак мебліў, калі пацек у стэне за ямі праскаквае.

Манія 5 мілісэкунд

Разработчыкі JavaScript маюць слабасць да мікрооптымізацый.

Частка гэтага адказу ўсё-такі мае сэнс.

Людзі спарчваюцься пра викорыстанне цыклаў for проты map().

Яны сперчваюцься пра стратэгіі выдзелу памяці.

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

За всім гэтым стоіць справжняя, ценная інформацыя.

Проблема не ў розумэнні гэтых механізмаў.

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

Спачатку функцыя выканаецца 100 разоў пад час адной взаімодзеі з корыстнікам.

Зараз на кожны вызов яе выканання займае 2 мс.

Вы пасвятаваеце палову дня, каб зменшыць гэты час да 1 мс.

Аб’ём заўтрэчання: 100 мілісекунд.

Гэта можа матыць значэнне.

Але заўважкаймо, што тая ж взаімодзея таксама запускае непатрэбны вызов API, які на выкаананне займае 600 мс.

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

Як можна проста сказаць, гэта здаецца явным.

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

Непатрэбны вызов сеціі, навпакі, можа быць захаваны за трыма шарамі абстракцыі.

Это стварае прыцэпны і небяспечны паклон:

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

Браузер — гэта не ваша функцыя

Іншая частая памылка — гадаць, што час выканання JavaScript апавесцівае пра всю эфектыўнасць.

Гэта здалёка не так.

Прыкладніцтва, якое базуецца на браузеры, — гэта цэлая система, а не проста выкананне адной функцыі.

У гэтай системе ёсць:

  • Распакаванне DNS
  • Складанне з’яўлення звязку
  • Абмены данымі за протакалам TLS
  • Обробка даных на серверы
  • Запыты да базы дадзеных
  • Серіяваванне адпаведзей API
  • Час перадачы даных па сеті
  • Аналіз HTML
  • Аналіз JavaScript
  • Выкананне JavaScript
  • Атрыбутаванне візуальных элементаў
  • Расчыткі лейауту
  • Атрыбутаванне кольороў
  • Складання візуальнага кадру
  • і рэальная взаемадзейнаўчасць пользователя з усім гэтым
  • Кожны з эых этапаў можа паўтлумачыць, насколькі быстро ўсё вядзецца.

    Спадзяймося, вам паспела скасці час адрэсавання компонента React з 15 мс да 8 мс.

    Гэта справды хораша робота.

    Але якщо бэкенду трэба 900 мс, каб падготавіць даны, якія патрэбны таму компоненту, ваша палегчэнне практычна не будзе зазначальным.

    А можа сервер адпавядае быстра, але надае 2 МБ JSON для відобразэння, якому патрэбна толькі 20 КБ.

    Тады вы витрачаеце ціклы CPU і пропускную здатнась на перадачу даных, якія вовсе не павінны існаваць у такой форме.

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

    Ні адна з гэтых проблем не ўзьязначае сам компонент.

    Это проблемы архітектуры.

    Самэльга серйозная работа па павышэнню працэснасі часта выглядае не як „зробіць JavaScript быстрэй“, а больш як розследавальная работа.

    Вы выявляеце прычыну затрымкі і шукаеце яе адказ, незалежна ад таго, куды гэта прыведзе.

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

    Пры рашэнні пытанняў, як паспрабаваць падбіцца да кращай працы, існуе корыстны порядак прыорітэтаў.

    Адшвайцаванне операцыі — гэта хорашы результат.

    Але часта ўжо кращы варыянт — адхіліць гэту операцыю цалкам.

    Уявіце сабе гэты фрагмент:

    const results = expensiveTransform(items);
    

    Аналіз працы паказвае, што гэтае ператворэнне займае 40 мс.

    Ваша інстынктыўная рэакція можа быць оптымізаваць яго.

    Можа, вы введзеце кэш.

    Можа, заменіце яго на болей розумны алгорытм.

    Можа, перанесце гэту роботу куды-небудзь іншае.

    Але перш чым зрабіць хоць што-небудзь, запытайце ся:

    Чаму вообща выконваецца гэтае ператворэнне?

    Можа, выхідны результат зменяецца толькі тады, калі налаштаваецца фільтр.

    Можа, вы яго перзапускаеце празь кожнага рэндара, незалежна ад гэтаго.

    Можа, бэкенд мог бы даць вам ўжо обрабатаную версію.

    Можа, інтэрфейс на самай працоўцы не патрабуе всіх 10 000 рэядоў.

    Можа, вы запрашваеце даны, якія корыстнік ніколі насправдзе не ачынае.

    Настоямы раўёнак можа ўзагалі не знаходзіцца ў expensiveTransform().

    Можа, хапіцца проста адмовіцца ад вызову.

    Такой падход добра прыменяецца не толькі да гэтага прыкладу.

    Праскочыце запиты, якія вам не трэба адправляць.

    Праскочыце рэндарын UI, які застаецца схованым.

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

    Праскочыце выкарыстоўванне шляхаў коду, якія корыстнікі ніколі не актывацуюць.

    Праскочыце обрабоцу даных, якія можна было бы адфільтраваць ранейш.

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

    Найшырэйша можлівая операцыя — гэта тая, якая ніколі не выкананае.

    Размах пакета — не ўсё

    Размах пакета заслуговы на увагу. Гэта правда.

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

    Команда скорачае свой JavaScript-пакет на 50 КБ і вважае гэта успехам.

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

    Звяжана, пакет стаў меньшым.

    Але гэта не значыць, што якось паспрабоўка стала кращай.

    Нічога з гэтага не паводзіць да вывару, што размах пакета не мае значэння.

    Это значыць, што трэба з’ясаваць колі саме гэты JavaScript насправды выкарыстоўваецца.

    100-КБ скрыпт, які блакуе пачатковую інтерактыўнасць, можа маты значныя наследкі, больш ніж 300-КБ скрыпт, які завантажаецца пазней для функцыі, якой корыстнік можа скорыстацца раз у месяц.

    Час выканання мае значэнне.

    Момент выконання коду таксама мае значэнне.

    Важна тая прычына, на якай працюе прыстрой.

    Важна сетка, якой ён выкарыстоўваецца.

    Важна такса кэшавання.

    І, не менш важна, важна тая прычына, калі сам акуар выконвае певную дзеянне.

    Якщо якая-небудзь функцыя викорыстоўваецца рэдка, то завантажэнне ўсіх неабходных элементаў пад час запуску можа стаць няэфектывным рашэнням.

    Раздзелэнне коду дапамагае ў гэтым.

    Так сама, як і паслядовае завантажэнне.

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

    Правильны вопыт не ёсць:

    Як нам яшчэ зменшыць габараты гэтага пакета?

    Ён ёсць:

    Калі сам акуар зараз патрэбуе конкрэтнае рашэння, і як шыбка мы можамы зробіць гэта рашэння доступным?

    Такой падход дапамагае прыбыць набліжэй да меты.

    Компанента, на якую вы адзірнуеце, можа не ў кашле

    Кожны, хто працаваў з React, ведае гэты цыкл.

    Компанента перарысваецца больш, чым трэба.

    Хтось вяртаецца да useMemo.

    Адна зайвая перарысовка зникае.

    Усі задаволеныя.

    Потым той самы падход застосоўваецца да наступной компанеты.

    Чырз калькі час кодбаза заполняецца вызвамі мемоізацыі:

    const filtered = useMemo(
      () => expensiveFilter(items, query),
      [items, query]
    );
    
    const handleClick = useCallback(() => {
      doSomething(id);
    }, [id]);
    
    const value = useMemo(
      () => ({ user, permissions }),
      [user, permissions]
    );
    

    Іноды гэта справды правільны крок.

    Іншыя разы гэта проста ускладняе розумеенне коду, не выправляючы практычна нічога.

    Оптымізацыя не ў безкоштовнасці.

    Мемоізацыя, у частным случае, мае рэальныя затраты.

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

    Змяркуйце раней, чым прымаць такі крок.

    Якщо якась вычысканне коштае 0,2 мс і выпалюецца рэдка, яе оптымізацыя нічога вам не дае.

    Якщо ж яна коштае 50 мс і выпалюецца пасля кожнага натыкання на клавішу, то гэта зусім іншая ситуацыя.

    Мета не ў тым, каб шукаць кожны раз практычна новыя вычысканні.

    Мета — ў тым, каб взаімадзеянні, якія маюць значэнне, здаваліся дастаткова шырокімі.

    Этыя два цялей не ўзаемна збігаюцца.

    Сфокусавайцеся на взаімадзеяннях, а не на адзінаковых складовых

    Сюды багато команд моглі бы отрымаць парадоксальную корысть ад змены падходу.

    Пользоватары не спрыймаюць складовыя як адзінаковыя елементы.

    Яны перажываюць тое, што робяць.

    Яны пішу запит на пошук.

    Яны запоўняюць полья.

    Яны пераходзяць між сторанамі.

    Яны надаюць форму.

    Яны ачынаюць выпадаючы список.

    Яны пералічваюць між вкладкамі.

    Яны завантажаюць файл.

    Яны прасуваюць кантэнт.

    Яны сядзяць і чакаюць, пакуль ўсё з’явіцца.

    У працоўным порядку не трэба запытаць:

    Чы гэты компанент добра аптыханы?

    Спробуйце запытацца:

    Чы введэнне тэксту ў гэтае польа пошуку выглядае мгновенным?

    Замест таго, каб запытацца:

    Чы гэты спіс адрасаваецца эфективна?

    Запытайце:

    Чы хтось можа павольна прасуваць гэты спіс, без перашкод ад інтэрфейсу?

    Замест таго, каб запытацца:

    Чы мы зменшылі колькасць адрасаванняў React?

    Запытайце:

    Чы нажатыя на гэты кантакт дае корыстніку негараздзеваючую, мгновенную адпаведь?

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

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

    Вкладка «Сеть» зазвычай краща за цикл, які вы перапісваеце

    Перш чым трагнуцца да хоць якога циклу, ачыніце панель сеті вашага браузера.

    Это не проста рада, яку можна ігнораваць.

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

    Зверніце увагу на такі аспекты:

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

    Возьмімо пошук як прыклад.

    Это наўважны падход:

    User types "j"
    → request
    
    User types "ja"
    → requestUser types "jav"
    → requestUser types "java"
    → request
    

    Команда можа тады вялікімі зусіллямі старацца прышвыдзіць атрыбутаванне рэзультаатаў.

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

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

    Гэта тае павышэнне, якое вырабатваецца на рэвэлі системы, а не ўнутрь адной-ўсёй функцыі.

    Не оптымізавайце неправильны прыстрой

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

    Гэта мае вельмі важлівое значэнне для JavaScript.

    Савременная апаратура можа обрабоцваць значны объём коду, і разработчык нават не зазначае сповільнення.

    Моцны ноутбук можа маскаваць проблемы.

    Флагманскі тэлефон можа маскаваць проблемы.

    Швайны офісны сеть можа маскаваць проблемы.

    Работа локальна таксама можа маскаваць проблемы.

    Потым рэальны чалавек ачынае аплікацыю на бюджэтным прыстрое через нестабільны з’ўязак.

    Раптам тая рэтельна настроўаная аплікацыя стае важкай у викорыстоўванні і нерэакtyваючайся.

    Самэ гэтая прычына, чаму теставанне за реалістычных умовах мае важлівэ значэнне.

    Вам не трэба робіць гэта стало.

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

    Правильны вопыт не ў тым:

    Чы гэта здаецца швайна на маій наладзе?

    А ў тым:

    Чы гэта швайна дастаткова для тых, хто яго насправды викорыстоўвае?

    Архітектура зазвычай перамагае мікрооптымізацыю

    Гэта, можна сказаць, найважлівейшы урок з усіх.

    Архітектура ёсць тое, што вялічынюе стэпень карыстоўнасці.

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

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

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

    Якщо якая-небудзь дзеянне пользователя стварае вельмі большы частак усунутага кэшаванага стану, то выкорыстанне мемоізацыі для компанентов не будзе вярнуць правильную стратэгію анулювання данных.

    Якщо вы адразу відрасцвяліваеце тыячы элементаў DOM, то змена способу выкорыстання map() не дапаможае захаваць час.

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

    Это ўпрабавкі на архітэктурны роўні, а не падкоректы на роўні коду.

    Што я на самай працы адступаю пад час расследавання працэсу выконання

    Калі ўсё здаецца медленным, трэба стрымацца ад негайнага падхождзення да коду.

    Спачатку неабяжна перадаць проблему.

    Потым запытайце, на шта самэўсёды чакае корыстнік.

    З таго моменту розследаванне зазвычай выконваецца па аднаковам порядку.

    1. Завантажэнне

    Што павінна адбыцца, прычым корыстнік можа побачыць і выкарыстоўваць важлівыя часткі стораніцы?

    Адступіце за критычны маршрут.

    Калія рэсурсы ў дзеўяльнасці патрэбны?

    Калія запытанні блакуюць працэс?

    Што завантажваецца, калі таго не трэба?

    2. Сеть

    Ачыніце панель Сеть.

    Шукайце шаблоны у вигляде «водоспаду».

    Ланцюгі последовных запытанніў заслуговуюць на асаблівую увагу.

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

    3. Атрыбутаванне

    Далей паглядзіце, што сам браузер выканаў.

    Чы не падае стораніца вельмі большую колькасць DOM-дадзеных?

    Чы крокі планавання і атрыбутавання є даскладнымі?

    Чы гэта дорогія праця выконваецца у адказ на дзейнаўку пользователя?

    4. JavaScript

    Толькі на гэтым этапе пачынаюць маты значэнне деталі на рывень функцый.

    Калькі з’явоў на самай працы спрачоўваюць час CPU?

    Калькі з іх выконваюцца паўтароўна?

    Калькі з іх связаныя з тым, што ўжо зрабіў пользователя?

    5. Памяць

    Якщо працоўнае запісанне становіцца гorsзым чым дольша яно застаецца ачытым, варта пераканацца з памяцю.

    Атрыманне памяці і неконтрольаваныя адзначкі можу выглядаць як звычная медлівасць.

    6. Рэальны адзінак на пользователя

    У падсумку, связайце все, што знайшлі, з рэальным досвядам.

    Чы стала працоўная запускальная процэс быстрейшым?

    Чы пошук стаў адпаведнейшым?

    Чы палітурка паспелацья паднялася?

    Чы якісь з процэсаў сталі менш болючымі?

    Якщо нічога з гэтага не змянілася, варта запытацца, чы справжняя проблема ўзагалі была выявлена.

    Бюджэты на працоўную дасканаласць ўжытковыя — якщо яны связаныя з рэальнасцю

    Звычайна справа, калі команды встановляюць такія правіла:

    Размер пакета JavaScript должен быць менейшы 300 КБ.

    Это разумная пачатковая точка, кращая, чым абсолютна відсутнакі правіл.

    Але бюджет, створаны на аднойчынным досвядзе, зазвычай ўжоць карыснейшы:

    • Галоўны контэнт должен быць практычна мгнова відобразжаны
    • Пошук не должен вяліцца надта дзейсна
    • Навігацыя должна негайна даўаць адказ
    • Ключовыя сторанкі не должны залежаць ад ланцоўка парадных запытак
    • JavaScript, неабходны для першай взаімадзеяння, должен быць мінімальны
    • Вялікія наборы дадзеных не должны відразу практычна выкліквацца на экране

    Їх важка пераклацаць у адзін чысты цифра.

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

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

    Яны становяцца небяпечнымі тады, калі досягненне певных цифр стае асальным метай.

    Пастка оптымаізацыі

    Існуе тонкі псыхалогічны фактор, який спрабоўвае прывести разработчыкаў па гэтым шляху.

    Оптымаізацыя чаго-небудзь здаецца прогрэсам.

    Вы можете паказаць на конкрэтны кастом і сказаць:

    Размах пакета зменшыўся на 14%.

    Або паказаць на тэст і сказаць:

    Гэтая функцыя тепер працюе на 32% быстрэй.

    Або даць кому-небудзь скріншот прафайлера як доказ.

    Гэтыя успехі здаюцца прыемнымі.

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

    Скасыванне некалькіх непатрэбных вызоў API не стварае захоплюючай дэманстрацыі.

    Перакаштовванне адпаведзення бэкенда таксама не ёсць красавіцай.

    Це таксама не ўскорэнне ланцуга залежнасцяў.

    Це таксама не выправленне запиту, які з’яўляе 5 000 рэядоў, калі дасканальна будзе 50.

    Це таксама не дадаванне кэшу.

    Робота, якую вы намагаетесь ухіліцца ад выкарання, за сваёю прыродай застаецца непазіруемай.

    І самэ гэта ўсё чым легка яе працягнуць.

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

    Можа не быць нічога, што варта было бы сфатаграфаваць.

    Проста прыстрой запускаецца краща.

    Оптымізацыя павінна начыняцца доказамі

    Ось правіла, якое варта прыйняць у всіх аспектах:

    Не оптымізавайце код. Оптымізавайце падтверджаныя проблемы.

    Для гэтага не трэба ствараць складныя процесы інжынеріі пасіблення для кожной функцыяй, яку вы выпускаеце.

    Цэль — проста збіраць достатню колькасць доказаў, каб зразумець, куды на самай працоўвае час.

    Акцыянуйтесь на інструментах для аналізу працы програмы.

    Іспользуйце вбудованыя панелі кароткага аналізу працы браузера.

    Зберагайце даныя парадакту сеті.

    Прыемліце даныя з рэальных умов працы програмы.

    Установіце монітарынг рэальных корыстнікаў там, дзе гэта мае сенс.

    Тэставайце на прыстроях, якія адпраўляюць реальную аудыторію.

    І, галоўнае, воспамінайце ситуацыю такой, якая была адзвярнута.

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

    Спачатку з’ясавайце, на шта самэй паўза.

    Чы не медленная ёсць пачатковая адпаведзь сервера?

    Чы проблемай являецца адпаведны вызов API?

    Чы пакет JavaScript занадта вялік?

    Чы парсаванне займае занадто много часу?

    Чы рэндарынг ёсць даскладным элементам?

    Чы якаясь дзейнасць заблокавала галоўную ніт?

    Чы запит да базы дадзенаў працюе неэфектыва?

    Чы гэтыя запыткі ствараюць затрымкі?

    Чы браузер проста сядзіць без дзеяння, чакаючы на ўсё, што могла бы пачацца раней?

    Ці ж аплікацыя тэхнічна реагуе, але не дае корыстніку жадных візуальных адказоў?

    Дыбаггін працэса выконання — гэта робата детектыва.

    Гэта не гонка, каб паціць, хто можа выдаліць больш JavaScript.

    Найлепшая оптымізацыя JavaScript можа быць меншым колькасцю JavaScript

    Гэта можа здавацца дзівным для разработчыка JavaScript.

    Але гэта становіцца ўсё важлівейшым, калі аплікацыі растуць.

    Кожны фрагмент коду, які выконваецца на кліянтэ, мае свой расход.

    Його трэба завантажыць.

    Можа, яго трэба аналізаваць.

    Можа, яго трэба компіляваць.

    Його трэба выканаць.

    Яны спрацоўваюць памяць.

    Яны конкуруюць з браузерам за час адрасавання.

    Яны можу стварыць перашкоды пад час взаімадзеяння з корыстнікам.

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

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

    Інодзе кращым рашэнням ёст трымка інфармацыі на сервере.

    Інодзе — стрімаванне кантэнту замест блакування яго обробкі.

    Інодзе — перанесенне логіки цалкам у бэкэнд.

    Інодзе — введенне кэша.

    Інодзе — скорачэнне таго, што вяртае API.

    Інодзе — завантажэнне элементаў поступова, а не ўсіх разам.

    Інодзе — проста адмена функцыі, якой ніхто насправдзе не выкарыстоўвае.

    А інодзе JavaScript, які вялічыцца ўже зараз, абсалютна падходзіць такім, які ён.

    Галоўная мысль — перастаць прыймать за звычку, што оптымаізацыя павінна адбывацца саме внутры JavaScript.

    Што ў канцэ научаюцца высокакваліфікаваныя разработчыкі

    У пачатковыя моменты кар’еры разработчыка оптымізацыя зазвычай означае прынятнае працаванне існуючага коду.

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

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

    Это значыць розвіт мышлення.

    Уместо таго, каб запытацца:

    Можна лягчэ заставіць гэты цыкл працаваць?

    Запытанне стае такім:

    Чаму ўвесь час переглядаюцца 20 000 записаў у браузеры?

    Уместо таго, каб запытацца:

    Як можна завадзіць гэтаму компоненту пераробляцца занова?

    Запытанне стае такім:

    Чаму аднае взаімадзейсцо выклікае змены ў всім стане сторонніцы?

    Уместо таго, каб запытацца:

    Як можна зменшыць размах гэтага пакета?

    З’яўляецца такой пытанне:

    Чаму корыстнік должен завантажыць гэты код прычым робіць што-небудзь значныя?

    У замен на пытанне:

    Як можна зробіць гэты запит болей эфектыўным?

    З’яўляецца такой пытанне:

    Чы рэальна ёсць патрэба ў гэтым запытанні?

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

    Мета — не швыракі код

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

    Работа над выдатнасцю — гэта не стварэнне найшвыракага можлівага JavaScript-кода.

    Гэта стварэнне продукту, які для людзей, якія ім фактычна выкарыстоўваюць, здаецца дастатньш швыракім.

    Гэтыя два цялі — не адна і тая ж рошчынь.

    Чудова оптымізаваная алгорытм не мае жаднае значэнне, якщо корыстувач змушаны чакаць два секунды на запуск задачі, яка яго актывае.

    Ідеальна компанента з мемаізацыяй не дапамагае, якщо сторанка атрыбутуе 40 компанент, якія корыстувач нават не побачыць.

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

    А павышаны показнік тэста нічога не значыць, якщо жадны рэальны корыстувач не відчувае разліку.

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

    Таму ўсё важлівейя знать, што не варта оптымізаваць.

    Пачніце з акцэнту на корыстувальцы.

    Знайдзіце рэальную затрымку.

    Правільна яе вызначыце.

    Праследавайце яе па всій системе, ад початку да канца.

    Адключыце всю непатрэбную роботу.

    Толькі тады трэба працаваць над прышвічаннем таго, што засталося.

    Этая парада мае значэнне.

    Адтуды, што найценнейшая оптымізацыя не павінна быць непабойна з тэхнічной точкі зору.

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

    Спадневана літэратура

    • Native Browser APIs Replacing Popular npm Packages in 2026 — Адказвае на пытанне, як вбудованыя функцыі JavaScript і CSS, такія як Signals, оператар пайплайна, Temporal і Anchor Positioning, заменяюць популярныя пакеты npm.
  • Праўя складнасць сучаснага JavaScript выходзіць з інструментаў, а не з самага языка — У гэтым артыкуле пояснюецца, як такія функцыі JavaScript, як async/await і optional chaining, спрыяюць спрасцаванню коду, тады як занадто многі інструменты і залежнасці ствараюць непатрэбную складнасць.
  • Як DataLayer GA4 выявляе, чырэй аналітыка ёсць справжняя — Пояснюецца, як dataLayer з’ѐднае веб-сайты і GTM з GA4, чаму простыя запісы падваюць аналітыку э-камеры, і як правільна структураваць та дэбагаваць даны.