Ինչու է արագ աշխատող կայք ստեղծելն ավելի դժվար, քան թվում է
Why Building a Fast Website Is Harder Than It Looks
Կայք ստեղծելը, որն աշխատում է, հեշտ է։ Կայք ստեղծելը, որն արագ է բեռնվում, սահուն է աշխատում և լավ փորձառություն է ապահովում տարբեր սարքերում ու ինտերնետային կապի պայմաններում, բոլորովին այլ խնդիր է։
Frontend development-ում հաճախ հանդիպում ենք մի իրավիճակի․ հավելվածն աշխատում է, բոլոր ֆունկցիաները ճիշտ են, դիզայնը համապատասխանում է պահանջներին, բայց կայքը դանդաղ է բեռնվում, կոճակները երբեմն ուշ են արձագանքում, իսկ օգտատերը ստիպված է սպասել, մինչև էջը վերջապես պատրաստ լինի։
Ինչո՞ւ է դա տեղի ունենում։
Խնդիրն այն է, որ ֆունկցիոնալությունը և արագագործությունը տարբեր խնդիրներ են։ Այն փաստը, որ կայքը ճիշտ է աշխատում ծրագրավորողի համակարգչում, դեռ չի նշանակում, որ այն նույն կերպ կաշխատի իրական օգտատերերի համար։
Ժամանակակից frontend development-ում performance-ը կախված է բազմաթիվ գործոններից՝ JavaScript-ի չափից, rendering-ի ռազմավարությունից, ցանցային հարցումներից, նկարներից, բրաուզերի աշխատանքից և նույնիսկ այն որոշումներից, որոնք կայացվել են նախագծի ճարտարապետությունը կառուցելիս։
Այս հոդվածում կքննարկենք, թե ինչու է արագ կայք ստեղծելն ավելի դժվար, քան թվում է, ինչ սխալներ են հաճախ թույլ տալիս ծրագրավորողները և ինչպես կարելի է չափելիորեն բարելավել կայքի արագագործությունը։
1. Կայքը կարող է աշխատել, բայց միևնույն ժամանակ դանդաղ լինել
Պատկերացնենք՝ կառուցել ենք Next.js-ով աշխատող առցանց խանութ։ Ապրանքների էջը բացվում է, որոնումը գործում է, զամբյուղը ճիշտ է աշխատում, և բոլոր կոճակները կատարում են իրենց գործառույթները։
Սակայն էջը բացելիս օգտատերը մի քանի վայրկյան տեսնում է դատարկ տարածք։ Երբ փորձում է զտել ապրանքները, ինտերֆեյսը մի պահ սառչում է։ Իսկ բջջային սարքում էջը երբեմն անսպասելիորեն փոխում է իր դասավորությունը։
Ֆունկցիոնալ առումով ամեն ինչ կարող է ճիշտ լինել, բայց օգտատիրոջ փորձառությունը լավը չէ։
Performance-ը միայն էջի ամբողջական բեռնման ժամանակը չէ։ Կարևոր է նաև հասկանալ՝
Որքա՞ն արագ է օգտատերը տեսնում էջի հիմնական բովանդակությունը։
Որքա՞ն արագ է էջն արձագանքում նրա գործողություններին։
Արդյո՞ք էջի տարրերը մնում են կայուն բեռնման ընթացքում։
Որքա՞ն ռեսուրս է պահանջվում հավելվածն աշխատեցնելու համար։
Ինչպե՞ս է կայքն աշխատում դանդաղ ինտերնետի կամ թույլ սարքի դեպքում։
Այս հարցերի պատասխանները հասկանալու համար պետք է չափել ոչ թե միայն այն, թե ինչպես է կայքն աշխատում մեր համակարգչում, այլև այն, թե ինչ է տեղի ունենում իրական օգտատերերի մոտ։
2. JavaScript-ն ավելի թանկ է, քան թվում է
JavaScript-ը ժամանակակից frontend հավելվածների հիմնական գործիքներից է, բայց դրա օգտագործումը որոշակի գին ունի։
Երբ բրաուզերը ստանում է JavaScript ֆայլ, աշխատանքը չի ավարտվում դրա ներբեռնմամբ։ Ֆայլը պետք է վերլուծվի, անհրաժեշտության դեպքում կոմպիլացվի և կատարվի։ Այս աշխատանքը կարող է զգալիորեն ծանրաբեռնել հատկապես թույլ պրոցեսոր ունեցող սարքերը։
Պատկերացնենք՝ մեր էջում ունենք բազմաթիվ բաղադրիչներ, մի քանի մեծ գրադարան և մի շարք ինտերակտիվ հնարավորություններ։ Եթե այդ ամենը ներառված է սկզբնական JavaScript bundle-ում, ապա օգտատերը կարող է ստիպված լինել ներբեռնել և մշակել կոդ, որն անհրաժեշտ չէ էջի առաջին ցուցադրման համար։
Խնդիրը՝ ամբողջ կոդը միանգամից բեռնելը
Օրինակ՝ ունենք dashboard, որտեղ կա գրաֆիկների բաժին, որը օգտատերը բացում է միայն որոշակի գործողությունից հետո։
Եթե գրաֆիկների գրադարանը ներառված է հիմնական bundle-ում, այն կարող է մեծացնել սկզբնական ներբեռնման և JavaScript-ի մշակման ծախսը՝ նույնիսկ եթե գրաֆիկները դեռ չեն ցուցադրվում։
Լուծումներից մեկը՝ dynamic import-ն է։
"use client";
import dynamic from "next/dynamic";
const AnalyticsChart = dynamic(
() => import("./analytics-chart"),
{
loading: () => <p>Loading chart...</p>,
}
);
export function AnalyticsSection() {
return <AnalyticsChart />;
}Այս մոտեցումը թույլ է տալիս առանձին բեռնել բաղադրիչի կոդը՝ փոխարենը այն սկզբնական JavaScript-ի մեջ ներառելու։ Սակայն իրական արդյունքը կախված է նաև նրանից, թե երբ է բաղադրիչը render արվում և ինչպես է կառուցված հավելվածը։
Եթե գրաֆիկը միշտ ցուցադրվում է էջը բացելուն պես, միայն dynamic() օգտագործելը չի երաշխավորում, որ դրա կոդը կբեռնվի ավելի ուշ։ Իսկ եթե այն պետք է միայն կոճակը սեղմելուց հետո, կարելի է ներմուծումը կապել հենց այդ գործողության հետ։
Կարևոր միտք․ նպատակն ամենափոքր bundle-ն ունենալը չէ ցանկացած գնով։ Նպատակն է բրաուզերին հնարավորինս շուտ տալ այն կոդը, որն անհրաժեշտ է օգտատիրոջ ընթացիկ գործողության համար։
Արդյո՞ք ավելի շատ կոդ նշանակում է ավելի դանդաղ կայք
Միշտ չէ։ Չափազանց պարզեցված հավելվածը նույնպես կարող է դանդաղ աշխատել, եթե այն սխալ է կառուցված։
Կարևոր են ոչ միայն JavaScript-ի ընդհանուր չափը, այլև՝
Որքան կոդ է անհրաժեշտ սկզբնական էջը ցուցադրելու համար։
Որքան ժամանակ է պահանջվում կոդը մշակելու և կատարելու համար։
Որքան հաճախ են կատարվում ավելորդ render-ներ։
Որքան ծանր աշխատանք է կատարվում հիմնական thread-ում։
Որքան JavaScript է իրականում անհրաժեշտ տվյալ էջի համար։
Այդ պատճառով bundle analyzer-ը, բրաուզերի Performance panel-ը և իրական չափումները շատ ավելի օգտակար են, քան պարզապես կոդի ծավալը ենթադրելով օպտիմիզացիա անելը։
3. Rendering-ի ռազմավարությունը կարող է փոխել ամեն ինչ
React-ի և Next.js-ի նախագծերում կարևոր ճարտարապետական որոշումներից մեկը տվյալների ստացման և HTML-ի ստեղծման ձևն է։
Հիմնական մոտեցումներն են՝
CSR (Client-Side Rendering) — էջի հիմնական ինտերֆեյսը կառուցվում է բրաուզերում՝ JavaScript-ի միջոցով։
SSR (Server-Side Rendering) — HTML-ը ստեղծվում է սերվերում՝ հարցման ընթացքում։
SSG (Static Site Generation) — HTML-ը նախապես ստեղծվում է build-ի ժամանակ։
ISR (Incremental Static Regeneration) — ստատիկ էջերը կարող են վերագեներացվել՝ ըստ սահմանված ռազմավարության։
Այս մոտեցումներից ոչ մեկը բոլոր դեպքերում լավագույնը չէ։
Client-Side Rendering
CSR-ը կարող է հարմար լինել ինտերակտիվ dashboard-ների և հավելվածների համար, որտեղ օգտատերն արդեն մուտք է գործել և աշխատում է տվյալների հետ։
Սակայն եթե հանրային էջի ամբողջ հիմնական բովանդակությունը կախված է JavaScript-ի ներբեռնումից, կատարումից և API հարցումից, օգտատերը կարող է ավելի երկար սպասել մինչև օգտակար բովանդակություն տեսնելը։
Server-Side Rendering
SSR-ը թույլ է տալիս սերվերում ստեղծել HTML և այն ուղարկել բրաուզերին։ Սա կարող է բարելավել հիմնական բովանդակության ցուցադրումը, բայց ինքնին չի երաշխավորում արագ կայք։
Եթե սերվերը դանդաղ է պատասխանում, տվյալների հարցումները երկար են տևում կամ էջի կառուցման համար չափազանց շատ աշխատանք է պահանջվում, առաջին պատասխանը նույնպես կարող է ուշանալ։
Next.js-ի App Router-ը
Next.js-ի App Router-ում Server Components-ը թույլ են տալիս որոշ բաղադրիչներ մշակել սերվերում՝ առանց դրանց կոդը հաճախորդի JavaScript bundle-ում ներառելու։
Օրինակ՝
// app/products/page.tsx
import { getProducts } from "@/lib/products";
import { ProductList } from "@/components/product-list";
export default async function ProductsPage() {
const products = await getProducts();
return (
<main>
<h1>Products</h1>
<ProductList products={products} />
</main>
);
}Այս օրինակում էջի բաղադրիչը կարող է տվյալներ ստանալ սերվերում։ Եթե ProductList-ը նույնպես Server Component է, դրա կոդը հաճախորդի JavaScript-ի մաս չի դառնա։
Սակայն եթե այդ ցուցակին անհրաժեշտ են զտումներ, զամբյուղի հետ անմիջական փոխազդեցություն կամ այլ browser-side գործողություններ, որոշ հատվածներ կարող են պահանջել Client Components։
Այստեղ կարևոր է ճիշտ սահմանազատումը։ Չարժե ամբողջ էջը դարձնել Client Component միայն այն պատճառով, որ դրա մի փոքր հատվածը ինտերակտիվ է։
Լավ մոտեցում է ինտերակտիվությունը պահել այնտեղ, որտեղ այն իսկապես անհրաժեշտ է։
Մյուս կողմից՝ Server Components-ը նույնպես անվճար արագագործություն չեն ապահովում։ Տվյալների հաջորդական հարցումները, դանդաղ backend-ը և սխալ cache ռազմավարությունը կարող են վատացնել արդյունքը։
4. Նկարները, տառատեսակները և ցանցային հարցումները
Հաճախ ծրագրավորողները մեծ ուշադրություն են դարձնում JavaScript-ին, բայց անտեսում են այն ռեսուրսները, որոնք կարող են զգալիորեն ազդել էջի բեռնման վրա։
Նկարների օպտիմիզացիա
Պատկերացնենք՝ էջի վերևում ունենք մեծ hero նկար, որը զբաղեցնում է էկրանի հիմնական հատվածը։
Եթե այդ նկարը չափազանց մեծ է, օգտագործում է ոչ արդյունավետ ձևաչափ կամ ուշ է ներբեռնվում, էջի հիմնական բովանդակությունը նույնպես կարող է ուշ ցուցադրվել։
Next.js-ում կարելի է օգտագործել next/image-ը՝ չափերի, հարմար ձևաչափերի և բեռնման ռազմավարության կառավարման համար։
import Image from "next/image";
export function Hero() {
return (
<section>
<Image
src="/images/hero.webp"
alt="Product dashboard"
width={1200}
height={700}
priority
/>
</section>
);
}Այստեղ priority-ը նպատակահարմար է միայն այն նկարի համար, որը կարևոր է սկզբնական ցուցադրման ժամանակ, օրինակ՝ էջի հիմնական hero նկարը։ Այն պետք չէ կիրառել բոլոր նկարների համար։
Մյուս կարևոր կանոններն են՝
Օգտագործել նկարին համապատասխան չափեր։
Ընտրել արդյունավետ ձևաչափեր, օրինակ՝ WebP կամ AVIF, երբ դրանք նպատակահարմար են։
Ստորին հատվածներում գտնվող նկարները սովորաբար բեռնել lazy loading-ով։
Նշել նկարի չափերը, որպեսզի բրաուզերը կարողանա նախապես տեղ հատկացնել դրա համար։
Տառատեսակներ
Արտաքին տառատեսակների ֆայլերը նույնպես կարող են ուշացնել տեքստի ցուցադրումը կամ առաջացնել տառատեսակի տեսանելի փոփոխություն։
Արժե բեռնել միայն անհրաժեշտ քաշերն ու նիշերի հավաքածուները և խուսափել բազմաթիվ տառատեսակային ֆայլեր առանց պատճառի ներբեռնելուց։
Next.js-ի next/font-ը կարող է օգնել կառավարել տառատեսակների բեռնումը և դրանք տեղային ռեսուրսների միջոցով մատուցել։
Ցանցային հարցումներ
Մեկ այլ տարածված խնդիր է API հարցումների սխալ կազմակերպումը։
Օրինակ՝ եթե էջը նախ ստանում է օգտատիրոջ տվյալները, հետո միայն դրանց հիման վրա հարցում է ուղարկում պատվերների համար, հարցումները կարող են կատարվել հաջորդաբար, նույնիսկ երբ դրանք հնարավոր էր կատարել զուգահեռ։
const [user, orders] = await Promise.all([
getUser(),
getOrders(),
]);Այս օրինակը ճիշտ է այն դեպքում, երբ երկու հարցումները միմյանցից անկախ են։ Եթե երկրորդ հարցումը պահանջում է առաջինի արդյունքը, դրանք զուգահեռ կատարել հնարավոր չէ առանց տվյալների հոսքը փոխելու։
Պետք է նաև զգույշ լինել Promise.all()-ի հետ․ եթե հարցումներից մեկը ձախողվի, ամբողջ Promise.all()-ը կձախողվի։ Եթե հարցումները պետք է մշակվեն անկախ, կարելի է դիտարկել Promise.allSettled()-ը կամ յուրաքանչյուր հարցման համար առանձին սխալների կառավարումը։
Performance-ի տեսանկյունից հարցումների քանակը պարզապես նվազեցնելը բավարար չէ։ Կարևոր են նաև դրանց տևողությունը, հաջորդականությունը, cache-ը և վերադարձվող տվյալների ծավալը։
5. Core Web Vitals․ ինչպե՞ս չափել օգտատիրոջ փորձառությունը
Եթե ուզում ենք բարելավել կայքի արագագործությունը, պետք է հասկանանք՝ ինչ ենք չափում։
Google-ի Core Web Vitals-ը ներառում է երեք հիմնական չափանիշ։
ՉափանիշԻ՞նչ է չափումԼավ արդյունքի շեմLCP (Largest Contentful Paint)Հիմնական բովանդակության ամենամեծ տարրի ցուցադրման ժամանակը≤ 2.5 վայրկյանINP (Interaction to Next Paint)Օգտատիրոջ փոխազդեցություններին էջի արձագանքելու արագությունը≤ 200 մվCLS (Cumulative Layout Shift)Էջի դասավորության անսպասելի տեղաշարժերը≤ 0.1
Այս շեմերը գնահատվում են իրական օգտատերերի տվյալների 75-րդ պերսենտիլի հիման վրա՝ առանձին բջջային և desktop սարքերի համար։
LCP․ ե՞րբ է ցուցադրվում հիմնական բովանդակությունը
LCP-ի վրա կարող են ազդել սերվերի պատասխանի ժամանակը, հիմնական նկարի ներբեռնումը, render-blocking ռեսուրսները և այլ գործոններ։
Եթե LCP-ն վատ է, պետք է պարզել՝ խնդիրը սերվերի պատասխանի՞ մեջ է, նկարի ներբեռնմա՞ն, թե՞ բրաուզերի կողմից դրա ցուցադրման։
INP․ արդյո՞ք էջը արագ է արձագանքում
Պատկերացնենք՝ օգտատերը սեղմում է ֆիլտրի կոճակը, բայց արդյունքը հայտնվում է ուշացումով։
Պատճառը կարող է լինել երկարատև JavaScript task-ը, ծանր հաշվարկը կամ մեծ թվով տարրերի միաժամանակյա թարմացումը։
Այս դեպքում միայն ցանցային արագությունն ավելացնելը չի լուծի խնդիրը։ Պետք է ուսումնասիրել բրաուզերի հիմնական thread-ի աշխատանքը և նվազեցնել փոխազդեցության ընթացքում կատարվող ծանր գործողությունները։
CLS․ ինչո՞ւ է էջը տեղաշարժվում բեռնման ընթացքում
Հավանաբար բոլորս հանդիպել ենք իրավիճակի, երբ փորձում ենք սեղմել կոճակը, բայց դրա փոխարեն սեղմում ենք մեկ այլ տարր, քանի որ էջի դասավորությունը հանկարծ փոխվել է։
Սա կարող է տեղի ունենալ, երբ նկարների չափերը սահմանված չեն, ուշ բեռնվող բովանդակությունը տեղ է զբաղեցնում կամ էջի վերևում դինամիկ տարրեր են հայտնվում։
Նկարների չափերը նախապես սահմանելը, բովանդակության համար անհրաժեշտ տարածքը պահելը և ինտերֆեյսի կայուն կառուցումը կարող են օգնել նվազեցնել CLS-ը։
Այս չափանիշները կարելի է ուսումնասիրել PageSpeed Insights-ի միջոցով։ Իսկ Chrome DevTools-ը կարող է օգնել գտնել կոնկրետ խնդիրների պատճառները։
Կարևոր է տարբերել լաբորատոր չափումները իրական օգտատերերի տվյալներից։ Lighthouse-ի լավ գնահատականը օգտակար է, բայց այն ինքնին չի ապացուցում, որ բոլոր օգտատերերի փորձառությունը լավն է։
6. Օպտիմիզացիայի ամենատարածված սխալները
Performance-ի բարելավման ճանապարհին ծրագրավորողները երբեմն կատարում են փոփոխություններ, որոնք ավելի շատ բարդություն են ավելացնում, քան իրական օգուտ տալիս։
Սխալ 1․ useMemo օգտագործել ամենուր
React-ում useMemo-ն կարող է օգնել խուսափել թանկ հաշվարկների կրկնությունից, երբ դրա պայմանները համապատասխանում են։
Բայց այն բոլոր փոփոխականների համար օգտագործելը պարտադիր չէ։
const fullName = `${firstName} ${lastName}`;Այսպիսի պարզ արժեքի համար useMemo ավելացնելը սովորաբար անհրաժեշտ չէ։
const fullName = useMemo(
() => `${firstName} ${lastName}`,
[firstName, lastName]
);Երկրորդ տարբերակը կոդն ավելի բարդ է դարձնում՝ առանց էական օգուտի։
Օպտիմիզացիան պետք է հիմնված լինի չափումների վրա։ Եթե հաշվարկը թանկ չէ կամ բաղադրիչը հաճախ չի վերամշակվում, memoization-ը կարող է չտալ նկատելի արդյունք։
Սխալ 2․ ամեն ինչ lazy loading անել
Lazy loading-ը օգտակար է, երբ ռեսուրսը կամ բաղադրիչը պետք չէ անմիջապես։
Բայց եթե էջի հիմնական բովանդակությունը կամ տեսանելի հատվածի կարևոր նկարը ուշ բեռնվի, դա կարող է վատացնել օգտատիրոջ փորձառությունը։
Պետք է հասկանալ՝ ինչն է անհրաժեշտ հենց սկզբում, և ինչը կարելի է բեռնել ավելի ուշ։
Սխալ 3․ cache-ը դիտարկել որպես կախարդական լուծում
Caching-ը կարող է զգալիորեն նվազեցնել կրկնվող հարցումների ժամանակը և սերվերի ծանրաբեռնվածությունը։ Սակայն սխալ cache ռազմավարությունը կարող է ցուցադրել հնացած տվյալներ կամ խնդիրներ առաջացնել տվյալների թարմացման ժամանակ։
Հատկապես Next.js-ում պետք է հասկանալ՝ ինչ տվյալներ են cache արվում, ինչ պայմաններով և երբ են դրանք թարմացվում։ Չարժե ենթադրել, որ բոլոր fetch() հարցումներն ինքնաբերաբար նույն կերպ են cache արվում՝ անկախ framework-ի տարբերակից և կազմաձևից։
Սխալ 4․ վստահել միայն Lighthouse-ի գնահատականին
Lighthouse-ի 100 միավորը հաճելի արդյունք է, բայց այն չպետք է դառնա միակ նպատակը։
Կարելի է ունենալ բարձր գնահատական թեստային միջավայրում, բայց իրական օգտատերերի մոտ հանդիպել դանդաղ backend-ի, ծանր սարքերի կամ բարդ օգտագործման սցենարների։
Ավելի ճիշտ է դիտարկել մի քանի աղբյուր՝ Lighthouse, Chrome DevTools, bundle analyzer և իրական օգտատերերի Core Web Vitals տվյալներ։
Սխալ 5․ օպտիմիզացնել առանց խնդիրը հասկանալու
Երբ էջը դանդաղ է, հեշտ է անմիջապես անցնել կոդը վերաշարադրելուն։ Բայց առանց չափումների հնարավոր է օպտիմիզացնել այն հատվածը, որն իրականում խնդիր չի առաջացնում։
Եթե հիմնական ուշացումը սերվերի պատասխանից է, React-ի render-ները նվազեցնելը կարող է գրեթե ոչինչ չփոխել։
Եթե խնդիրը մեծ նկարի ներբեռնումն է, JavaScript-ի bundle-ը փոքրացնելը կարող է չլուծել LCP-ի հիմնական խնդիրը։
Սկզբում չափում ենք, հետո գտնում պատճառը, հետո միայն փոխում կոդը։
7. Գործնական checklist՝ նախքան նախագիծը production ուղարկելը
Ահա այն հարցերը, որոնք արժե ստուգել իրական նախագծում։
Բեռնման արագություն
Արդյո՞ք սկզբնական էջը բեռնում է միայն անհրաժեշտ JavaScript-ը։
Արդյո՞ք մեծ գրադարանները ներմուծվում են միայն անհրաժեշտության դեպքում։
Արդյո՞ք հիմնական նկարը ճիշտ չափի և ձևաչափի է։
Արդյո՞ք սերվերի պատասխանը և API հարցումները բավարար արագ են։
Արդյո՞ք հնարավոր է անկախ հարցումները կատարել զուգահեռ։
React և Next.js
Արդյո՞ք Client Components-ն օգտագործվում են միայն այնտեղ, որտեղ անհրաժեշտ է ինտերակտիվություն։
Արդյո՞ք կան ավելորդ render-ներ կամ թանկ հաշվարկներ։
Արդյո՞ք տվյալների հարցումները կատարվում են արդյունավետ։
Արդյո՞ք cache ռազմավարությունը համապատասխանում է տվյալների թարմության պահանջներին։
Արդյո՞ք էջի կարևոր բովանդակությունը հասանելի է առանց ավելորդ client-side աշխատանքի։
Օգտատիրոջ փորձառություն
Արդյո՞ք LCP-ն համապատասխանում է նպատակային շեմին։
Արդյո՞ք INP-ն ընդունելի է իրական փոխազդեցությունների ժամանակ։
Արդյո՞ք CLS-ը ցածր է, և էջի դասավորությունը կայուն է։
Արդյո՞ք կայքը ստուգվել է բջջային սարքերում։
Արդյո՞ք performance-ը չափվել է production-ին մոտ պայմաններում։
Այս checklist-ը վերջնական երաշխիք չէ, բայց օգնում է համակարգված մոտեցում ձևավորել և բաց չթողնել հաճախ հանդիպող խնդիրները։
Եզրակացություն
Արագ կայք ստեղծելը մեկ տեխնոլոգիա ընտրելու կամ մի քանի օպտիմիզացիա կիրառելու հարց չէ։ Դա բազմաթիվ որոշումների արդյունք է՝ սկսած նախագծի ճարտարապետությունից մինչև նկարների բեռնումն ու բրաուզերի հիմնական thread-ի աշխատանքը։
React-ը, Next.js-ը և ժամանակակից գործիքները մեզ տալիս են բազմաթիվ հնարավորություններ, բայց դրանք ինքնաբերաբար արագ կայք չեն ստեղծում։ Ծրագրավորողը պետք է հասկանա՝ երբ է պետք սերվերային rendering, երբ է պետք client-side interactivity, ինչ տվյալներ պետք է cache անել և ինչն է իրականում դանդաղեցնում էջը։
Իմ կարծիքով՝ frontend developer-ի կարևոր հմտություններից մեկը ոչ թե պարզապես աշխատող կոդ գրելն է, այլ կարողանալը հասկանալ, թե ինչու է այդ կոդն աշխատում այսպես, ինչ գին ունի դրա աշխատանքը և ինչպես կարելի է բարելավել այն՝ առանց ավելորդ բարդություն ստեղծելու։
Լավ performance-ը պատահական արդյունք չէ։ Այն ճիշտ որոշումների, չափումների և շարունակական բարելավման արդյունք է։
Եվ ամենակարևորը՝ մի՛ օպտիմիզացրու միայն այն պատճառով, որ կարող ես։ Օպտիմիզացրու, երբ հասկանում ես խնդիրը, գիտես՝ ինչ արդյունք ես ակնկալում, և կարող ես չափել՝ արդյոք լուծումն իսկապես օգնեց։