مقدمه
توسعه برای وب تلفن همراه این روزها موضوع داغی است. امسال، برای اولین بار، فروش تلفنهای هوشمند از رایانههای شخصی پیشی گرفت. کاربران بیشتر و بیشتری از دستگاه همراه برای گشتوگذار در وب استفاده میکنند، یعنی بهینهسازی سایتها برای مرورگرهای تلفن همراه برای توسعهدهندگان حیاتی میشود.
میدان نبرد «تلفن همراه» هنوز برای تعداد زیادی از توسعهدهندگان قلمرویی ناشناخته است. بسیاری از افراد سایتهای قدیمی دارند که کاربران تلفن همراه را کاملاً نادیده میگیرند. درعوض، سایت در درجه اول برای مرور در رایانه طراحی شده است و در مرورگرهای تلفن همراه بهخوبی نمایش داده نمیشود. این سایت (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 برای دستگاههایی اعمال میشود
که مرورگر آنها را «دستی» درنظر میگیرد یا دستگاههایی که عرض صفحهنمایش آنها کمتر از ۳۲۰ پیکسل است.
<link rel='stylesheet'
media='handheld, only screen and (max-device-width: 320px)' href='phone.css'>
افزودن پیشوند به پُرسمانهای رسانه با کلیدواژه «only» باعث میشود
مرورگرهای ناسازگار با CSS3 قانون را نادیده بگیرند.
مورد زیر اندازه صفحهنمایش بین ۶۴۱ پیکسل و ۸۰۰ پیکسل را هدف قرار میدهد:
<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) را برای عرضهای صفحه زیر ۸۰۰ پیکسل اعمال میکنیم. پرسوجوی رسانهای آن تلفنهای هوشمند (~۳۲۰ پیکسل) و iPad (~۷۶۸ پیکسل) را پوشش میدهد.
نتیجه: ما بهتدریج سبکها را در base.css لغو میکنیم (فقط درصورت لزوم)
تا ظاهر موارد در تلفن همراه بهتر شود.
برخیاز تغییرات سبک که mobile.css اعمال میکند:
- فاصله سفید/حاشیه داخلی اضافی را در سراسر سایت کاهش میدهد. صفحهنمایشهای کوچک یعنی فضا محدود است!
:hoverایالت را برمیدارد. این دکمهها هرگز در دستگاههای لمسی دیده نخواهند شد.- چیدمان را بهصورت تکستونی تنظیم میکند. بعداً دراینباره بیشتر خواهید شنید.
box-shadowرا از اطراف div محفظه اصلی سایت برمیدارد. سایههای جعبه بزرگ عملکرد صفحه را کاهش میدهد.- از مدل جعبه انعطافپذیر CSS
box-ordinal-groupبرای تغییر ترتیب هر بخش در صفحه اصلی استفاده کردیم. متوجه خواهید شد که «LEARN BY MAJOR HTML5 FEATURE GROUPS» (یادگیری براساس گروههای اصلی ویژگیهای HTML5) در صفحه اصلی قبلاز بخش «TUTORIALS» (آموزشها) قرار دارد اما در نسخه تلفن همراه بعداز آن قرار دارد. این ترتیب برای تلفن همراه منطقیتر بود و نیازی به تغییر نشانهگذاری نداشت. CSS flexbox FTW! opacityتغییر را برمیدارد. تغییر مقادیر آلفا بر عملکرد در تلفن همراه تأثیر میگذارد.
متا تگهای تلفن همراه
Mobile WebKit از چند ویژگی خوب پشتیبانی میکند که تجربه مرور بهتری را در برخی دستگاهها به کاربران ارائه میدهد.
تنظیمات ناحیه نمایش
اولین تنظیم متا (و تنظیمی که بیشتر از همه استفاده خواهید کرد) ویژگی ناحیه نمایش است. تنظیم ناحیه نمایش به مرورگر میگوید که محتوا چگونه باید در صفحهنمایش دستگاه جا شود و به مرورگر اطلاع میدهد که سایت برای تلفن همراه بهینهسازی شده است. برای مثال:
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
به مرورگر میگوید که نمای هدف را روی عرض دستگاه با مقیاس اولیه ۱ تنظیم کند. این مثال همچنین امکان بزرگنمایی را فراهم میکند، چیزی که ممکن است برای یک وبسایت مطلوب باشد اما برای یک برنامه وب نه. میتوانیم با 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.
اگر میخواهید صفحه وب خود را برای تراکمهای مختلف صفحه تغییر دهید، از
-webkit-device-pixel-ratio پرسمان رسانه CSS و/یا ویژگی window.devicePixelRatio
در جاوا اسکریپت استفاده کنید، سپس ویژگی متا target-densitydpi
را روی device-dpi تنظیم کنید. این کار باعث میشود Android مقیاسبندی را در صفحه وب شما انجام ندهد و به شما امکان میدهد تنظیمات لازم را برای هر تراکم ازطریق CSS و جاوا اسکریپت انجام دهید.
برای اطلاعات بیشتر درباره هدفیابی وضوح دستگاه، اسناد WebView Android را ببینید.
مرور تمامصفحه
دو مقدار متا دیگر وجود دارد که 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 برای ایجاد چنین چیدمانی استفاده کردیم. دوباره، بدون تغییر نشانگذاری.
بهینهسازیهای تلفن همراه
بیشتر بهینهسازیهایی که انجام دادیم کارهایی هستند که باید در همان ابتدا انجام میشدند. کارهایی مثل کاهش تعداد درخواستهای شبکه، فشردهسازی JS/CSS، فشردهسازی gzip (بهطور رایگان در App Engine ارائه میشود)، و بهحداقل رساندن دستکاریهای DOM. این تکنیکها روالهای مطلوب رایج هستند اما گاهی اوقات هنگام عجله برای راهاندازی سایت نادیده گرفته میشوند.
پنهان کردن خودکار نوار نشانی
مرورگرهای تلفن همراه فاقد فضای صفحه همتای رایانهای خود هستند. بدتر از همه اینکه در پلاتفرمهای مختلف، گاهی اوقات با یک نوار نشانی بزرگ و قدیمی در بالای صفحه مواجه میشوید… حتی پساز اینکه بار کردن صفحه تمام شده است.
یک راه آسان برای مقابله با آن، پیمایش صفحه بااستفاده از جاوا اسکریپت است.
حتی اگر این کار را با یک پیکسل انجام دهید، نوار نشانی مزاحم برطرف خواهد شد.
برای پنهان کردن اجباری نوار نشانی در 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 اتخاذ کردیم آورده شده است:
برداشتن iframe - iframe کند است! بخش زیادی از تأخیر ما ناشی از ابزارهای همرسانی شخص ثالث (Buzz، Google Friend Connect، توییتر، فیسبوک) در صفحههای آموزشی بود. این میاناهای برنامهسازی کاربردی ازطریق برچسبهای
<script>اضافه شدهاند و iframeهایی ایجاد میکنند که سرعت صفحه را کاهش میدهد. ابزارهها برای تلفن همراه برداشته شدند.display:none- در برخی موارد، اگر نشانهگذاری با نمایه تلفن همراه مطابقت نداشت، آن را پنهان میکردیم. یک نمونه خوب، چهار چارگوش گردشده در بالای صفحه اصلی بود:
در سایت تلفن همراه وجود ندارند. باید بهخاطر داشته باشید که
مرورگر همچنان برای هر نماد درخواست ارسال میکند، بااینکه محفظه آنها
با display:none پنهان شده است. بنابراین، صرفاً پنهان کردن این دکمهها کافی نبود. این کار نه تنها باعث هدر رفتن پهنای باند میشود، بلکه کاربر حتی نتیجه این پهنای باند هدررفته را نخواهد دید! راهحل این بود که یک
بولی «is_mobile» در الگوی Django خود ایجاد کنیم تا بخشهایی از HTML را بهصورت شرطی حذف کنیم.
وقتی کاربر سایت را در دستگاه هوشمند مشاهده میکند، دکمهها حذف میشوند.
حافظه نهان برنامه - این کار نهتنها پشتیبانی آفلاین را برای ما فراهم میکند، بلکه راهاندازی سریعتری نیز ایجاد میکند.
فشردهسازی CSS/JS - ما بهجای کامپایلر Closure از فشردهساز YUI استفاده میکنیم، عمدتاً به این دلیل که هم CSS و هم JS را مدیریت میکند. یکی از مشکلاتی که با آن مواجه شدیم این بود که پُرسمانهای رسانه درونخطی (پُرسمانهای رسانهای که در برگه سبک نگارش ظاهر میشوند) در YUI compressor 2.4.2 دچار مشکل شدند (به این مشکل مراجعه کنید). استفاده از YUI Compressor 2.4.4+ مشکل را برطرف کرد.
درصورت امکان، از CSS image sprites استفاده شده است.
از pngcrush برای فشردهسازی تصویر استفاده شد.
از dataURIs برای تصاویر کوچک استفاده شده است. کدگذاری پایه ۶۴ حدود ۳۰٪+ به اندازه تصویر اضافه میکند اما درخواست شبکه را ذخیره میکند.
«جستجوی سفارشی Google» بهجای بار کردن پویا با
google.load()، بااستفاده از یک برچسب دستورگان بهطور خودکار بار شد. مورد دوم درخواست اضافهای ایجاد میکند.
<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
- کد pretty printer و Modernizr ما در هر صفحه گنجانده شده بود، حتی اگر هرگز استفاده نشده بود. Modernizr عالی است، اما در هر بارگذاری، یک سری آزمایش اجرا میکند. برخیاز این آزمایشها تغییرات پرهزینهای در DOM ایجاد میکنند و بار شدن صفحه را کند میکنند. اکنون، این کتابخانهها را فقط در صفحههایی که واقعاً به آنها نیاز است اضافه میکنیم. -۲ درخواست :)
بهینهسازیهای عملکردی بیشتر:
- همه جاوا اسکریپتها را به پایین صفحه منتقل کردیم (هرجا که ممکن بود).
- برچسبهای
<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 از حافظه پنهان برنامه برای افزایش سرعت بارگیری اولیه استفاده میکند و به کاربران اجازه میدهد محتوا را بهصورت آفلاین بخوانند.
هنگام پیادهسازی 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، و
فایلهای جاوا اسکریپت را فهرست کنید. آخرین کاری که میخواهید انجام دهید این است که مرورگر تلفن همراه را مجبور کنید
در هر بهروزرسانی appcache، تعداد زیادی دارایی را بارگیری کند. درعوض، بهخاطر داشته باشید که وقتی کاربر از صفحه html بازدید میکند (و این صفحه شامل ویژگی <html manifest="..."> است)، مرورگر بهطور ضمنی آن را ذخیره میکند.