11 שלב בניית היכולות

Performance ו-Core Web Vitals — מהיר = מקצועי

בפרק הזה הופכים את האתר ממה ש"נראה טוב" למה ש"נראה טוב ונטען מהר" — כי על מובייל ישראלי ב-4G איטי, אתר שנטען ב-5 שניות הוא אתר שאין לו משתמשים. תכירו את שלושת המדדים של Google שקובעים אם אתר נחשב איכותי — LCP (מתי התמונה הגדולה מופיעה), CLS (כמה הדף "קופץ" תוך כדי טעינה), ו-INP (כמה מהר האתר מגיב לקליק). תריצו Lighthouse בצורה נכונה (לא פעם אחת, אלא 3), תלמדו לפרש את התוצאה בלי להיכנס לפאניקה מ-"red scores", ותבינו אילו פיצ'רי CSS הם רוצחי performance שקטים — backdrop-filter על רקע גדול, will-change על כל אלמנט, box-shadow כבד, אנימציות שלא רצות על ה-GPU. תבנו critical CSS, תשתמשו ב-content-visibility: auto ו-contain: paint לדחיית rendering, תחליפו spinners ב-skeleton screens, ותטפלו בפונטים עבריים — מקור LCP גרוע #1 באתרי ישראל. בסוף הפרק יהיו לכם Performance Audit Prompt ו-Performance Fix Prompt שיגרמו ל-AI לא רק לכתוב קוד שעובד, אלא קוד שרץ.

מה יהיה לך בסוף הפרק הזה
מה תוכלו לעשות בסוף הפרק הזה
דרישות קדם
הפרויקט שלך

לאורך הקורס אתם בונים את היכולת להפוך אתר גנרי שAI בנה לאתר שנראה כמו עבודת סטודיו — ה-capstone בפרק 13. עד כה: פרקים 1-2 (זיהוי גנריות + premium anatomy), פרק 3 (פלטת צבעים + design tokens), פרק 4 (טיפוגרפיה, כולל font-display), פרק 5 (Layout + 8px grid), פרק 6 (Modern CSS — Container Queries, :has()), פרקים 7-8 (Scroll-driven + View Transitions), פרק 9 (Glassmorphism + backdrop-filter), פרק 10 (Responsive + <picture> + srcset + width/height). בפרק הזה (11) — לוקחים את כל זה ומוסיפים את השכבה שעושה את ההבדל בין "נראה טוב" ל-"נראה טוב ונטען תוך 2 שניות": Performance ו-Core Web Vitals. זו לא שכבה דקורטיבית — זה תנאי סף לקידום אורגני (Google מתגמל אתרים מהירים ב-search rankings), לשימור משתמשים (מובייל ב-4G עוזב אחרי 3 שניות), ולחוויה מקצועית. בפרק הבא (12 — כלי עיצוב אופציונליים: Figma, Google Stitch, MCP) תכירו כלים שיכולים להאיץ את ה-workflow שלכם, אבל עם הבנה ברורה שהידע שבניתם בפרקים 1-11 (כולל פרק ה-Performance הזה) הוא מה שקובע את האיכות — הכלים הם אופציונליים, האופטימיזציה היא לא.

מילון מונחים — 16 מושגים מרכזיים בפרק
מונח (English)תרגוםהגדרה בשורה אחת
Core Web Vitalsאותות ליבת-ה-Web3 מדדי ביצועים רשמיים של Google שמשפיעים על דירוג SEO: LCP, CLS, INP
LCP (Largest Contentful Paint)הצגת האלמנט הגדולהזמן עד שהאלמנט הגדול ביותר ב-viewport (בד"כ תמונה או כותרת) מופיע; יעד פחות מ-2.5 שניות
CLS (Cumulative Layout Shift)הזזת Layout מצטברתכמה Layout "קופץ" תוך טעינה (0 = מושלם, 0.1 = גבול המותר, מעל 0.25 = גרוע)
INP (Interaction to Next Paint)תגובה לאינטראקציההזמן בין קליק/הקשה של המשתמש לבין התגובה הוויזואלית הבאה (יעד פחות מ-200ms)
FCP (First Contentful Paint)הצגת תוכן ראשוןמתי משהו — כל דבר — מופיע על המסך (יעד פחות מ-1.8 שניות)
TTFB (Time To First Byte)זמן עד לבייט ראשוןכמה זמן השרת לוקח לשלוח את ה-byte הראשון של התגובה (יעד פחות מ-800ms)
LighthouseLighthouseכלי חינמי של Google ב-Chrome DevTools שמריץ audit ביצועים ומחזיר score 0-100
PageSpeed Insightsתובנות מהירות דףגרסת ענן של Lighthouse ב-pagespeed.web.dev + נתוני משתמשים אמיתיים (CrUX)
Field Dataנתוני שטחמדידות מ-Chrome של משתמשים אמיתיים ב-28 הימים האחרונים (CrUX) — המציאות
Lab Dataנתוני מעבדהמדידה סינתטית (Lighthouse) על מכונה מדומה — קבועה אבל לא בהכרח משקפת את המשתמשים
Lazy Loadingטעינה עצלהדחיית טעינת תמונה/iframe עד שהמשתמש מתקרב אליו בגלילה — loading="lazy"
content-visibility: autoשקיפות-תוכן אוטומטיתProperty ב-CSS שגורמת לדפדפן לדלג על rendering של אלמנטים מחוץ ל-viewport
contain: paintהגבלת paintProperty שמבטיחה לדפדפן שאלמנט לא "יצבע מחוץ לקווים" — משפר זמן render
will-changeיעבור שינוירמז לדפדפן שאלמנט עומד להשתנות — מעביר אותו ל-GPU layer; שימוש זהיר בלבד
Critical CSSCSS קריטיה-CSS המינימלי הדרוש להצגת ה-above-the-fold — מוזרק inline ב-<head> (יעד < 14KB)
Render-Blocking Resourceמשאב חוסם-renderקובץ (CSS, JS, font) שהדפדפן חייב לטעון לפני שהוא יכול להציג את הדף — מעכב FCP ו-LCP
מתחיל 8 דקות חינם מושג

11.1 למה Performance = מקצועיות — והמציאות של 4G ישראלי

יש בישראל מיתוס של "בכל מקום יש 5G עם fiber". זה לא נכון. המציאות של הגולש הישראלי הממוצע, לפי נתוני CrUX (Chrome User Experience Report) של Google: 60-70% mobile traffic (כבר ראיתם את זה בפרק 10), מתוכם 35-50% על 4G אמיתי (לא 5G, לא WiFi ביתי), עם latency ממוצע של 60-110ms ו-bandwidth של 5-15 Mbps בתנאי עומס (ערב בתל-אביב, שבת ברעננה, פיקוק עירוני). זה אומר: תמונה של 2MB שאתם רואים נטענת תוך 0.3 שניות ב-WiFi שלכם — נטענת תוך 1.6-3.5 שניות אצל המשתמש האמיתי.

המסקנה: לבדוק performance רק ב-"Desktop + Fast 3G" של DevTools זה לא performance audit אמיתי — זה אשליה. הבדיקה האמיתית: Lighthouse ב-Mobile mode, עם CPU throttling של 4x, רשת 4G. זו המציאות שבה רוב המשתמשים שלכם חיים.

נתוני Performance ומשתמשים (אומדן 2025-2026, דורש אימות לפרויקט ספציפי)

נתוני Google רשמיים ב-web.dev/vitals. נתוני 4G הישראלי משתנים לפי מיקום, שעה, מפעיל רשת, ועומס. הדרך היחידה לדעת את הערך שלכם: Search Console של Google → Experience → Core Web Vitals.

למה Google מתגמל אתרים מהירים

Google לא מתגמל אתרים מהירים מ"טוב-לב". הם מתגמלים אותם כי משתמשים אוהבים אותם, וזה מה ש-Google צריכה למכור: חוויית חיפוש טובה. אתר שנטען מהר → משתמש נשאר בו יותר → מצליח למצוא את מה שחיפש → חוזר ל-Google יותר. מעגל חיובי.

המשמעות המעשית ל-Vibe Coder: אם האתר שלכם מתחרה עם 10 אחרים על אותה keyword, וכולם סיפקו את אותו תוכן — ה-מהיר ביותר יעלה בדירוג. פעם זה היה "content is king". היום זה "content + performance is king". מי שיש לו רק את ה-content, מפסיד.

Do-Now: בדקו את ה-Core Web Vitals שלכם ב-Search Console 4 דקות

אם יש לכם אתר שמחובר ל-Google Search Console: לכו ל-Experience → Core Web Vitals. רשמו:

אם אין לכם Search Console — הקימו אותו עכשיו (חינם, 10 דקות). אם האתר חדש ואין נתונים עדיין — השתמשו ב-PageSpeed Insights על ה-URL הראשי ורשמו את הציונים.

טעות נפוצה: "האתר טוען מהר אצלי" = "האתר מהיר"

אתם יושבים מול Mac Studio עם SSD, חיבור fiber 1Gbps, וב-Chrome DevTools הכל נראה מצוין. LCP של 0.8 שניות, CLS של 0, INP לא רלוונטי כי לא אינטראקטיביים. אתם חוגגים ו-deploy. אבל המשתמש האמיתי — הילד בן ה-16 שגולש באוטובוס עם Samsung A52, 4G של פרטנר — מקבל LCP של 4.8 שניות. זו לא "בעיה שלו". זו התוצאה שלכם על המכשיר שלו. מה לעשות במקום: תמיד להריץ Lighthouse ב-Mobile mode עם throttling של 4x CPU + Slow 4G, תמיד לבדוק ב-PageSpeed Insights שמציג גם Field Data (מציאות) וגם Lab Data (מעבדה), ולפחות פעם בחודש להריץ את האתר על מכשיר אמיתי שקניתם מאיביי לפני 3 שנים.

מתחיל 6 דקות חינם מושג

11.2 Core Web Vitals — 3 המדדים של Google בשפה פשוטה

Core Web Vitals הוא שם מותג ש-Google נתנה לשלושה מדדים רשמיים שמשפיעים על דירוג ה-SEO. הם נבחרו כי הם מה שהמשתמש מרגיש, לא כי הם קלים למדידה. שלושתם ביחד מכסים את שלושת השלבים של חוויה: טעינה, יציבות, אינטראקטיביות.

מדדמה הוא מודדהשאלה שהוא עונהיעד Goodיעד Poor
LCP
Largest Contentful Paint
זמן הצגת האלמנט הגדול ביותר ב-viewport "מתי המשתמש רואה את הדבר החשוב?" < 2.5 שניות > 4.0 שניות
CLS
Cumulative Layout Shift
כמה דברים קפצו תוך כדי טעינה "כמה יציב המסך בזמן שנטען?" < 0.1 > 0.25
INP
Interaction to Next Paint
זמן התגובה הכי גרוע לאינטראקציה "כמה מהר האתר מגיב ללחיצה?" < 200ms > 500ms

75th percentile — הכלל שצריך להבין

Google לא מסתכל על הממוצע של ה-Core Web Vitals — אלא על ה-75th percentile. המשמעות: 75% מהמשתמשים שלכם חייבים לקבל חוויה "Good". אם 74% מקבלים 2 שניות LCP אבל 26% מקבלים 5 שניות — אתם ב-"Needs Improvement". ה-25% הגרועים הם מה שקובע.

זה משפיע מעשית: לא מספיק ש-"ברוב המקרים זה עובד". צריך שזה יעבוד גם למשתמש עם Android ישן ב-4G עמוס. אם יש לכם תמונה של 3MB, ה-50% של המשתמשים שלכם ב-WiFi יראו אותה מהר, אבל ה-25% על 4G — יראו LCP גרוע. ואז האתר שלכם "Poor" ב-Google, גם אם ב-Lighthouse שלכם הוא מצוין.

טיפ זהב: "Good / Needs Improvement / Poor"

Google מחלק כל מדד ל-3 קבוצות: Good (ירוק, מעודד), Needs Improvement (כתום, משתפר), Poor (אדום, מעניש). היעד המעשי: להיות ב-Good על 3 המדדים. זה לא בהכרח אומר להגיע ל-Lighthouse 100. Lighthouse 75 יכול להיות "Good" על 3 CWV, וזה מה שמשנה ל-Google. אל תתרכזו במספר הגדול — תתרכזו ב-3 המדדים הספציפיים.

מה לא נכלל ב-Core Web Vitals

להשלמת התמונה — יש מדדים שהיו פעם או מומלצים, אבל לא נכללים ב-Core Web Vitals הרשמי:

Do-Now: הריצו PageSpeed Insights על האתר 3 דקות

פתחו pagespeed.web.dev. הכניסו את ה-URL של האתר שלכם. המתינו 20-30 שניות. רשמו:

אם אין "Field Data" למעלה — זה אומר שאין מספיק תנועה אמיתית ל-CrUX. במקרה כזה, רק ה-Lab Data (Lighthouse) רלוונטי. זה לא שבר — פשוט פחות מדויק.

בינוני 12 דקות חינם ניתוח

11.3 LCP — Largest Contentful Paint (יעד < 2.5 שניות)

LCP מודד את הזמן שחלף מהרגע שהמשתמש "נחת" על הדף (request התחיל) ועד שהאלמנט הגדול ביותר ב-viewport הופיע. ב-90% מהאתרים, האלמנט הזה הוא או תמונת ה-hero, או כותרת ה-h1, או background image של hero section. זה האלמנט שאומר למשתמש "הדף נטען, התוכן מוכן".

מה גורם ל-LCP גרוע — 4 הגורמים הנפוצים ביותר

  1. תמונת hero כבדה מדי. JPEG של 1.8MB שאפשר להיות 120KB ב-AVIF. זו הסיבה #1 באתרי ישראל.
  2. פונט עברי שחוסם render. Heebo עם 9 משקלים = 450KB. עד שהפונט נטען, הדפדפן לא מציג את הכותרת (אם font-display: block) — וה-LCP נדחה. זו סיבה #2 באתרי ישראל.
  3. Lazy loading על ה-hero image. הטעות שדיברנו עליה בפרק 10 — loading="lazy" על תמונה שמופיעה במיקום הראשון.
  4. Render-blocking CSS או JS. קובץ CSS של 300KB נטען סינכרונית ב-<head>, חוסם את הכל.

איך מוצאים מה ה-LCP element של הדף שלכם

Chrome DevTools → Performance tab → Record → רענן את הדף → Stop. בתצוגת התוצאות תראו קו בציר הזמן עם "LCP". הקליקו עליו. בפינה הימנית התחתונה ("Related Node") תראו איזה אלמנט ספציפי היה ה-LCP. רוב הסיכויים — תמונה או כותרת.

דרך מהירה יותר: Lighthouse → Performance → Largest Contentful Paint → "View Trace" או לחיצה על ה-item. הוא יראה בדיוק איזה אלמנט.

איך מתקנים LCP — 5 אופטימיזציות בסדר חשיבות

  1. תמונה מאופטמת + preload. הקטינו את ה-hero image ל-AVIF + WebP (מפרק 10). הוסיפו <link rel="preload" as="image"> ב-<head>:
    <link rel="preload"
        as="image"
        href="hero-1200.avif"
        type="image/avif"
        imagesrcset="hero-400.avif 400w, hero-800.avif 800w, hero-1200.avif 1200w"
        imagesizes="(min-width: 1024px) 1200px, 100vw"
        fetchpriority="high"
    />
  2. fetchpriority="high" על ה-img tag. גם אם אין preload — <img fetchpriority="high" loading="eager"> אומר לדפדפן "זה החשוב".
  3. Font loading עם swap. font-display: swap אומר לדפדפן "תציג fallback מיד, תחליף כשהפונט נטען". כך ה-h1 מופיע תוך 100ms עם Arial, ואז מתחלף ל-Heebo — אבל LCP נרשם על ה-Arial, והוא מהיר.
  4. CDN לתמונות. Cloudflare Images, Cloudinary, Vercel Image — כולם מחזירים את התמונה הנכונה לגודל המסך, מהשרת הקרוב ביותר ל-user.
  5. הסרת render-blocking resources. CSS קריטי inline, שאר ה-CSS בסוף ה-body או עם media="print" onload="this.media='all'" (טריק ידוע).
מסגרת החלטה: מה לבדוק כש-LCP גרוע
ה-LCP element שלכם הוא...הבעיה הסבירההתיקון הראשון לנסות
תמונה (hero, product)משקל גדול / lazy loading / ללא preloadAVIF + fetchpriority="high" + <link rel="preload">
Heading (h1)פונט לא נטען מיד / font-display: blockfont-display: swap + preload של font
Background imageלא ניתן ל-preload בקלותלהעביר ל-<img> עם position: absolute, ואז preload
Video / iframeAutoplay כבדPoster image כ-fallback + preload="none" על video
Text block (long paragraph)Render-blocking CSS שוחק FCPCritical CSS inline + Font swap
Do-Now: מצאו את ה-LCP element 5 דקות

פתחו את האתר שלכם. DevTools → Lighthouse → Mobile → Performance → Generate Report. כשסיים, לכו ל-"Largest Contentful Paint" → לחצו על ה-item. רשמו:

אם LCP מעל 2.5 שניות — המדד הזה הוא ה-priority הראשון לתיקון. בתרגיל 2 של הפרק תתקנו אותו.

בינוני 10 דקות חינם ניתוח

11.4 CLS — Cumulative Layout Shift (יעד < 0.1)

CLS מודד כמה "הדף קופץ" תוך כדי טעינה. זה המדד הכי פחות מוכר אבל הכי מרגיז למשתמש: אתם עומדים לקרוא טקסט, ופתאום תמונה נטענת למעלה ומזיזה את כל התוכן למטה — ואתם לוחצים על הדבר הלא-נכון. CLS של 0 = מושלם. CLS של 0.1 = גבול "Good". מעל 0.25 = "Poor".

המספר מחושב כמכפלה של impact fraction (כמה שטח המסך השתנה) × distance fraction (כמה רחוק זז). לא חשוב להבין את הנוסחה — חשוב להבין את הסיבות.

5 הסיבות הנפוצות ל-CLS גרוע

  1. תמונות בלי width ו-height attributes. הדפדפן לא יודע איזה שטח להקצות. התמונה נטענת, התוכן קופץ למטה. הסיבה #1 בישראל.
  2. פונט עם swap שגורם ל-FOUT (Flash Of Unstyled Text). הפונט fallback רוחב שונה מהפונט האמיתי — הטקסט "זורם" אחרת כשהפונט מתחלף. תיקון: size-adjust ב-@font-face.
  3. Ads או embeds בלי מידות קבועות. iframe של YouTube / מודעות / טוויטר embed — כולם יכולים "להתרחב" אחרי שה-content שלהם נטען. תיקון: aspect-ratio או height מפורש.
  4. Cookie banner שמופיע בראש הדף אחרי שהתוכן כבר נטען. דוחף הכל למטה. תיקון: position: fixed בתחתית, או height reserved בראש.
  5. תוכן שמוזרק דינמית (fetch/AJAX) בתוך תוכן קיים. תגובות שנטענות, טופסי newsletter שמופיעים. תיקון: skeleton screens עם height קבוע שמוחלפים בתוכן.

איך מתקנים CLS — 3 תיקונים שמחסלים 80% מהבעיות

1. תמיד width ו-height על כל תמונה. לא בתור ציון גודל התצוגה — אלא בתור יחס. הדפדפן משתמש בהם לחשב aspect-ratio ולהקצות שטח לפני שהתמונה נטענת.

<!-- רע — גורם CLS -->
<img src="product.jpg" alt="מוצר" />

<!-- טוב — מונע CLS -->
<img
    src="product.jpg"
    alt="מוצר"
    width="800"
    height="600"
/>

/* CSS — ה-aspect-ratio נשמר גם כשהתמונה responsive */
img {
    width: 100%;
    height: auto;
    /* aspect-ratio נגזר מ-attributes אוטומטית */
}

2. Reserve space לכל embed/iframe. שימוש ב-aspect-ratio:

.video-embed {
    width: 100%;
    aspect-ratio: 16 / 9;  /* מקצה שטח לפני הטעינה */
}

.video-embed iframe {
    width: 100%;
    height: 100%;
    border: 0;
}

3. Font metric override ב-@font-face. טיפ מתקדם ממש: שולט ב-fallback font להראות זהה למידות של הפונט האמיתי. נקרא "adjusted font fallback":

/* Fallback font עם metrics מותאמים ל-Heebo */
@font-face {
    font-family: 'Heebo Fallback';
    src: local('Arial');
    size-adjust: 107%;      /* מתאים רוחב */
    ascent-override: 90%;   /* מתאים גובה שורה */
    descent-override: 25%;
    line-gap-override: 0%;
}

body {
    font-family: 'Heebo', 'Heebo Fallback', sans-serif;
}

התוצאה: הטקסט הראשוני (עם Arial) יתפוס בדיוק את אותו שטח כמו שהטקסט הסופי (עם Heebo) יתפוס. לא יהיה "קפיצה" כשהפונט מתחלף.

טעות נפוצה: "ה-image במלוא הרוחב — למה לי width?"

כשהתמונה היא width: 100% ב-CSS, מפתחים/AI מניחים שה-HTML attributes width ו-height מיותרים. טעות. ה-attributes האלה נותנים לדפדפן את היחס (aspect ratio) של התמונה לפני שהוא מתחיל להוריד אותה. בלעדיהם, הדפדפן מקצה 0×0, התמונה נטענת, ה-aspect ratio מתחשב, וכל הדף קופץ למטה — CLS של 0.15+. מה לעשות במקום: תמיד להוסיף width ו-height attributes שתואמים את יחס המימדים של התמונה (800×600, 1200×800 וכו'), גם אם ב-CSS התמונה תהיה 100% רוחב. זה מספיק.

Do-Now: חיפוש תמונות בלי width/height 4 דקות

פתחו את קובץ ה-HTML הראשי. Ctrl+F ו-חפשו <img. עברו על כל tag. רשמו:

כל תמונה שחסר לה width או height — candidate לגרום CLS. הוסיפו אותם. אם אתם לא יודעים את היחס — פתחו את התמונה ורשמו את המימדים בפיקסלים.

בינוני 10 דקות חינם ניתוח

11.5 INP — Interaction to Next Paint (יעד < 200ms)

INP החליף את FID רשמית במרץ 2024. ההבדל: FID מדד רק את ה-interaction הראשון; INP מודד את ה-interaction הכי גרוע לאורך ביקור המשתמש. זה מציאותי הרבה יותר — כי משתמש שלחץ 10 פעמים על כפתורים וכל אחד הגיב תוך 100ms חוץ מאחד שלקח 800ms — INP שלו = 800ms.

ל-INP יש מרכיבים: Input delay (כמה זמן ה-browser עסוק ולא יכול לענות), Processing time (כמה זמן ה-JS רץ בתגובה), ו-Presentation delay (כמה זמן לוקח לצייר את השינוי).

איפה זה קשור ל-CSS (כי אתם Vibe Coders, לא מפתחי JS)

INP נחשב "בעיית JavaScript" — וברוב המקרים הוא אכן כזה (JS כבד שחוסם את ה-main thread). אבל יש סיבות ל-INP גרוע שקשורות ישירות ל-CSS:

Rule of Thumb ל-CSS שרץ על GPU

אנימציות שרצות על ה-GPU (לא חוסמות את ה-main thread, לא גורמות reflow): רק transform ו-opacity. זה הכל.

/* רע — גורם reflow, INP גבוה */
.card {
    transition: width 0.3s, margin-top 0.3s;
}
.card:hover {
    width: 320px;
    margin-top: -10px;
}

/* טוב — GPU-accelerated, INP נמוך */
.card {
    transition: transform 0.3s;
}
.card:hover {
    transform: translateY(-10px) scale(1.02);
}

הטיפ הזה לבד — "רק transform ו-opacity באנימציות" — מחסל כ-60% מבעיות ה-INP ב-CSS.

מסגרת החלטה: איך לבחור property לאנימציה
רוצים לשנות...במקום...השתמשו ב...
מיקום (נע)top, left, margintransform: translate()
גודל (גדל/קטן)width, heighttransform: scale()
רוטציהrotation (ישן)transform: rotate()
העלמה/הופעהdisplay: noneopacity: 0 + visibility: hidden
שקיפותכל דבר אחרopacity (אחד הבודדים שבאמת GPU-accelerated)
צבע/borderעם transitionאפשר transition, אבל מוגבל — לא לאנימציות ארוכות
Do-Now: חיפוש אנימציות בעייתיות 4 דקות

פתחו קובץ CSS. חפשו transition: ו-@keyframes. עברו על כל אחד:

כל אנימציה בעייתית — רשמו את ה-selector. בתרגיל 3 תמירו אותן ל-transform/opacity.

מתחיל 12 דקות חינם כלי

11.6 Lighthouse — איך להריץ ומה המספרים אומרים

Lighthouse הוא הכלי הראשי לאודיט performance. הוא מובנה ב-Chrome DevTools (F12 → Lighthouse tab), הוא חינמי לגמרי, והוא נותן לכם ציון 0-100 על 5 קטגוריות: Performance, Accessibility, Best Practices, SEO, ו-PWA (לפעמים).

הריצה הנכונה — לא הריצה שעושים

  1. Incognito mode. Extensions של Chrome (uBlock, Grammarly) משפיעים על תוצאות. תמיד Lighthouse ב-Incognito.
  2. Device: Mobile (לא Desktop). זה מה ש-Google Search מסתכל עליו. Desktop הוא bonus אחרי שה-Mobile בסדר.
  3. Categories: רק Performance לבדיקה ראשונית. כל קטגוריה מאריכה את הזמן; מתחילים ב-Performance, אחרי שזה טוב עוברים לשאר.
  4. Mode: Navigation (default). יש גם "Timespan" ו-"Snapshot", אבל עבור performance הכלל הוא Navigation.
  5. הרצה 3-5 פעמים ולקחת את המדיאן. תוצאות Lighthouse יש להן שונות של 5-15 נקודות בין הרצות. הרצה אחת = מטעה. 3 הרצות ולקחת את האמצעית — אמין הרבה יותר.

איך לפרש את ה-Performance score

Rangeצבעמשמעותמה לעשות
90-100ירוקExcellentשמרו, ואל תעשו regressions
50-89כתוםNeeds improvementתתרכזו ב-top 3 issues לפי ה-"Opportunities"
0-49אדוםPoorהפרויקט דורש עבודה רצינית — לפחות LCP, CLS, ו-JS bundle size

ה-5 מדדים שמרכיבים את ה-Performance score

ה-score הוא ממוצע משוקלל של 5 מדדים:

המשמעות: TBT + LCP = 55% מהציון. אם רוצים לשפר performance — מתחילים שם.

Opportunities ו-Diagnostics — איפה הזהב

אחרי ה-score, Lighthouse מציג 2 מדורים חשובים:

המלצת זהב: לטפל ב-Opportunities לפי הסדר, מהחיסכון הגדול ביותר. כל טיפול אחד מחסן 0.5-2 שניות בדר"כ.

טיפ מתקדם: בדיקה עם throttling מותאם

Lighthouse Mobile משתמש ב-"Slow 4G" + 4x CPU throttling. זה טוב לסטנדרט של Google. אבל אם תרצו לבדוק את החוויה של משתמש על מכשיר ישן ברשת גרועה: לכו ל-Network tab → Throttling → "Slow 3G", ואז ב-Performance tab → CPU → 6x slowdown. הריצו עמוד. תקבלו חוויה של משתמש עם Samsung A10 באוטובוס צפוף. אם עובר שם — עובר בכל מקום.

Do-Now: Lighthouse הרצה נכונה 6 דקות

פתחו Chrome, ואז Incognito mode. נווטו לאתר שלכם. F12 → Lighthouse. בחרו: Mobile + Performance only + Navigation. הריצו 3 פעמים. רשמו את 3 ה-scores:

המדיאן זה ה-score האמיתי שלכם. אל תסתמכו על ההרצה הטובה ביותר — Google הוא המדיאן ברוב המקרים.

מתחיל 6 דקות חינם כלי

11.7 PageSpeed Insights — Field Data vs Lab Data

PageSpeed Insights (PSI) ב-pagespeed.web.dev הוא הכלי הרשמי של Google לבדיקת ביצועים. מה שמבדיל אותו מ-Lighthouse המקומי: הוא רץ מהשרת של Google ומציג שני מקורות נתונים — Field Data ו-Lab Data. הבנת ההבדל קריטית.

Field Data (CrUX)Lab Data (Lighthouse)
מקור:משתמשי Chrome אמיתיים ב-28 ימים אחרוניםהרצה סינתטית של Google
מה רואים:75th percentile של משתמשים אמיתייםהרצה אחת במכונת בדיקה
יתרון:המציאות — זה מה ש-Google Search מסתכל עליוdeterministic — תוצאות יציבות לפחות
חיסרון:דורש תנועה מינימלית (אלפי משתמשים בחודש)עלול לא לשקף את החוויה של משתמשים אמיתיים
מתי להסתכל:אתר ב-production עם תנועהאתר חדש / staging / לוודא שלא נשבר משהו

מה קורה כשאין Field Data

בפתיחת PSI, אם האתר שלכם קטן או חדש — תראו "Real-user experience data is unavailable". זה בסדר. זה אומר: המשתמשים שלכם פחות מהמספר הנדרש ל-CrUX. במקרה הזה, הסתמכו רק על Lab Data (שזה הדבר היחיד שיש), ובנוסף — השתמשו ב-web-vitals npm package כדי לאסוף נתונים משלכם.

<!-- קוד מינימלי לאיסוף Core Web Vitals מדפדפני משתמשים -->
<script type="module">
    import { onCLS, onINP, onLCP } from 'https://unpkg.com/web-vitals@4?module';

    function sendToAnalytics(metric) {
        // שלחו ל-Google Analytics, Plausible, או endpoint שלכם
        console.log(metric.name, metric.value);
    }

    onCLS(sendToAnalytics);
    onINP(sendToAnalytics);
    onLCP(sendToAnalytics);
</script>

פער בין Field ל-Lab — מה זה אומר

Do-Now: השוואת Field מול Lab 3 דקות

ב-PSI (pagespeed.web.dev), הריצו על ה-URL שלכם. אם יש Field Data — רשמו:

פער של פחות מ-20% — סביר. מעל 50% — לחפש מה שונה בתנאי המשתמשים שלכם (geography, device mix, network).

בינוני 12 דקות חינם ניתוח

11.8 רוצחי Performance ב-CSS — מה להימנע ממנו

CSS נחשב "קל". זה לא נכון לגמרי. יש properties ודפוסים ב-CSS שהורגים performance שקטים — לא תראו אותם ב-JavaScript profiler, אבל תרגישו אותם ב-LCP ו-INP. הנה ה-8 הגדולים, לפי סדר חשיבות.

1. backdrop-filter על רקעים גדולים

בפרק 9 (Glassmorphism) למדתם backdrop-filter: blur(). הוא מדהים. הוא גם כבד. הדפדפן חייב לצייר את כל מה שמאחורי האלמנט, ואז להחיל blur על כל פיקסל. על אלמנט קטן (navbar, card קטן) — זה בסדר. על hero של 100vw × 70vh — זה קטסטרופה.

2. will-change על כל אלמנט

AI אוהב להוסיף will-change: transform על כל אלמנט עם hover animation. זה הפוך מאופטימיזציה. will-change אומר לדפדפן "תרים את האלמנט ל-GPU layer עצמאי". זה צורך זיכרון GPU. אם יש לכם 50 אלמנטים עם will-change, הדפדפן יוצר 50 layers, RAM של ה-GPU נגמר, ואז הכל מאט.

טעות נפוצה: will-change על כל אלמנט — זה הפוך מאופטימיזציה

Vibe Coders ש-"שמעו שזה מאיץ אנימציות" מוסיפים will-change: transform על כל .card, .button, .hero. זו טעות קריטית. will-change מאלץ את הדפדפן להקצות layer GPU קבוע לאלמנט — גם אם הוא לא מאונמטם כרגע. עם 50 אלמנטים כאלה, זיכרון ה-GPU נגמר, וכל האתר מאט (במיוחד על mobile). הכלל הנכון: will-change רק על אלמנט שבאמת עומד להשתנות בעוד רגע, ורק סביב האירוע. להסיר אותו אחרי. דוגמה: .card:hover { will-change: transform; } — מפעיל רק ב-hover, לא תמידית. או ב-JS: el.style.willChange = 'transform'; / doSomething(); / el.style.willChange = 'auto';. מה לעשות במקום של will-change קבוע: להשתמש ב-transform: translateZ(0) רק כשחייבים (זה "GPU hint" יותר עדין), או פשוט להסתמך על זה שהדפדפן אופטימלי בעצמו.

3. box-shadow מרובה שכבות מונפש

ב-premium design, אתם משתמשים ב-layered shadows (3-5 shadows יחד לעומק מציאותי). זה מצוין ויזואלית. אבל: transition: box-shadow 0.3s על hover של כל card — הדפדפן מצייר 3-5 shadows בכל frame. 60fps × 5 shadows = 300 paint operations לשנייה. אופציות:

4. אנימציה של width/height

כל שינוי של width, height, top, left, margin, padding — מפעיל reflow של כל הדף. reflow = דפדפן מחשב מחדש את ה-layout של כל האלמנטים. זה יקר. תחליף: transform: scale() ו-transform: translate() (ראו framework ב-section 11.5).

5. filter: blur() בזמן scroll

אפקט פופולרי: תמונה ברקע שעושה blur כשגוללים. בעיה: filter: blur() בזמן scroll מפעיל GPU work על כל פריים. ב-desktop זה בסדר; על mobile זה 5fps. תחליפים: להשתמש ב-backdrop-filter על overlay (קל יותר), או ל-pre-blur את התמונה ב-Photoshop/Squoosh ולאפשר אותה כ-background.

6. Gradients מונפשים (aurora background)

בפרק 9 ראיתם aurora backgrounds עם radial-gradients מונפשים. אפקט מדהים. אבל: gradient ב-CSS לא GPU-accelerated — כל frame מחשב אותו מחדש. פתרון: במקום background-position animation, השתמשו ב-transform: translate של pseudo-element עם gradient קבוע:

/* רע — animation של background-position, רץ על CPU */
.aurora {
    background: radial-gradient(circle at 20% 50%, #8b5cf6, transparent);
    animation: shift 10s infinite;
}
@keyframes shift {
    50% { background-position: 80% 50%; }
}

/* טוב — transform של pseudo-element, רץ על GPU */
.aurora {
    position: relative;
    overflow: hidden;
}
.aurora::before {
    content: "";
    position: absolute;
    inset: -20%;
    background: radial-gradient(circle, #8b5cf6, transparent 60%);
    animation: drift 10s infinite ease-in-out;
    will-change: transform;  /* כאן זה מוצדק — animation תמידית */
}
@keyframes drift {
    50% { transform: translate(20%, 10%) scale(1.2); }
}

7. :hover על elements גדולים עם transition

לדוגמה: .section:hover { background: #f0f0f0; transition: 0.5s; } על section שהוא 100vw רוחב. בכל זיז של עכבר, הדפדפן בודק אם לצייר section מחדש. לרוב לא מורגש, אבל על mobile שה-hover = touch start — זה כן.

8. פונטים שלא מוגדרים עם font-display: swap

זה נושא הפרק הבא (section 11.15), אבל מספיק להגיד: אם הפונט לא מוגדר עם swap, הטקסט לא מופיע עד שהפונט נטען — זה LCP גרוע. הסיבה #2 ל-LCP גבוה בישראל.

Do-Now: Audit של CSS Killers בקוד שלכם 5 דקות

פתחו קובץ CSS. חפשו כל אחד מהבאים:

כל אחד מאלה הוא candidate לתיקון. בתרגיל 3 תטפלו בכולם.

מתחיל 8 דקות חינם הקמה

11.9 Lazy Loading — תמונות, iframes, ו-content מתחת ל-fold

Lazy loading = "אל תטען את זה עד שהמשתמש מתקרב אליו". ב-2020 דרש JS (IntersectionObserver); ב-2026 זה native ב-HTML עם loading="lazy". Browser support ב-2026: 95%+ (Chrome, Edge, Firefox, Safari 15.4+).

מה לטעון lazy, ומה לא

אלמנטמיקוםLazy?
Hero imageAbove the foldלאloading="eager" fetchpriority="high"
Navigation logoAbove the foldלא
Product images ב-gridAbove/Below the foldהעליונות = eager; מהשלישית והלאה = lazy
Article body imagesBelow the foldכן — loading="lazy"
Footer imagesBelow the foldכן — loading="lazy"
YouTube embedכל מקוםכן — loading="lazy" על iframe (תמיד)
Map embedכל מקוםכן
Third-party widgets (social)כל מקוםכן

הסינטקס המלא

<!-- תמונה מתחת ל-fold -->
<img
    src="article-image.jpg"
    srcset="article-400.jpg 400w, article-800.jpg 800w"
    sizes="(min-width: 768px) 800px, 100vw"
    alt="תיאור"
    width="800"
    height="500"
    loading="lazy"
    decoding="async"
/>

<!-- iframe (YouTube, Map) — תמיד lazy -->
<iframe
    src="https://www.youtube.com/embed/xxx"
    loading="lazy"
    width="560"
    height="315"
    allowfullscreen
></iframe>

<!-- Hero (אל תסמנו lazy!) -->
<img
    src="hero-1200.webp"
    srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
    sizes="100vw"
    alt="תיאור"
    width="1200"
    height="800"
    loading="eager"
    fetchpriority="high"
/>

decoding="async" — ה-attribute ששכחו ממנו

decoding="async" אומר לדפדפן "תפענח את ה-image ב-background thread, לא ב-main thread". זה לא משנה הרבה ב-desktop, אבל ב-mobile עם CPU חלש זה משפר INP משמעותית. הוסיפו אותו לכל תמונה מלבד ה-hero (שם אפשר decoding="sync").

טעות נפוצה: loading="lazy" על תמונת hero — LCP נהרס

(חוזרים על זה כי זה הטעות השנייה-הכי-נפוצה של AI, אחרי will-change). AI בונה את ה-<img> של ה-hero, ומוסיף loading="lazy" כי "זה best practice". זה הפוך מ-best practice עבור hero. ה-hero הוא בדרך כלל ה-LCP element; אם הוא lazy, הדפדפן מחכה לו, ה-LCP מתעכב, והציון נופל מ-90 ל-55. מה לעשות במקום: תמיד loading="eager" + fetchpriority="high" על hero image, ו-<link rel="preload"> ב-<head> כחיזוק נוסף. Lazy loading הוא רק מתחת ל-fold.

Do-Now: רשימת תמונות ומיקומן 4 דקות

פתחו את עמוד הבית של האתר. ספרו כמה <img> יש בו. לכל אחד, רשמו:

בינוני 8 דקות חינם הקמה

11.10 content-visibility: auto — הדפדפן לא מרנדר מה שלא רואים

content-visibility: auto היא אחת הפיצ'רות הכי עוצמתיות של CSS המודרני שרוב ה-Vibe Coders לא מכירים. הרעיון פשוט: הדפדפן יכול לדלג על rendering של אלמנטים שנמצאים מחוץ ל-viewport. זה לא lazy loading של תמונות — זה lazy loading של layout + paint של sections שלמים.

איך זה עובד

.section {
    content-visibility: auto;
    contain-intrinsic-size: 0 800px;  /* החלקה ידנית של גובה משוער */
}

שני שורות. הדפדפן עושה:

מתי זה מועיל במיוחד

מה לא לעשות איתו

Browser support ב-2026

Chrome 85+, Edge 85+, Firefox 125+ (יחסית חדש, מ-2024), Safari 17.6+. בסה"כ 93%+ global. Fallback: הדפדפן הישן פשוט ירנדר הכל (בסדר — זה רק הפסד של אופטימיזציה, לא שבירה של פונקציונליות).

טיפ זהב: השילוב המנצח ל-Landing Page

Hero section — בלי content-visibility (הוא תמיד ב-viewport). כל section אחר — content-visibility: auto + contain-intrinsic-size: 0 600px (התאמה לגובה ממוצע). במבחן אמיתי על landing page של 8 sections: time-to-interactive ירד מ-3.2s ל-2.1s. זה שיפור של כמעט שנייה שלמה מ-2 שורות CSS.

מתקדם 7 דקות חינם הקמה

11.11 contain: paint — הגבלת rendering לאזור

contain הוא property שאומר לדפדפן "תנחש משהו על האלמנט הזה". יש 4 ערכים: size, layout, style, paint. רוב הזמן, contain: paint הוא מה שמעניין אותנו.

המשמעות: הדפדפן יכול להניח שהאלמנט לא "מצייר מחוץ לגבולות שלו". זה חותך את מחשבי ה-paint tree משמעותית.

.card {
    contain: paint;
    /* או משולב: */
    contain: layout paint;
}

מתי להשתמש

ההבדל בין contain: paint ל-content-visibility: auto

contain: paintcontent-visibility: auto
מה הוא עושה:חותך paint לאזור האלמנטדולג על render מלא כשמחוץ ל-viewport
השפעה:קטנה-בינונית, תמידיתגדולה, אבל רק מחוץ ל-viewport
מתי:Cards, widgets, אזורים מבודדיםSections גדולים בדף ארוך
Browser support:95%+93%+

שילוב: על section של blog post, אפשר לשים גם content-visibility: auto וגם contain: paint — הם משלימים, לא מחליפים.

מתקדם 8 דקות חינם מושג

11.12 will-change — רמז עוצמתי, שימוש זהיר

דיברנו עליו ב-section 11.8 ובאזהרה הקודמת. כאן מרחיבים: מתי כן להשתמש, מתי לא, והחלופות.

מה will-change באמת עושה

הוא אומר לדפדפן: "האלמנט הזה עומד להשתנות בקרוב, תכין את עצמך". הדפדפן בתגובה:

זה מדהים עבור אלמנטים שעומדים לעבור אנימציה ברגע הקרוב — מוחק latency של "הכנה". אבל אם זה לא קורה — בזבוז GPU memory.

הכלל המעשי

  1. כברירת-מחדל: אל תשתמשו. הדפדפן בעצמו יודע לאופטם אנימציות של transform ו-opacity.
  2. להשתמש רק אם ראיתם הוכחה ל-jank. פתחו DevTools → Performance. הקליטו אנימציה. אם יש "long tasks" או "frame drops" — שקלו will-change.
  3. אם בכל זאת צריך — להשתמש באופן ממוקד:
    /* טוב — על hover event, לזמן קצר */
    .button {
        transition: transform 0.3s;
    }
    .button:hover {
        will-change: transform;
        transform: scale(1.05);
    }
    
    /* רע — כל הזמן, בלי סיבה */
    .button {
        will-change: transform;
    }
  4. לכל היותר 3-5 אלמנטים בדף עם will-change קבוע. ולא כל card/button/link.

חלופה עדינה: transform: translateZ(0)

טריק ישן שעדיין עובד — transform: translateZ(0) גם מרים אלמנט ל-GPU layer, אבל בלי להצהיר על כוונה (פחות אגרסיבי). שימושי כשאתם באמת רוצים להבטיח GPU compositing בלי הטיה של הדפדפן לאופטים אגרסיביים.

בינוני 10 דקות חינם אסטרטגיה

11.13 Critical CSS — מה לטעון מיד, מה לדחות

Critical CSS = ה-CSS המינימלי הדרוש להציג את ה-above the fold של הדף. הרעיון: במקום לטעון CSS של 150KB סינכרונית (חוסם render ל-500ms), להזריק את ה-critical (14KB) ישירות ב-<head> עם <style> inline, ואת שאר ה-CSS לטעון async.

למה 14KB — מגבלה קסומה?

TCP slow start: החיבור הראשון של HTTP/2 ל-server שולח את ה-14KB הראשונים ב-round trip אחד. כל דבר מעל זה דורש round trip נוסף, שמוסיף 100-300ms. לכן אם ה-critical CSS שלכם מתחת ל-14KB, הוא מגיע בתוך ה-HTML הראשון, והדפדפן יכול להתחיל לצייר ברגע שה-HTML הגיע.

איך מחלצים critical CSS

  1. ידנית (רלוונטי לאתרים קטנים): פתחו את הדף. רשמו את כל ה-selectors שמופיעים ב-above the fold (hero, nav, logo, ה-h1). העתיקו רק את ה-CSS שלהם.
  2. אוטומטית (לאתרים גדולים): כלי כמו critical npm package, Penthouse, או service כמו CriticalCSS.com. הם מריצים את הדף ב-headless browser, מזהים אילו selectors פעילים ב-above the fold, ומחלצים אותם.

הדפוס המעשי

<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>עמוד הבית</title>

    <!-- Critical CSS — inline, < 14KB -->
    <style>
        /* רק מה ש-above the fold צריך */
        :root { --primary: #3b82f6; --text: #1a1a1a; }
        body { font-family: 'Heebo Fallback', sans-serif; color: var(--text); }
        .nav { display: flex; padding: 16px; }
        .hero { min-height: 80vh; padding: 64px 16px; }
        .hero h1 { font-size: clamp(32px, 6vw, 64px); }
        /* ... */
    </style>

    <!-- Preload של font קריטי -->
    <link rel="preload"
        href="/fonts/Heebo-Regular.woff2"
        as="font"
        type="font/woff2"
        crossorigin
    />

    <!-- שאר ה-CSS — async load -->
    <link rel="preload"
        href="/css/main.css"
        as="style"
        onload="this.onload=null;this.rel='stylesheet'"
    />
    <noscript><link rel="stylesheet" href="/css/main.css"></noscript>
</head>

ה-rel="preload" + onload טריק הוא הדרך המקובלת לטעון CSS async. הוא טוען את ה-CSS ברקע, ורק כשסיים — מחיל אותו. <noscript> הוא fallback למשתמשים שכיבו JavaScript.

האם שווה את המאמץ ל-Vibe Coder?

תלוי. לאתר קטן-בינוני של Vibe Coder (landing page, portfolio), בדר"כ ה-CSS הכולל הוא 20-50KB. אם זה כבר נטען מהר, אז critical CSS הוא overkill. התחילו לדאוג ל-critical CSS כש:

מסגרת החלטה: מתי לעשות Critical CSS
מצב האתרCritical CSS?אלטרנטיבה
CSS total < 30KBלא שווהTailwind JIT / purged CSS
CSS 30-80KBאולי — אם Lighthouse אומרAsync load של main CSS
CSS 80KB+כן, עקרוניתCritical CSS + dynamic imports
Next.js / Astro / Gatsbyמובנההפרויקטים האלה מחלצים critical CSS אוטומטית
HTML סטטי + CSS fileרק אם הצטייןידני או כלי — 30-60 דקות חד-פעמית
בינוני 8 דקות חינם מושג

11.14 Render-Blocking Resources — fonts, CSS, JS שחוסמים

Render-blocking = משאב שהדפדפן חייב לטעון ולעבד לפני שהוא יכול להציג את הדף. ברירת המחדל של HTML: CSS ו-JS סינכרוני חוסמים. זה הסיבה #1 ל-LCP גבוה אחרי תמונות.

מה חוסם render — הרשימה המלאה

איך משחררים — 5 טכניקות

  1. JavaScript עם defer. <script src="app.js" defer> — הסקריפט נטען בלי לחסום parsing, רץ אחרי שה-HTML סיים. שמור על סדר ביצוע בין scripts.
  2. JavaScript עם async. <script src="analytics.js" async> — סקריפט נטען ורץ ברקע, לא חוסם, אין ערובה לסדר. מושלם ל-analytics.
  3. CSS עם preload + onload (ראו section 11.13).
  4. פונטים עם font-display: swap (ראו section 11.15).
  5. העברת scripts לסוף ה-body. אם אי אפשר defer/async, לפחות שהם יריצו אחרי הרבה HTML.

Preconnect ו-Preload — שני ההשלמות

preconnect: אומר לדפדפן "פתח חיבור לדומיין הזה עכשיו, גם אם אני עוד לא מבקש ממנו כלום". חוסך 100-300ms. שימושי ל-Google Fonts, CDN, analytics.

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://cdn.example.com">

preload: אומר לדפדפן "תוריד את המשאב הזה בעדיפות גבוהה, אני אשתמש בו בקרוב". שימושי ל-hero image, font קריטי, critical CSS file (אם לא inline).

<link rel="preload" as="image" href="hero.avif" fetchpriority="high">
<link rel="preload" as="font" href="/fonts/Heebo.woff2" type="font/woff2" crossorigin>
Do-Now: בדיקת render-blocking בדף 4 דקות

ב-Lighthouse → Performance → "Eliminate render-blocking resources" (אם קיים). רשמו:

לכל אחד, הוסיפו את ה-attribute המתאים (defer/async/preload). זה עבודה של 10-20 דקות שחוסכת 300-800ms.

בינוני 10 דקות חינם הקמה

11.15 Font Loading — font-display: swap ופונטים עבריים

פונטים עבריים הם מקור LCP גרוע #2 בישראל אחרי תמונות. הסיבה: glyphs עבריים כבדים יותר (כל מילה דורשת ligatures, combining marks לניקוד, Unicode ranges רחבים). קובץ WOFF2 של Heebo Regular + Bold = ~120KB. עם 4 משקלים = 480KB. על 4G איטי = 3-5 שניות לטעינה.

font-display: swap — חובה, לא רשות

ברירת המחדל של Google Fonts (עד 2020) הייתה font-display: block — הטקסט מוסתר עד שהפונט נטען (FOIT = Flash of Invisible Text). זה רוצח LCP. הפתרון: font-display: swap — הטקסט מופיע מיד עם fallback (Arial / system-ui), ואז מתחלף כשהפונט נטען (FOUT = Flash of Unstyled Text).

מאז 2022, Google Fonts מציעים &display=swap ב-URL:

<!-- חובה — &display=swap בסוף -->
<link
    href="https://fonts.googleapis.com/css2?family=Heebo:wght@400;600;800&display=swap"
    rel="stylesheet"
/>

ב-self-hosted fonts, השתמשו ב-@font-face:

@font-face {
    font-family: 'Heebo';
    src: url('/fonts/Heebo-Regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;  /* חובה! */
}

הטעינה האופטימלית של פונט עברי

  1. בחרו 2-3 משקלים מקסימום. לא 9. 400 (regular) + 700 (bold) + אופציונלי 500 או 600 למשקל ביניים. כל משקל נוסף = 120KB נוספים.
  2. Preconnect ל-Google Fonts. 2 השורות שכבר יש לכם ב-head:
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  3. Preload את המשקל הקריטי (בדר"כ Regular שבהם נכתב ה-body):
    <link rel="preload"
        as="font"
        type="font/woff2"
        href="https://fonts.gstatic.com/s/heebo/...Heebo-Regular.woff2"
        crossorigin
    />
  4. font-display: swap על הכל.
  5. Metric overrides ב-@font-face של fallback — למניעת CLS בזמן swap (ראו section 11.4).

Variable Fonts — הפתרון של 2026

Variable fonts הם פונטים שיש בהם את כל המשקלים בקובץ אחד. במקום 3 קבצים של 120KB כל אחד = 360KB, יש קובץ אחד של 180KB שמכיל את כל המשקלים. Heebo יש variable font מאז 2023. שימוש:

@font-face {
    font-family: 'Heebo VF';
    src: url('/fonts/Heebo-VariableFont.woff2') format('woff2-variations');
    font-weight: 100 900;  /* טווח משקלים זמין */
    font-display: swap;
}

body {
    font-family: 'Heebo VF', sans-serif;
    font-weight: 400;  /* או כל מספר בין 100 ל-900 */
}

חיסכון: 50-60% במשקל כולל של פונטים. זו אופטימיזציה משמעותית לאתר עברי.

טעות נפוצה: טעינת 9 משקלים של Heebo "למקרה שנצטרך"

AI מקבל "use Heebo font" ומוסיף את כל המשקלים: 100, 200, 300, 400, 500, 600, 700, 800, 900. זה 9 × 120KB = 1.08MB של פונטים לפני שהמשתמש ראה תו אחד. המשתמש שלכם על 4G מחכה 8 שניות לפונט. מה לעשות במקום: (א) להחליט בפרומפט מראש על 2-3 משקלים בלבד לפי ה-hierarchy שבניתם בפרק 4 (בד"כ 400 + 700 מספיקים), (ב) לשקול variable font שמחליף את כל המשקלים בקובץ אחד קטן יותר, (ג) לעולם לא לכתוב family=Heebo:wght@300;400;500;600;700;800;900 — זה דגל אדום.

בינוני 8 דקות חינם הקמה

11.16 Skeleton Screens vs Spinners — למה skeleton מנצח

טעינה של משהו (תוכן, תמונה, data מ-API) לוקחת זמן. יש 2 דפוסים לראוות למשתמש ש"משהו קורה": Spinner (גלגל מסתובב) ו-Skeleton Screen (תבנית אפורה בצורת התוכן הסופי). המדע: skeleton מרגיש מהיר פי 2 למרות שה-wall time זהה.

למה skeleton עדיף

Skeleton Component — CSS בלבד, ללא JS

<div class="skeleton-card">
    <div class="skeleton skeleton-image"></div>
    <div class="skeleton skeleton-title"></div>
    <div class="skeleton skeleton-text"></div>
    <div class="skeleton skeleton-text skeleton-text-short"></div>
</div>
.skeleton {
    background: linear-gradient(
        90deg,
        #e5e7eb 0%,
        #f3f4f6 50%,
        #e5e7eb 100%
    );
    background-size: 200% 100%;
    animation: shimmer 1.5s infinite;
    border-radius: 6px;
}

.skeleton-card {
    padding: 16px;
    border-radius: 12px;
    background: #fff;
    border: 1px solid #e5e7eb;
}

.skeleton-image {
    width: 100%;
    aspect-ratio: 16 / 9;
    margin-bottom: 16px;
}

.skeleton-title {
    height: 24px;
    width: 70%;
    margin-bottom: 12px;
}

.skeleton-text {
    height: 16px;
    width: 100%;
    margin-bottom: 8px;
}

.skeleton-text-short {
    width: 40%;
}

@keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* Prefers-reduced-motion — כיבוי shimmer */
@media (prefers-reduced-motion: reduce) {
    .skeleton {
        animation: none;
    }
}

התוצאה: skeleton-card שמחליף את התוכן האמיתי עד שהוא נטען. ה-shimmer מסמן למשתמש "פעיל, נטען". ברגע שהתוכן הגיע — JavaScript מסיר את ה-.skeleton-card ומחליף ב-.real-card עם אותן מידות בדיוק.

מתי עדיין spinner

בינוני 15 דקות חינם אסטרטגיה

11.17 Performance Audit Prompt + Performance Fix Prompt

שני פרומפטים שכל Vibe Coder צריך בכיס. הראשון לאודיט של אתר קיים — מוצא בעיות. השני לתיקון — מיישם אופטימיזציות.

Prompt 1: Performance Audit Prompt

העתיקו את הפרומפט הבא, הדביקו ל-Claude / Cursor / Copilot, והצמידו את קוד ה-HTML + CSS הראשי.

Please audit this website for performance issues that impact
Core Web Vitals (LCP, CLS, INP). Be specific — no generic advice.

Check for and report, in priority order:

1. LCP KILLERS:
   - Find the likely LCP element (hero image, h1, or background).
   - Is the hero image optimized? Format (JPEG/WebP/AVIF), width attribute?
   - Is loading="lazy" on the hero image? (This is a BUG if yes.)
   - Is there <link rel="preload" as="image"> for the hero?
   - Is fetchpriority="high" on the hero img tag?
   - Are fonts using font-display: swap? Or are they blocking?

2. CLS KILLERS:
   - Find all <img> tags. Flag any missing width or height attributes.
   - Find all <iframe>. Flag any missing aspect-ratio or height.
   - Flag dynamic content injected above existing content (ads, banners).
   - Are fonts using size-adjust/ascent-override metric fallbacks?

3. CSS PERFORMANCE KILLERS:
   - Find backdrop-filter on elements larger than 500x500px.
   - Find will-change applied to more than 5 elements.
   - Find transitions on width, height, margin, top, left
     (should be transform).
   - Find transitions on box-shadow (should be opacity of ::after).
   - Find animations of background-position on large elements.

4. LAZY LOADING STRATEGY:
   - List all <img> with their loading attribute.
   - Flag above-the-fold images with loading="lazy" (BUG).
   - Flag below-the-fold images WITHOUT loading="lazy" (missing opt).
   - Flag all <iframe> without loading="lazy" (always should).

5. RENDER-BLOCKING:
   - List all <link rel="stylesheet"> in <head>.
   - List all <script src> without async or defer.
   - Flag any @import inside CSS files (chain blocking).
   - Flag Google Fonts URL without &display=swap.

6. FONT LOADING:
   - Count Hebrew font weights loaded. Flag if more than 3.
   - Is there preconnect to fonts.googleapis.com and fonts.gstatic.com?
   - Is there preload of the critical font weight?
   - Is the font-family using a proper fallback chain?

7. MODERN OPTIMIZATIONS OPPORTUNITIES:
   - Can content-visibility: auto be applied to sections below fold?
   - Can contain: paint be applied to isolated widgets (cards, modals)?
   - Are skeleton screens used instead of spinners?

Output: Prioritized list (Critical / High / Medium) with:
- Specific line numbers
- Exact current code
- Exact recommended code
- Estimated performance impact (LCP -X ms, CLS -X, INP -X ms)

Be concrete. Don't say "optimize images" — say
"Convert hero.jpg (380KB) to hero.avif (~80KB), estimated
LCP improvement of 800ms on Slow 4G."

Prompt 2: Performance Fix Prompt

אחרי ה-audit, הפרומפט הזה מבקש מ-AI ליישם את התיקונים. הדביקו את הקוד + ה-audit הקודם.

Based on the performance audit above, implement the fixes
with the following non-negotiable specs:

=== HERO IMAGE (LCP) ===
- Convert to <picture> with AVIF, WebP, JPEG fallback (3 sources).
- Add width and height attributes (aspect ratio preserved).
- Set loading="eager" fetchpriority="high" decoding="sync".
- Add <link rel="preload" as="image"> in <head> with imagesrcset.
- NO loading="lazy" on hero. Ever.

=== BELOW-THE-FOLD IMAGES ===
- Add loading="lazy" decoding="async" to every <img> below the fold.
- Add loading="lazy" to every <iframe> (YouTube, Maps, embeds).
- Ensure width and height attributes on every <img>.

=== FONTS (LCP + CLS) ===
- Load Hebrew font (Heebo) with max 2-3 weights (400, 700, optional 600).
- Use font-display: swap always.
- Add preconnect to fonts.googleapis.com and fonts.gstatic.com.
- Add preload of the Regular weight woff2 file.
- Add <@font-face> metric-adjusted fallback to prevent CLS on swap.

=== CSS PERFORMANCE ===
- Replace any transition: width/height/margin with transform.
- Replace transition: box-shadow with ::after + opacity pattern.
- Remove will-change from all elements except those with active animations.
- If backdrop-filter is on a large element, either scope it to a smaller
  child or replace with pre-baked blurred background image.

=== MODERN CSS OPTIMIZATIONS ===
- Add content-visibility: auto + contain-intrinsic-size: 0 Xpx to
  every section below the hero (estimate X from current heights).
- Add contain: paint to isolated widgets (cards, modals, sidebars).
- Replace spinners with skeleton screens for content that loads > 500ms.

=== RENDER-BLOCKING ===
- Add async or defer to all non-critical scripts.
- Add preconnect to external domains loaded in critical path.
- If CSS bundle > 80KB, implement critical CSS inline + async main CSS.

=== VERIFICATION ===
After implementing:
1. Provide updated HTML and CSS.
2. Explain each change and its CWV impact.
3. Flag any trade-offs (e.g., "will-change removed from .card
   may cause 1-frame lag on first hover, acceptable trade-off").
Do-Now: הריצו את Audit Prompt 7 דקות

העתיקו את Performance Audit Prompt למעלה. פתחו את האתר הנוכחי שלכם. הדביקו את ה-HTML + CSS לתוך Claude/Cursor עם הפרומפט. קבלו את רשימת הבעיות. רשמו את 3 הבעיות הגדולות ביותר שהוא זיהה:

  1. ____
  2. ____
  3. ____

אלה ה-priorities שלכם לתיקון בתרגיל 4.

11.18 תרגילים מעשיים

בינוני 110 דקות (כל ה-4 תרגילים) חינם תרגול
תרגיל 1: Lighthouse Baseline + הבנה של 5 המדדים 25 דקות
  1. פתחו Chrome, Incognito mode. נווטו לאתר האישי שלכם (אם אין — השתמשו באתר גנרי שבנה AI בקורס הקודם).
  2. F12 → Lighthouse. בחרו: Mobile + Performance only + Navigation. הריצו.
  3. כשסיים — שמרו screenshot של ה-scores. הריצו שוב 2 פעמים נוספות. רשמו את 3 ה-scores ב-spreadsheet.
  4. לקחו את המדיאן (הציון האמצעי). זה ה-baseline שלכם. רשמו: Performance Score Baseline: ____ / 100.
  5. לכו ל-section "Metrics" בתוך Lighthouse. רשמו את 5 המדדים: FCP: __s / LCP: __s / TBT: __ms / CLS: __ / Speed Index: __s.
  6. לכל אחד מהם, סמנו אם הוא Good (ירוק) / Needs Improvement (כתום) / Poor (אדום) לפי ה-color coding של Lighthouse.
  7. לכו ל-"Opportunities". רשמו את 3 ההזדמנויות הגדולות לפי "Estimated savings". לכל אחת: מה המשמעות שלה, וכמה היא חוסכת.
  8. לכו ל-"Diagnostics". רשמו את 3 האזהרות הגדולות ביותר.
  9. הריצו את אותם 3 ההרצות על עמוד שני באתר (לדוגמה: עמוד about או contact). רשמו את ההבדל.

מה צריך להיות בסוף: spreadsheet עם 2 עמודים × 3 הרצות × 5 מדדים, מדיאן מחושב לכל אחד, רשימה של Opportunities ו-Diagnostics — תמונה מלאה של מצב ה-performance של האתר. זה ה-baseline שמולו תשוו בתרגיל 4.

תרגיל 2: LCP Fix מלא — תמונת Hero + Preload + Font 30 דקות
  1. מהתרגיל הקודם, רשמתם מה ה-LCP element שלכם. אם זה hero image — נתחיל שם.
  2. פתחו את התמונה המקורית. רשמו את ה-format (JPEG/PNG) וה-size (KB).
  3. לכו ל-Squoosh.app. ייצאו את התמונה ב-3 פורמטים × 3 רזולוציות (400w, 800w, 1200w) = 9 קבצים. השוו משקלים: JPEG 1200w: __KB / WebP 1200w: __KB / AVIF 1200w: __KB.
  4. העלו את 9 הקבצים ל-public folder / CDN.
  5. החליפו את ה-<img> של ה-hero ב-<picture> מלא עם 3 <source> tags + <img> fallback. ודאו width, height, loading="eager", fetchpriority="high".
  6. הוסיפו ב-<head>: <link rel="preload" as="image" href="hero-1200.avif" type="image/avif" imagesrcset="..." imagesizes="..." fetchpriority="high" />.
  7. בדקו את ה-Google Fonts URL. ודאו ש-&display=swap בסוף. ודאו שאין יותר מ-3 משקלים טעונים. אם יש — הסירו.
  8. הוסיפו <link rel="preload" as="font" type="font/woff2" href="..." crossorigin /> של המשקל הקריטי (בדר"כ Regular).
  9. הריצו Lighthouse 3 פעמים. מדיאן חדש: Performance Score: ____ / 100. LCP: ____ (צריך לרדת ב-500ms-1.5s).

מה צריך להיות בסוף: <picture> component מוכן, 9 קבצי תמונה ב-CDN, preload של image ו-font, ו-before/after של LCP עם שיפור של 500ms+.

תרגיל 3: CSS Killers — Hunt and Replace 25 דקות
  1. פתחו את קובץ ה-CSS הראשי. חפשו את כל ה-pattern-ים הבאים:
    • will-change — רשמו כל מופע. לרוב — הסירו, אלא אם יש סיבה ברורה.
    • backdrop-filter — בדקו גודל האלמנט. מעל 500×500px? תחליפו ב-pre-baked background.
    • transition: עם width, height, margin, top, left — המירו ל-transform.
    • transition: box-shadow — המירו ל-::after עם opacity.
    • Google Fonts URL בלי &display=swap — הוסיפו.
  2. לכל תיקון, רשמו את ה-selector ואת השינוי. דוגמה: .card — הסר will-change: transform; .button:hover — transition: margin-top → transform: translateY.
  3. אחרי התיקונים, רענו את האתר. ודאו שהאנימציות עדיין עובדות ויזואלית (לפעמים transform ו-margin לא זהים מבחינת מיקום סופי — כיוונו).
  4. הריצו Lighthouse 3 פעמים. התמקדו ב-TBT (Total Blocking Time). מדיאן חדש: ____ ms.
  5. פתחו את האתר ב-mobile אמיתי. בדקו 3 hover/tap interactions. האם הן חלקות? האם אין jank?
  6. הוסיפו content-visibility: auto + contain-intrinsic-size: 0 600px על 2 sections שנמצאים מתחת ל-fold. הריצו שוב.

מה צריך להיות בסוף: רשימת 5-10 תיקונים עם before/after של קוד, TBT improvement של 50-150ms, והתחושה הסובייקטיבית במובייל שהאתר "חלק יותר".

תרגיל 4: Audit Prompt → Fix Prompt → Before/After 30 דקות
  1. העתיקו את Performance Audit Prompt מ-section 11.17.
  2. פתחו את הקוד שלכם אחרי תרגילים 2-3 (יש לכם כבר שיפורים — זה הבסיס).
  3. הדביקו ל-Claude / Cursor. קבלו את רשימת הבעיות שעדיין קיימות.
  4. העתיקו את Performance Fix Prompt. בקשו מ-AI ליישם את התיקונים.
  5. עברו על כל תיקון. ודאו שה-AI לא שבר משהו (בעיקר לבדוק: האם ה-UI עדיין נראה זהה? האם אין regressions?).
  6. ב-cases שהאתר נראה אחרת — החזירו חלק מהתיקונים. עדיפות: אל תיצרו אופטימיזציה על חשבון העיצוב.
  7. הריצו Lighthouse סופי. 3 פעמים. מדיאן. השוו למדיאן של תרגיל 1:
מדדBaseline (תרגיל 1)אחרי (תרגיל 4)שיפור
Performance Score____________
LCP____ s____ s____ s
CLS____________
TBT____ ms____ ms____ ms
Speed Index____ s____ s____ s

מה צריך להיות בסוף: טבלת before/after מלאה, screenshot של ה-Lighthouse הסופי, ותחושה שהאתר שלכם עכשיו נטען מהר אצל משתמש אמיתי ב-4G. אם הגעתם ל-Performance 90+ במובייל — אתם בקבוצה של ה-5% האתרים המובילים בישראל.

שגרת עבודה: שמירה על Performance
תדירותמה לעשותכמה זמן
יומי בסוף כל session של פיתוח — הריצו Lighthouse פעם אחת במובייל על העמוד שעבדתם עליו. רק בדיקה מהירה: Performance Score לא ירד? LCP עדיין מתחת ל-2.5s? אם כן — המשיכו. אם לא — טפלו לפני שתמשיכו לעמוד הבא. 3-5 דקות
שבועי הריצו את Performance Audit Prompt (section 11.17) על הפרויקט הפעיל. תקנו את 3 ה-Critical issues הראשונים. בנוסף — בדקו ב-Search Console את ה-Core Web Vitals של השבוע האחרון: יש URLs חדשים שהפכו ל-"Poor"? אם כן — חקרו למה. 30-40 דקות
חודשי הריצו Lighthouse על 3-5 עמודים עיקריים (homepage, 2 landing pages פופולריים, דף contact). רשמו ב-spreadsheet. השוו לחודש שעבר. אם LCP עלה — כנראה תמונה חדשה לא אופטמה. אם CLS עלה — כנראה חסר width/height על משהו. בנוסף: בדקו ב-PageSpeed Insights את ה-Field Data ב-CrUX. 60-90 דקות
אם אתם עושים רק דבר אחד מהפרק הזה

תקנו את ה-LCP של ה-hero של העמוד הראשי. זה הדבר היחיד שיעשה את ההבדל הגדול ביותר בחוויה של המשתמשים שלכם: (1) המירו את תמונת ה-hero ל-AVIF + WebP ב-Squoosh, (2) הוסיפו width, height, loading="eager", fetchpriority="high", (3) הוסיפו <link rel="preload" as="image"> ב-<head>, (4) ודאו ש-Google Fonts URL מסתיים ב-&display=swap ויש לכם preconnect. 4 שינויים שלוקחים 25 דקות, מורידים LCP ב-800-1500ms, מעלים את ה-Performance Score ב-15-30 נקודות, ומוציאים אתכם מ-"Needs Improvement" ל-"Good" ב-Core Web Vitals. זה הטיפול הכי חסכוני-בזמן וחזק-בתוצאה בקורס כולו. אם אתם עושים רק את זה — הרווחתם.

בדקו את עצמכם — 5 שאלות
  1. מה ההבדל בין Field Data ל-Lab Data ב-PageSpeed Insights, ולמה שניהם חשובים? תנו דוגמה למצב שבו הם סותרים. (רמז: CrUX של משתמשים אמיתיים מול Lighthouse סינתטי; Field טוב + Lab גרוע = lab מחמיר; Field גרוע + Lab טוב = בעיית שרת או רשת)
  2. למה אסור will-change: transform על כל אלמנט באתר? מה קורה כשמשתמשים בו נכון? (רמז: GPU memory exhaustion, 50 layers = אתר מאט, שימוש נכון = רק כשבאמת האלמנט עומד להשתנות, לזמן קצר, :hover כ-trigger)
  3. למה אסור loading="lazy" על תמונת hero, ומה כן לעשות? תנו 3 אלמנטים שצריך להוסיף ל-hero image. (רמז: לא lazy כי זה ה-LCP element; loading="eager" + fetchpriority="high" + <link rel="preload"> ב-head)
  4. למה פונטים עבריים הם סיבה נפוצה ל-LCP גרוע בישראל, ואיך פותרים את זה בלי להיפרד מהפונט? (רמז: 9 משקלים × 120KB = 1MB; פתרונות: font-display: swap, 2-3 משקלים בלבד, preload של Regular, variable font, metric-adjusted fallback)
  5. מה ההבדל בין content-visibility: auto ל-contain: paint, ומתי משתמשים בכל אחד? האם אפשר לשלב אותם? (רמז: content-visibility = דילוג על render מחוץ ל-viewport, מתאים ל-sections גדולים; contain: paint = הגבלת paint לאזור, מתאים ל-widgets מבודדים; כן, אפשר לשלב על אותו section)
סיכום הפרק

בפרק הזה עברתם מ-"האתר שלי נראה טוב" ל-"האתר שלי נראה טוב ונטען תוך 2 שניות גם על 4G של פרטנר". הבנתם שהמציאות של הגולש הישראלי הממוצע היא לא fiber של Mac Studio — זה Samsung A52 ב-4G של 5-15 Mbps, עם latency של 60-110ms. על המציאות הזו, אתר לא-מאופטם נטען תוך 4-5 שניות, ו-53% מהמשתמשים נוטשים. אתר מאופטם נטען תוך 1.5-2 שניות, והמשתמש נשאר.

למדתם את שלושת המדדים של Core Web VitalsLCP (יעד < 2.5 שניות, מודד מתי האלמנט הגדול מופיע), CLS (יעד < 0.1, מודד עד כמה הדף "קופץ"), ו-INP (יעד < 200ms, מודד כמה מהר האתר מגיב לקליק). הבנתם את כלל ה-75th percentile של Google — לא מספיק שה-50% הטובים רואים חוויה טובה; גם ה-25% עם ה-conditions הכי גרועים חייבים.

תרגלתם Lighthouse ב-Mobile mode עם הריצה נכונה: Incognito, 3 הרצות, מדיאן. הכרתם את PageSpeed Insights וההבדל בין Field Data (מציאות מ-CrUX) ל-Lab Data (Lighthouse סינתטי). הבנתם את חמשת המדדים שמרכיבים את ה-Performance score, ושם TBT + LCP מהווים 55% מהציון.

זיהיתם את 8 רוצחי ה-Performance ב-CSS: backdrop-filter על רקעים גדולים, will-change על כל אלמנט (הטעות הנפוצה ביותר של AI), box-shadow מרובה שכבות מונפש, אנימציות של width/height/margin במקום transform, filter: blur בזמן scroll, gradients מונפשים על background-position, hover על elements גדולים, ופונטים בלי font-display: swap. למדתם את ה-rule הפשוט: אנימציות רק עם transform ו-opacity (השאר מפעילים reflow).

בניתם lazy loading strategy מעשית — eager + fetchpriority="high" על hero, lazy + decoding="async" על הכל מתחת ל-fold, תמיד lazy על iframes. הכרתם את content-visibility: auto + contain-intrinsic-size — 2 שורות CSS שחוסכות שנייה מ-TTI בדפים ארוכים. הוספתם contain: paint לווידג'טים מבודדים. הבנתם את will-change לעומק: הוא עוצמתי, אבל לשימוש ממוקד בלבד, לא כ-blanket optimization.

למדתם על Critical CSS — ה-14KB הראשונים שיכולים להיכנס ב-round trip אחד של TCP, וה-pattern של rel="preload" + onload לטעינת CSS async. הבנתם render-blocking resources ואיך לשחרר אותם: defer ו-async על scripts, preconnect לדומיינים חיצוניים, preload למשאבים קריטיים. טיפלתם בפונטים עבריים — מקור LCP גרוע #2 בישראל: מקסימום 2-3 משקלים, font-display: swap, preload של Regular, size-adjust ב-fallback, ואופציה של variable fonts לחיסכון של 50-60% במשקל.

החליפו spinners ב-skeleton screens — דפוס שמרגיש מהיר פי 2 למרות שה-wall time זהה, עם CSS בלבד (shimmer animation על linear-gradient), כולל respect ל-prefers-reduced-motion. קיבלתם שני פרומפטים מוכנים — Performance Audit Prompt שמוצא בעיות ספציפיות (לא "make it faster"), ו-Performance Fix Prompt שמיישם תיקונים עם specs ברורים. עברתם תרגיל מקיף של Before/After עם טבלה של 5 מדדים לפני ואחרי.

יש לכם עכשיו 8 deliverables מוחשיים: (1) Lighthouse Report עם ניתוח, (2) Core Web Vitals Cheat Sheet, (3) רשימת 10 אופטימיזציות ל-AI, (4) Critical CSS Pattern, (5) Font Loading Strategy לעברית, (6) Skeleton Screen Component, (7) Performance Audit + Fix Prompts, ו-(8) מילון 16 מונחים. יחד עם Responsive Design מפרק 10, Glassmorphism מפרק 9, Modern CSS מפרק 6, Typography מפרק 4, ופלטת צבעים מפרק 3 — יש לכם את כל ה-toolkit של מפתח Web מקצועי ב-2026: אתר שנראה כמו סטודיו, מתנהג כמו אפליקציה, ונטען מהר כמו אתר פרסום של חברת תשתית.

הגשר לפרק הבא: בפרק 11 השלמתם את ה-foundations של אתר מקצועי — עיצוב + responsive + מהירות. בפרק 12 — "כלי עיצוב (כוחות-על אופציונליים): Figma, Google Stitch ו-MCP" — תכירו כלי עיצוב מקצועיים שיכולים להאיץ את ה-workflow שלכם אבל הם אופציונליים. תבחנו את Figma (הסטנדרט של מעצבי UI בישראל) — איך לבצע inspect כדי לחלץ spacing, colors ו-fonts, איך למדוד מרחקים עם Option-hover, ואיך לייצא SVGs ואייקונים. תכירו את Google Stitch (text-to-UI) — כלי חדש שממיר תיאור טקסט לעיצוב מלא, עם היתרונות והמגבלות שלו. תלמדו על MCP (Model Context Protocol) — הפרוטוקול של Anthropic שמחבר כלי AI (Cursor, Claude Desktop) ישירות ל-Figma ול-Stitch. המסר המרכזי של הפרק: הידע שבניתם בפרקים 1-11, כולל פרק ה-Performance הזה, הוא מה שקובע את האיכות. Vibe Coder שמבין Performance, Responsive ו-Typography יכול לבנות אתר מקצועי גם בלי לפתוח Figma אף פעם — פשוט בתיאור טקסטואלי עשיר ל-AI. הכלים הם אצל מי שיודע; למי שלא יודע, הכלים לא מצילים. פרק 12 הוא power-up אופציונלי, פרק 11 היה חובה. ופרק 13 (ה-capstone) יחבר את הכל לעבודה אמיתית.

צ'קליסט — 15 דברים לבדוק לפני launch (Performance)