web.dev בלוג הנדסה מס' 1: כיצד אנחנו בונים את האתר ומשתמשים ברכיבי אינטרנט

זהו הפוסט הראשון בבלוג ההנדסה של web.dev. בחודשים הקרובים אנחנו מקווים לשתף תובנות פרקטיות מהעבודה שלנו, אז כדאי לעקוב אחרי פוסטים עם תג של בלוג ההנדסה. כאן נסביר על תהליך ה-build של האתר הסטטי שלנו ועל (אופציונלי!) JavaScript שמאחורי רכיבי האינטרנט שלנו.

באתר web.dev מוצג תוכן בנושא בניית חוויות אינטרנט מודרניות, ומאפשר לכם למדוד את ביצועי האתר. משתמשים מתוחכמים אולי הבינו שדף המדידה שלנו הוא רק ממשק ל-Lighthouse, שזמין גם בכלי הפיתוח של Chrome. כניסה ל-web.dev מאפשרת לכם להריץ ביקורות שוטפות של Lighthouse באתר כדי לראות איך הציון שלו משתנה לאורך זמן. אבקר שוב בדף 'מדידה' בהמשך, כי לדעתנו הוא די מיוחד. 🎊

מבוא

ביסודו, web.dev הוא אתר סטטי שנוצר מאוסף של קובצי Markdown. בחרנו להשתמש ב-Eleventy כי זהו כלי משוכלל וניתן להתאמה שמאפשר להמיר בקלות Markdown ל-HTML.

אנחנו משתמשים גם בחבילות JavaScript מודרניות שאנחנו מציגים רק בדפדפנים שתומכים ב-type="module", כולל async ו-await. אנחנו גם משתמשים בתכונות שנתמכות בדפדפנים פופולריים, אבל לא בגרסת מיעוט של גרסאות ישנות יותר. מכיוון שמדובר באתר סטטי, אין צורך ב-JavaScript כדי לקרוא את התוכן שלנו.

אחרי שתהליך ה-build יסתיים – תהליך שכולל יצירת קובץ HTML סטטי וקיפול של JavaScript באמצעות Rollup – אפשר לארח את web.dev בשרת סטטי פשוט לצורך בדיקה. האתר כמעט סטטי לחלוטין, אבל יש לנו כמה צרכים מיוחדים שעדיין יכולים ליהנות משרת Node.js בהתאמה אישית. אלה כוללים הפניות אוטומטיות לדומיינים לא חוקיים, וגם קוד לניתוח השפה המועדפת של המשתמש לצורך תכונה בינלאומית שתושקה בקרוב.

יצירת קוד סטטי

כל דף ב-web.dev כתוב ב-Markdown. כל הדפים כוללים תוכן מקדים שמתאר את המטא-נתונים של כל פוסט. המטא-נתונים האלה מוטמעים בפריסה של כל דף, ויוצרים כותרות, תגים וכו'. לדוגמה:

---
layout: post
title: What is network reliability and how do you measure it?
authors:
  - jeffposnick
date: 2018-11-05
description: |
  The modern web is enjoyed by a wide swath of people…
---

The modern web is enjoyed by a wide swath of [people](https://www.youtube.com/watch?v=dQw4w9WgXcQ), using a range of different devices and types of network connections.

Your creations can reach users all across the world...

העניין הקדמי הזה מאפשר לנו להגדיר מאפיינים שרירותיים כמו מחברים, תאריך פרסום ותגים. ב-Eleventy, תוכן הקוד של החלק הקדמי מוצג כנתונים בנוחות כמעט בכל פלאגין, תבנית או הקשר אחר שבו רוצים לבצע פעולה חכמה. אובייקט הנתונים מכיל גם את מה ש-Eleventy מתארת בתור מפל הנתונים – מגוון נתונים שנשלפים מכל דף ספציפי, מהפריסה שבה הדף משתמש ומנתונים שנמצאים במבנה ההיררכי של התיקיות.

כל פריסה ייחודית מתארת סוג אחר של תוכן ויכולה לעבור בירושה מפריסות אחרות. ב-web.dev אנחנו משתמשים בתכונה הזו כדי להציג בצורה נכונה סוגים שונים של תוכן (כמו פוסטים וקורסים ב-Codelab), ועדיין לשתף פריסה אחת של HTML ברמה העליונה.

אוספים

Eleventy מספק דרך פרוגרמטית ליצירת אוספים שרירותיים של תוכן. כך הצלחנו ליצור תמיכה בחלוקה לדפים וליצור דפים וירטואליים (דפים שאין להם קובץ Markdown תואם בדיסק) לכותבי פוסטים. לדוגמה, אנחנו יוצרים את דפי המחברים באמצעות תבנית שמכילה ביטוי לכתובת ה-Permalink (כך שהתבנית עוברת עיבוד מחדש לכל מחבר) ואוסף תומך.

התוצאה היא, לדוגמה, דף פשוט שמכיל את כל הפוסטים של Addy.

מגבלות

בשלב הזה אנחנו לא יכולים להתחבר בקלות לתהליך ה-build של Eleventy כי הוא הצהרתי ולא ציוויתי: אתם מתארים מה אתם רוצים, ולא איך אתם רוצים את זה. קשה להריץ את Eleventy כחלק מכלי build גדול יותר, כי אפשר להפעיל אותו רק דרך ממשק שורת הפקודה (CLI).

תבניות

web.dev משתמש במערכת התבניות Nunjucks שפותחה במקור על ידי Mozilla. ב-Nunjucks יש את התכונות הסטנדרטיות של תבניות, כמו לולאות ותנאי, אבל הוא גם מאפשר לנו להגדיר קיצורי קוד שיוצרים עוד HTML או מפעילים לוגיקה אחרת.

כמו רוב הצוותים שמפתחים אתרים עם תוכן סטטי, התחלנו בקטן והוספנו קודי קיצור לאורך זמן – עד כה הוספנו כ-20 קודי קיצור. רוב הרכיבים האלה יוצרים רק קוד HTML נוסף (כולל רכיבי האינטרנט בהתאמה אישית שלנו). לדוגמה:

{% Aside %}
See how Asides work in the web.dev codebase
{% endAside %}

זה ייראה כך:

אבל בפועל הוא יוצר קובץ HTML שנראה כך:

<div class="aside color-state-info-text">
<p>See how Asides work in the web.dev codebase</p>
</div>

מעבר להיקף של הפוסט הזה, ב-web.dev נעשה שימוש גם בקודים קצרים כסוג של שפת מטא-תכנות. מקשי קיצור יכולים לקבל ארגומנטים, ואחד מהם הוא התוכן הכלול. אין צורך שקודים קצרים יחזירו משהו, כך שאפשר להשתמש בהם כדי ליצור מצב או להפעיל התנהגות אחרת. 🤔💭

כתיבת סקריפטים

כפי שצוין קודם, מכיוון ש-web.dev הוא אתר סטטי, אפשר להציג אותו ולהשתמש בו בלי JavaScript, וגם בדפדפנים ישנים שלא תומכים ב-type="module" או בקוד המודרני שלנו. זהו חלק חשוב מאוד בגישה שלנו להנגשת web.dev לכולם.

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

  1. קוד אתחול, שכולל קוד לניתוב מצב גלובלי, Analytics וניתוב SPA
  2. קוד ו-CSS לרכיבי אינטרנט שמשפרים את האתר באופן הדרגתי

קוד ה-bootstrap פשוט למדי: web.dev יכול לטעון דפים חדשים כאפליקציית דף יחיד (SPA), לכן אנחנו מתקינים מאזין גלובלי שמקשיב לקליקים על רכיבי <a href="..."> מקומיים. מודל ה-SPA עוזר לנו לשמור על מצב גלובלי לגבי הסשן הנוכחי של המשתמש, כי אחרת כל טעינת דף חדשה תפעיל קריאות ל-Firebase כדי לגשת למצב של המשתמש שמחובר לחשבון.

אנחנו גם מציינים כמה נקודות כניסה שונות לאתר שלנו על סמך כתובת ה-URL שבה לחצתם, ואנחנו טוענים את הנקודה הנכונה באמצעות import() דינמי. כך אנחנו מצמצמים את מספר הבייטים שהמשתמשים שלנו צריכים להעביר לפני שהאתר משופר באמצעות קוד.

Web Components

רכיבי אינטרנט הם רכיבים מותאמים אישית שמכילים פונקציונליות בסביבת זמן הריצה שסופקה ב-JavaScript, והם מזוהים בשמות מותאמים אישית כמו <web-codelab>. העיצוב מתאים במיוחד לאתרים סטטיים בעיקר, כמו web.dev: הדפדפן מנהל את מחזור החיים של רכיב בזמן העדכון של ה-HTML באתר, ומעדכן את כל הרכיבים בצורה נכונה כשהם מצורפים לדף או מופרדים ממנו. בדפדפנים מיושנים, רכיבי Web Components פשוט מתעלמים לגמרי ומריצים רינדור של כל מה שנשאר ב-DOM.

כל רכיב אינטרנט הוא כיתה עם שיטות, כולל connectedCallback(),‏ disconnectedCallback() ו-attributeChangedCallback(). הרכיבים המותאמים אישית ב-web.dev יורשים את רובם מ-LitElement, שמספק בסיס פשוט לרכיבים מורכבים.

ב-web.dev נעשה שימוש ברכיבי אינטרנט בדפים רבים, אבל בשום מקום לא נדרש יותר מאשר בדף Measure. שני רכיבים מספקים את רוב הפונקציונליות שאתם רואים בדף הזה:

<web-url-chooser-container></web-url-chooser-container>
<web-lighthouse-scores-container></web-lighthouse-scores-container>

הרכיבים האלה יוצרים רכיבים נוספים שמספקים פונקציונליות רבה יותר. חשוב לדעת שהרכיבים האלה הם רק חלק מקוד המקור הרגיל שלנו ב-Markdown, וצוות התוכן שלנו יכול להוסיף פונקציונליות מורחבת לכל דף, ולא רק לצומת Measure.

רכיבי האינטרנט שלנו בדרך כלל משתמשים במודל Container Component (רכיב קונטיינר) שנוצר על ידי React, אבל המודל הזה הוא קצת Passé. כל רכיב -container מתחבר למצב הגלובלי שלנו (מסופק על ידי unistore), ולאחר מכן מעבד רכיב חזותי, שממשיך לעבד צומתי DOM אמיתיים עם עיצוב או פונקציונליות מובנית אחרת.

תרשים שבו מוצג הקשר בין המצב הגלובלי לבין רכיבי ה-HTML שמשתמשים בו.
מצב גלובלי ורכיב אינטרנט

רכיבי ה-Web Components המורכבים ביותר שלנו מיועדים להצגה חזותית של פעולות וסטטוסים גלובליים. לדוגמה, ב-web.dev אפשר לבדוק את האתר האהוב עליכם ואז לנווט אל דף אחר. אם תחזרו, תראו שהמשימה עדיין מתבצעת.

הרכיבים הפשוטים שלנו משפרים תוכן סטטי או יוצרים חזותיות מדהימות (לדוגמה, כל תרשים קו הוא <web-sparkline-chart> משלו), ללא קשר למצב הגלובלי.

קדימה, לצ'אט

צוות מהנדסי התוכנה web.dev (Rob, Ewa, Michael ו-Sam) יחזור אליך בקרוב עם ניתוחים טכניים נוספים.

אנחנו מקווים שהסברנו לכם איך אנחנו עושים את הדברים, ונתתם לעצמכם כמה רעיונות לפרויקטים שלכם. אם יש לכם שאלות או בקשות לנושאים שתרצו שנכתוב עליהם בבלוג, אתם מוזמנים לפנות אלינו ב-Twitter.