זהו הפוסט הראשון בבלוג ההנדסה של 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 תואם בדיסק) לכותבי פוסטים. לדוגמה, אנחנו יוצרים את דפי המחברים באמצעות תבנית שמכילה ביטוי של הקישור הקבוע (כך שהתבנית עוברת עיבוד מחדש לכל מחבר) ואוסף תומך.
התוצאה היא, לדוגמה, דף פשוט שמכיל את כל הפוסטים של Addy.
מגבלות
בשלב הזה אנחנו לא יכולים להתחבר בקלות לתהליך ה-build של Eleventy כי הוא הצהרתי ולא ציוויתי: אתם מתארים מה אתם רוצים, ולא איך אתם רוצים את זה. קשה להריץ את Eleventy כחלק מכלי build גדול יותר, כי אפשר להפעיל אותו רק דרך ממשק שורת הפקודה שלו.
תבניות
ב-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 נעשה שימוש גם בקודים קצרים כסוג של שפת מטא-תכנות. קודי ה-Shortcode מקבלים ארגומנטים, ואחד מהם הוא התוכן הכלול. אין צורך שהקודים המקוצרים יחזירו משהו, כך שאפשר להשתמש בהם כדי ליצור מצב או להפעיל התנהגות אחרת. 🤔💭
כתיבת סקריפטים
כפי שצוין קודם, מכיוון ש-web.dev הוא אתר סטטי, אפשר להציג אותו ולהשתמש בו בלי JavaScript, וגם בדפדפנים ישנים שלא תומכים ב-type="module"
או בקוד המודרני שלנו.
זהו חלק חשוב מאוד בגישה שלנו להנגשת web.dev לכולם.
עם זאת, הקוד שלנו לדפדפנים מודרניים מורכב משני חלקים עיקריים:
- קוד Bootstrap, שכולל קוד למצב גלובלי, ל-Analytics ולניתוב SPA
- קוד ו-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 נעשה שימוש ברכיבי אינטרנט בדפים רבים, אבל השימוש בהם הכי נחוץ בדף מדידה. שני אלמנטים מספקים את רוב הפונקציונליות שמוצגת בדף הזה:
<web-url-chooser-container></web-url-chooser-container>
<web-lighthouse-scores-container></web-lighthouse-scores-container>
הרכיבים האלה יוצרים רכיבים נוספים שמספקים פונקציונליות נוספת. חשוב לדעת שהרכיבים האלה הם רק חלק מקוד המקור הרגיל שלנו ב-Markdown, וצוות התוכן שלנו יכול להוסיף פונקציונליות מורחבת לכל דף, ולא רק לצומת Measure.
ברוב המקרים, רכיבי ה-Web שלנו מבוססים על המודל של רכיב מאגר, שהפך לפופולרי בזכות React, למרות שהמודל הזה קצת מיושן.
כל רכיב -container
מתחבר למצב הגלובלי שלנו (שסופק על ידי unistore), ולאחר מכן מבצע עיבוד (render) של רכיב חזותי, שממשיך לעבד צמתים אמיתיים של DOM עם עיצוב או פונקציונליות מובנית אחרת.
רכיבי ה-Web Components המורכבים ביותר שלנו משמשים להצגה חזותית של פעולות ומצבים גלובליים. לדוגמה, ב-web.dev אפשר לבדוק את האתר האהוב עליכם ואז לנווט אל דף אחר. אם תחזרו, תראו שהמשימה עדיין מתבצעת.
הרכיבים הפשוטים שלנו משפרים תוכן סטטי או יוצרים תצוגות חזותיות מדהימות (לדוגמה, כל תרשים קו הוא <web-sparkline-chart>
משלו), ללא קשר למצב הגלובלי.
קדימה, לצ'אט
צוות מהנדסי web.dev (Rob, Ewa, Michael ו-Sam) ימשיך לפרסם בקרוב ניתוחים טכניים מעמיקים נוספים.
אנחנו מקווים שהסברנו לכם איך אנחנו עושים את הדברים, ונתתם לעצמכם כמה רעיונות לפרויקטים שלכם. אם יש לכם שאלות או בקשות לנושאים שתרצו שנכתוב עליהם בבלוג, אתם מוזמנים לפנות אלינו ב-Twitter.