מבוא
פיתוח עבור האינטרנט לנייד הוא נושא פופולרי בימינו. השנה, בפעם הראשונה בהיסטוריה, מכירות הסמארטפונים עלו על מכירות המחשבים האישיים. יותר ויותר משתמשים משתמשים במכשיר נייד כדי לגלוש באינטרנט, ולכן חשוב יותר ויותר למפתחים לבצע אופטימיזציה לאתרים שלהם לדפדפנים לנייד.
זירת הקרב 'ניידת' עדיין לא מוכרת למספר גדול של מפתחים. לאנשים רבים יש אתרים קיימים מדור קודם שמשמיטים את המשתמשים בנייד לגמרי. במקום זאת, האתר תוכנן בעיקר לגלישה במחשב, והוא לא מותאם בצורה טובה לדפדפנים בנייד. האתר הזה (html5rocks.com) הוא לא יוצא דופן. בזמן ההשקה, הקדשנו מעט מאמץ לגרסת האתר לנייד.
יצירת אתר html5rocks.com שמותאם לניידים
בתור תרגיל, חשבתי שכדאי להשתמש ב-html5rocks (אתר HTML5 קיים) ולשפר אותו באמצעות גרסה ידידותית לנייד. הדבר העיקרי שעניין אותי היה כמות העבודה המינימלית שנדרשת כדי לטרגט לטלפונים חכמים. המטרה של התרגיל שלי לא הייתה ליצור אתר חדש לגמרי לנייד ולנהל שתי גרסאות של קוד. זה היה לוקח לנצח והיה בזבוז זמן עצום. כבר הגדרנו את המבנה של האתר (תגי עיצוב). בדקנו את המראה והתחושה (CSS). הפונקציונליות העיקרית (JS) הייתה שם. העניין הוא שהרבה אתרים נמצאים באותה סירה.
המאמר הזה מתאר איך יצרנו גרסה לנייד של html5rocks שעברו אופטימיזציה למכשירי Android ו-iOS. כדי לראות את ההבדל, פשוט טוענים את html5rocks.com במכשיר שתומך באחת ממערכת ההפעלה האלה. אין הפניות אוטומטיות לכתובת m.html5rocks.com או תרמיות אחרות מהסוג הזה. אתם מקבלים את html5rocks כמו שהוא… עם היתרון הנוסף של משהו שנראה נהדר ופועל היטב במכשיר נייד.
שאילתות מדיה של CSS
ב-HTML4 וב-CSS2 יש תמיכה בגיליונות סגנונות שתלויים במדיה במשך זמן מה. לדוגמה:
<link rel="stylesheet" media="print" href="printer.css">
יטרגט מכשירים להדפסה ויספק עיצוב ספציפי לתוכן הדף כשהדף מודפס. ב-CSS3, הרעיון של סוגי מדיה מקבל ביטוי נוסף, והפונקציונליות שלהם משופרת באמצעות שאילתות מדיה. שאילתות מדיה מגדילות את התועלת של סוגי מדיה בכך שהן מאפשרות להוסיף תוויות מדויקות יותר לגיליונות סגנונות. כך אפשר להתאים אישית את הצגת התוכן למגוון ספציפי של מכשירי פלט, בלי לשנות את התוכן עצמו. זה נשמע מושלם לפריסת אתר קיימת שצריך לשנות.
אפשר להשתמש בשאילתות מדיה במאפיין media
של גיליונות סגנון חיצוניים כדי לטרגט את רוחב המסך, רוחב המכשיר, כיוון וכו'. לרשימה המלאה, עיינו במפרט שאילתת המדיה של W3C.
טירגוט לפי גדלי מסכים
בדוגמה הבאה, הערך phone.css
יחול על מכשירים שנחשבים "ידניים" ל"נייד" או למכשירים עם מסכים ברוחב <= 320px.
<link rel='stylesheet'
media='handheld, only screen and (max-device-width: 320px)' href='phone.css'>
הוספת מילת המפתח only
כתחילית לשאילתות מדיה תגרום לדפדפנים שלא תואמים ל-CSS3 להתעלם מהכלל.
הקריטריונים הבאים יגדירו טירגוט למסכים בגודל שבין 641 פיקסלים ל-800 פיקסלים:
<link rel='stylesheet'
media='only screen and (min-width: 641px) and (max-width: 800px)' href='ipad.css'>
שאילתות מדיה יכולות להופיע גם בתוך תגי <style>
בשורה. הטירגוט הבא מתייחס לסוגי המדיה all
כשהם בפורמט לאורך:
<style>
@media only all and (orientation: portrait) { ... }
</style>
media="handheld"
אנחנו צריכים לעצור לרגע ולדון בנושא media="handheld"
.
עובדה: ב-Android וב-iOS מתעלמים מ-media="handheld"
. לטענת המבקרים, המשתמשים יפסידו את התוכן ברמה הגבוהה שמספק גיליון סגנונות שמטרגט את media="screen"
, ויש פחות סיכוי שהמפתחים יטפלו בגרסה media="handheld"
באיכות נמוכה יותר. לכן, כחלק מהמוטו 'אינטרנט מלא', רוב הדפדפנים המודרניים לסמארטפונים פשוט מתעלמים מגיליונות סגנונות לנייד.
מומלץ להשתמש בתכונה הזו כדי לטרגט מכשירים ניידים, אבל דפדפנים שונים הטמיעו אותה בדרכים שונות:
- חלק מהמכשירים קוראים רק את גיליון הסגנונות לנייד.
- חלק מהדפדפנים קוראים רק את גיליון הסגנונות לנייד, אם יש כזה, אבל אם לא, הם משתמשים כברירת מחדל בגיליון הסגנונות למסך.
- חלק מהמכשירים קוראים גם את גיליון הסגנונות לנייד וגם את גיליון הסגנונות למסך.
- בחלקם קוראים רק את גיליון הסגנונות של המסך.
Opera Mini לא מתעלמת מ-media="handheld"
. כדי לגרום ל-Windows Mobile לזהות את media="handheld"
, צריך להשתמש באותיות רישיות בערך של מאפיין המדיה של גיליון סגנונות המסך:
<!-- media="handheld" trick for Windows Mobile -->
<link rel="stylesheet" href="screen.css" media="Screen">
<link rel="stylesheet" href="mobile.css" media="handheld">
איך אתר html5rocks משתמש בבקשות מדיה
נעשה שימוש רב בשאילתות מדיה ב-html5rocks לנייד. הם אפשרו לנו לשנות את הפריסה בלי לבצע שינויים משמעותיים בסימון התבנית של Django… פשוט הצילו אותנו! בנוסף, התמיכה שלהם בדפדפנים השונים טובה למדי.
ב-<head>
של כל דף תראו את גיליונות הסגנון הבאים:
<link rel='stylesheet'
media='all' href='/static/css/base.min.css' />
<link rel='stylesheet'
media='only screen and (max-width: 800px)' href='/static/css/mobile.min.css' />
base.css
תמיד הגדיר את המראה והתחושה הראשיים של html5rocks.com, אבל עכשיו אנחנו מחילים סגנונות חדשים (mobile.css
) על רוחב מסך של פחות מ-800px. שאילתה המדיה שלו מכסה טלפונים חכמים (כ-320 פיקסלים) ו-iPad (כ-768 פיקסלים).
ההשפעה: אנחנו מחליפים בהדרגה את הסגנונות ב-base.css
(רק לפי הצורך) כדי לשפר את המראה של הממשק בנייד.
חלק מהשינויים בסגנון שהקובץ mobile.css
אוכף:
- צמצום של רווחים או מרווח פנימי מיותרים באתר. במסכים קטנים, המקום מוגבל!
- מתבצעת הסרה של
:hover
מצבים. הם אף פעם לא יוצגו במכשירי מגע. - שינוי הפריסה לעמודה אחת. בהמשך נסביר על כך.
- הסרת ה-
box-shadow
סביב ה-div הראשי של מאגר האתר. צללי תיבות גדולים פוגעים בביצועי הדף. - נעשה שימוש במודל של תיבת CSS גמישה
box-ordinal-group
כדי לשנות את הסדר של כל קטע בדף הבית. תוכלו לראות שהקטע 'לימוד לפי קבוצות עיקריות של תכונות HTML5' מופיע לפני הקטע 'מדריכים' בדף הבית, אבל אחריו בגרסה לנייד. הסדר הזה הגיוני יותר בנייד ולא נדרש בו שינוי ברכיבי ה-Markup. CSS flexbox FTW! - הסרת השינויים ב-
opacity
. שינוי ערכי האלפא גורם לירידה בביצועים בנייד.
מטא תגים לנייד
Mobile WebKit תומך בכמה תכונות שמספקות למשתמשים חוויית גלישה טובה יותר במכשירים מסוימים.
הגדרות אזור התצוגה
הגדרת המטא הראשונה (וזו שבה משתמשים בתדירות הגבוהה ביותר) היא מאפיין אזור התצוגה. הגדרת אזור תצוגה מאפשרת לדפדפן לדעת איך התוכן צריך להתאים למסך של המכשיר, ומציינת לדפדפן שהאתר מותאם לניידים. לדוגמה:
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
היא מנחה את הדפדפן להגדיר את אזור התצוגה לרוחב המכשיר, עם סולם ראשוני של 1. דוגמה זו מאפשרת גם שינוי מרחק התצוגה, פעולה שאולי מתאימה לאתר אינטרנט אבל לא לאפליקציית אינטרנט. נוכל למנוע הגדלה של user-scalable=no
או להגביל את ההתאמה לרמה מסוימת:
<meta name=viewport
content="width=device-width, initial-scale=1.0, minimum-scale=0.5 maximum-scale=1.0">
Android מרחיב את המטא-תג של אזור התצוגה ומאפשר למפתחים לציין את רזולוציית המסך שלגביה האתר פותח:
<meta name="viewport" content="target-densitydpi=device-dpi">
הערכים האפשריים של target-densitydpi
הם device-dpi
, high-dpi
, medium-dpi
, low-dpi
.
אם רוצים לשנות את דף האינטרנט בהתאם לצפיפות מסך שונה, משתמשים בשאילתת המדיה מסוג CSS -webkit-device-pixel-ratio
ו/או במאפיין window.devicePixelRatio
ב-JavaScript, ולאחר מכן מגדירים את מאפיין המטא target-densitydpi
לערך device-dpi
. כך מערכת Android לא תשנה את הגודל של דף האינטרנט, ותוכלו לבצע את השינויים הנדרשים לכל צפיפות באמצעות CSS ו-JavaScript.
מידע נוסף על טירגוט לפי רזולוציות של מכשירים זמין במסמכי התיעוד של Android בנושא WebView.
גלישה במסך מלא
יש עוד שני ערכי מטא שהם iOS-sfic. apple-mobile-web-app-capable
ו-apple-mobile-web-app-status-bar-style
יריצו את תוכן הדף במצב מסך מלא כמו אפליקציה ויהפכו את שורת הסטטוס לשקופה:
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
לקבלת מידע נוסף על כל אפשרויות המטא הזמינות, עיינו במאמרי העזרה של Safari.
סמלים במסך הבית
מכשירי iOS ו-Android מקבלים גם את הקידומת rel="apple-touch-icon"
(iOS) ואת הקידומת rel="apple-touch-icon-precomposed"
(Android) לקישורים. הם יוצרים סמל נוצץ דמוי אפליקציה במסך הבית של המשתמש כשהם מוסיפים את האתר לסימניות:
<link rel="apple-touch-icon"
href="/static/images/identity/HTML5_Badge_64.png" />
<link rel="apple-touch-icon-precomposed"
href="/static/images/identity/HTML5_Badge_64.png" />
איך html5rocks משתמשים במטא תגים לנייד
כדי לסכם את כל מה שאמרנו, הנה קטע קוד מהקטע <head>
ב-html5rocks:
<head>
...
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
<link rel="apple-touch-icon"
href="/static/images/identity/HTML5_Badge_64.png" />
<link rel="apple-touch-icon-precomposed"
href="/static/images/identity/HTML5_Badge_64.png" />
...
</head>
פריסה אנכית
במסכים קטנים, הרבה יותר נוח לגלול אנכית מאשר אופקית. מומלץ להציג את התוכן בפריסה אנכית בעמודה אחת בנייד. באתר html5rocks, השתמשנו בשאילתות מדיה מסוג CSS3 כדי ליצור פריסה כזו. שוב, בלי לשנות את ה-Markup.
אופטימיזציה לנייד
רוב האופטימיזציות שביצענו הן פעולות שצריך היה לבצע מלכתחילה. למשל, צמצום מספר בקשות הרשת, דחיסת JS/CSS, gzipping (זמין בחינם ב-App Engine) וצמצום מניפולציות DOM. הטכניקות האלה הן שיטות מומלצות נפוצות, אבל לפעמים הן לא נלקחות בחשבון כשרוצים להפעיל אתר במהירות.
הסתרה אוטומטית של סרגל הכתובות
בדפדפנים לנייד אין את שטח המסך שיש בדפדפנים למחשב. גרוע מכך, בפלטפורמות שונות לפעמים מופיעה סרגל כתובות גדול בחלק העליון של המסך… גם אחרי שהדף מסיים להיטען.
דרך קלה אחת להתמודד עם הבעיה היא לגלול בדף באמצעות JavaScript.
אפילו אם תעשו זאת בפיקסל אחד, סרגל הכתובות יסומן.
כדי להסתיר בכוח את סרגל הכתובות ב-html5rocks, צרפתי לטפל באירועים מסוג onload
לאובייקט window
וגלשתי את הדף אנכית בפיסקל אחד:
// Hides mobile browser's address bar when page is done loading.
window.addEventListener('load', function(e) {
setTimeout(function() { window.scrollTo(0, 1); }, 1);
}, false);
בנוסף, עטפנו את המאזין הזה במשתנה התבנית is_mobile
, כי אין צורך בו במחשב.
צמצום מספר הבקשות לרשת, חיסכון ברוחב הפס
העובדה שאתם יודעים שהפחתת מספר בקשות ה-HTTP יכולה לשפר משמעותית את הביצועים. במכשירים ניידים יש הגבלה נוספת על מספר החיבורים בו-זמנית שהדפדפן יכול ליצור, ולכן אתרים לנייד ירוויחו עוד יותר מהפחתת הבקשות הלא נחוצות האלה. בנוסף, הסרה של כל בייט היא קריטית, כי רוחב הפס מוגבל בדרך כלל בטלפונים. יכול להיות שאתם גורמים למשתמשים להוציא כסף!
ריכזנו כאן כמה מהגישות שלנו לצמצום בקשות הרשת ולהפחתת רוחב הפס ב-html5rocks:
הסרת iframes - iframes איטיים! חלק גדול מהזמן שחלף מהקליק להצגת הדף נובע מווידג'טים של צד שלישי לשיתוף (Buzz, Google Friend Connect, Twitter, Facebook) בדפי ההדרכה. ממשקי ה-API האלה נכללו באמצעות תגי
<script>
ויוצרים iframes שמפחיתים את מהירות הדף. הווידג'טים הוסרו מהנייד.display:none
– במקרים מסוימים, הוסתרנו את ה-Markup אם הוא לא התאים לפרופיל בנייד. דוגמה טובה לכך היא ארבעת התיבות העגולות בחלק העליון של דף הבית:
הם חסרים באתר לנייד. חשוב לזכור שהדפדפן עדיין שולח בקשה לכל סמל, למרות שהמאגר שלהם מוסתר באמצעות display:none
. לכן, לא מספיק פשוט להסתיר את הלחצנים האלה. לא רק שזה יהיה בזבוז של רוחב פס, אלא שהמשתמש לא ייהנה מהרוחב הפס הזה. הפתרון היה ליצור משתנה בוליאני בשם 'is_mobile' בתבנית Django כדי להשמיט קטעי HTML באופן מותנה.
כשהמשתמש צופה באתר במכשיר חכם, הלחצנים לא מוצגים.
מטמון אפליקציה – הוא לא רק מספק לנו תמיכה במצב אופליין, אלא גם מאפשר הפעלה מהירה יותר.
דחיסת CSS/JS – אנחנו משתמשים ב-YUI compressor במקום ב-Closure compiler, בעיקר כי הוא מטפל גם ב-CSS וגם ב-JS. אחת הבעיות שבהן נתקלנו היא ששאילתות מדיה בקוד (שאילתות מדיה שמופיעות בתוך גיליון סגנונות) גרמו לבעיה ב-YUI compressor 2.4.2 (ראו הבעיה הזו). הבעיה נפתרה באמצעות YUI Compressor מגרסה 2.4.4 ואילך.
שימוש ב-CSS sprites של תמונות כשהדבר אפשרי.
נעשה שימוש ב-pngcrush לדחיסת תמונות.
השתמשת במזהי dataURI לתמונות קטנות. קידוד Base64 מוסיף לתמונה כ-30% יותר גודל, אבל חוסך את בקשת הרשת.
חיפוש Google בהתאמה אישית נטען באופן אוטומטי באמצעות תג סקריפט יחיד, במקום לטעון אותו באופן דינמי באמצעות
google.load()
. האפשרות השנייה שולחת בקשה נוספת.
<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
- מדפסת הקוד והספרייה Modernizr נכללו בכל דף, גם אם אף פעם לא השתמשו בהם. Modernizr נהדר, אבל הוא מפעיל כמה בדיקות בכל טעינת דף. חלק מהבדיקות האלה מבצעות שינויים יקרים ב-DOM ומאטות את טעינת הדף. עכשיו אנחנו כוללים את הספריות האלה רק בדפים שבהם הן נחוצות בפועל. -2 בקשות :)
שיפורים נוספים בביצועים:
- העברנו את כל ה-JavaScript לתחתית הדף (אם אפשר).
- הוסרו תגי
<style>
בשורה. - חיפושים של DOM ששמורים במטמון ופעולות מניפולציה מינימליות ב-DOM – בכל פעם שמזיזים את DOM, הדפדפן מבצע זרימה מחדש. התאמות גופן מחדש הן יקרות עוד יותר במכשיר נייד.
- העברת קוד מיותר בצד הלקוח לשרת. באופן ספציפי, התיבה 'לבדיקה' מגדירה את סגנון הניווט של הדף הנוכחי:
js var lis = document.querySelectorAll('header nav li'); var i = lis.length; while (i--) { var a = lis[i].querySelector('a'); var section = a.getAttribute("data-section"); if (new RegExp(section).test(document.location.href)) { a.className = 'current'; } }
- רכיבים עם רוחב קבוע הוחלפו ברכיבים גמישים מסוג
width:100%
אוwidth:auto
.
מטמון האפליקציה
בגרסה לנייד של html5rocks נעשה שימוש בApplication Cache כדי לזרז את הטעינה הראשונית ולאפשר למשתמשים לקרוא תוכן במצב אופליין.
כשמטמיעים את AppCache באתר, חשוב מאוד לא לשמור בקובץ המניפסט (באופן מפורש בקובץ המניפסט עצמו או באופן משתמע באמצעות כותרות בקרה כבדות של מטמון). אם הדפדפן מאחסן את המניפסט במטמון, תהיה לכם עבודה קשה לנפות באגים. מערכת iOS ו-Android מאחסנות את הקובץ הזה במטמון בצורה טובה במיוחד, אבל אין בהן דרך נוחה לנקות את המטמון כמו בדפדפנים למחשב.
כדי למנוע את האחסון במטמון של האתר שלנו, קודם כל הגדרנו ל-App Engine אף פעם לא לאחסן קובצי מניפסט במטמון:
- url: /(.*\.(appcache|manifest))
static_files: \1
mime_type: text/cache-manifest
upload: (.*\.(appcache|manifest))
expiration: "0s"
שנית, השתמשנו ב-JS API כדי להודיע למשתמש כשההורדה של המניפסט החדש מסתיימת. הם מתבקשים לרענן את הדף:
window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
window.applicationCache.swapCache();
if (confirm('A new version of this site is available. Load it?')) {
window.location.reload();
}
}
}, false);
כדי לחסוך בתעבורת נתונים ברשת, חשוב להשתמש במניפסט פשוט. כלומר, אל תציינו כל דף באתר. פשוט מציינים את קובצי התמונות, ה-CSS וה-JavaScript החשובים. הדבר האחרון שאתם רוצים לעשות הוא לאלץ את הדפדפן בנייד להוריד מספר גדול של נכסים בכל עדכון של המטמון לאפליקציה. במקום זאת, צריך לזכור שהדפדפן ישמור דף HTML במטמון באופן לא מפורש כשהמשתמש מבקר באתר (והוא כולל את המאפיין <html manifest="...">
).