در این کد لبه، یاد خواهید گرفت که چگونه از Google Analytics و User Timeming API برای اندازه گیری عملکرد واقعی وب سایت یا برنامه خود و بهینه سازی آن برای بهبود تجربه برای کاربران خود استفاده کنید.
ابزارهایی مانند WebPagetest.org یک شروع عالی برای بهینه سازی عملکرد هستند، اما آزمون واقعی عملکرد سایت همیشه داده های واقعی کاربران واقعی است.
اگر وبسایتی دارید، به احتمال زیاد از Google Analytics برای اندازهگیری ترافیک و همچنین مواردی مانند استفاده از دستگاه و مرورگر استفاده میکنید. فقط با کمی کد اضافی می توانید معیارهای عملکرد را به ترکیب اضافه کنید.
چیزی که یاد خواهید گرفت
- نحوه اندازهگیری دقیق و مؤثر معیارهای عملکرد با استفاده از User Timings API
- چگونه آن داده ها را به Google Analytics ارسال کنیم تا بتوان آنها را در گزارش های شما گنجاند
آنچه شما نیاز دارید
- یک مرورگر با کنسول توسعه دهنده
- وب سرور برای Chrome ، یا از وب سرور دلخواه خود استفاده کنید
- کد نمونه
- یک ویرایشگر متن
- (اختیاری) یک حساب Google Analytics
چگونه از این آموزش استفاده خواهید کرد؟
تجربه خود را با ساختن وب سایت ها یا برنامه ها چگونه ارزیابی می کنید؟
می توانید تمام کدهای نمونه را در رایانه خود دانلود کنید ...
... یا مخزن GitHub را از خط فرمان کلون کنید.
git clone https://github.com/googlecodelabs/performance-analytics.git
کد نمونه به زیر شاخه هایی تقسیم می شود که با هر یک از مراحل شماره گذاری شده در این آزمایشگاه کد مطابقت دارد. میتوانید از این برای رد کردن آسان در آزمایشگاه کد یا تأیید صحت اجرای خود استفاده کنید.
اگر به یک برنامه متفاوت دسترسی دارید، می توانید از آن استفاده کنید تا ببینید دقیقاً چه چیزی از مرحله به مرحله تغییر کرده است.
در این آزمایشگاه کد، شما یک فایل HTML را می گیرید که دارایی های زیر را بارگیری می کند:
- فونت های وب
- شیوه نامه ها
- تصاویر
- جاوا اسکریپت
و شما قصد دارید کد جدیدی بنویسید که معیارهای عملکرد کلیدی را برای هر یک از این نوع دارایی ها اندازه گیری می کند.
ملاحظات عملکرد دارایی
اگر تا به حال چیزی در مورد بهینه سازی عملکرد خوانده اید، احتمالاً قبلاً می دانید که هر یک از این انواع دارایی ها ویژگی های متفاوت خود را دارند و می توانند به طرق مختلف بر عملکرد کلی درک شده تأثیر بگذارند.
CSS
به عنوان مثال، شیوه نامه ها رندر تمام عناصر موجود در DOM را که بعد از آنها می آیند مسدود می کنند، به این معنی که مرورگر باید درخواستی برای شیوه نامه ارسال کند، آن را دانلود کند و قبل از اینکه بتواند محتوای موجود در DOM را ارائه کند، آن را تجزیه کند. بعد از آن. به همین دلیل، معمولاً بهتر است شیوه نامه ها را در <head> سند قرار دهید. و به دلیل ماهیت مسدود کننده CSS، اغلب توصیه می شود که CSS مهم خود را فقط در <head> قرار دهید و CSS غیر بحرانی را به صورت ناهمزمان بارگذاری کنید.
جاوا اسکریپت
از طرف دیگر جاوا اسکریپت رندر را مسدود نمی کند، اما تجزیه و ساخت DOM را مسدود می کند. این امر ضروری است زیرا جاوا اسکریپت میتواند DOM را تغییر دهد، به این معنی که هر زمان که مرورگر تگ <script> را میبیند (به استثنای اسکریپتهای همگامسازی)، باید کد را قبل از ادامه روی تگ بعدی اجرا کند. اگر تگ <script> به یک فایل جاوا اسکریپت خارجی ارجاع می دهد، باید قبل از ادامه کار، کد را دانلود و اجرا کند.
به همین دلیل اغلب توصیه می شود که جاوا اسکریپت شما درست قبل از بسته شدن برچسب </body> بارگیری شود، بنابراین اکثر DOM در سریع ترین زمان ممکن در دسترس است.
فونت های وب
اگر فونتهای وب را بارگیری میکنید، ممکن است تا زمانی که فونت برای استفاده در دسترس نباشد، نمایش سند را مسدود کنید. در این مورد، بسیار مهم است که بفهمید این واقعا چقدر برای کاربران شما طول می کشد. یک فونت وب ممکن است برای شما سریع بار شود اما برای اکثر افرادی که از سایت شما بازدید می کنند بسیار آهسته است. به همین دلیل است که اندازه گیری و تصمیم گیری بر روی داده های واقعی بسیار مهم است.
تصاویر
در نهایت، تصاویر واقعاً میتوانند یک سایت را زنده کنند، اما اغلب زمان بارگذاری آنها بیشتر میشود. درک اینکه این واقعاً به چه معناست و توانایی تشخیص هر گونه همبستگی بین الگوهای استفاده و زمان بارگذاری صفحه برای درک نحوه بهینه سازی بسیار مهم است.
اولین قدم در این آزمایشگاه کد این است که قبل از افزودن هر کد اندازه گیری عملکرد، ببینید صفحه نمایشی چگونه به نظر می رسد.
برای مشاهده دمو، یک پوشه جدید ایجاد کنید و یک فایل داخل آن به نام index.html اضافه کنید. سپس کد زیر را کپی کرده و در فایل index.html قرار دهید.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Performance Analytics Demo</title>
<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->
<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Roboto, sans-serif; margin: 1em; }
img { float: left; height: auto; width: 33.33%; }
.gallery { overflow: hidden; }
</style>
<!-- End CSS -->
</head>
<body>
<div class="container">
<!-- Start images -->
<div class="gallery">
<img src="http://lorempixel.com/380/200/animals/1/">
<img src="http://lorempixel.com/380/200/animals/2/">
<img src="http://lorempixel.com/380/200/animals/3/">
</div>
<!-- End images -->
<h1>Performance Analytics Demo</h1>
<p>Real performance data from real users.</p>
</div>
<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!-- End JavaScript -->
</body>
</html>
سپس، Web Server را برای Chrome باز کنید و یک سرور محلی را در فهرستی که ایجاد کرده اید راه اندازی کنید. مطمئن شوید که "نمایش خودکار index.html" علامت زده شده است.
اکنون باید بتوانید در مرورگر خود به http://127.0.0.1:8887/ بروید و فایل آزمایشی را ببینید. باید چیزی شبیه به این باشد:
هنگامی که صفحه دمو را اجرا کردید، لحظه ای به کد نگاه کنید و همه انواع دارایی های مختلف در حال بارگذاری را مشاهده کنید. در چند مرحله بعدی، کدی را برای اندازهگیری زمانی که این داراییها بارگیری میشوند اضافه میکنید و کاربر میتواند با آنها تعامل داشته باشد.
همانطور که در بخش ملاحظات عملکرد دارایی قبلا ذکر شد، CSS رندر عناصر DOM و همچنین اجرای اسکریپت هایی را که بعد از آن در DOM می آیند را مسدود می کند.
فایل دمویی که ایجاد کردید حاوی CSS زیر است که به Bootstrap و چند سبک درون خطی اشاره دارد.
<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Roboto, sans-serif; margin: 1em; }
img { float: left; height: auto; width: 33.33%; }
.gallery { overflow: hidden; }
</style>
<!-- End CSS -->
از آنجایی که CSS هم رندر عناصر DOM و هم اجرای اسکریپت ها را مسدود می کند، می توان تعیین کرد که چه زمانی CSS مسدود شده است با افزودن یک تگ <script>
بلافاصله بعد از CSS که زمان فعلی را ذخیره می کند.
شما می توانید این کار را با ایجاد یک متغیر و اختصاص new Date()
به آن انجام دهید، اما به لطف User Timings API ، راه بسیار ساده تری وجود دارد: روش performance.mark
.
برای علامت گذاری زمانی که CSS برای مسدود کردن اجرای هر دو رندر و اسکریپت تمام شده است، خط کد زیر را بلافاصله قبل از بسته شدن نظر <!-- End CSS -->
اضافه کنید.
<script>performance.mark('css:unblock');</script>
متد performance.mark
دقیقاً در این نقطه زمانی یک مهر زمانی با وضوح بالا ایجاد میکند و آن را با هر نامی که به روش داده شده است مرتبط میکند. در این مورد شما علامت را "css:unblock" نام گذاری کرده اید.
روش performance.mark
همگام با روش performance.measure
است که برای محاسبه اختلاف زمانی بین دو علامت استفاده میشود (علاوه بر علامتهایی که میزنید، میتوانید از علائمی که مرورگر به طور خودکار برای نقاط مختلف ایجاد میکند نیز استفاده کنید. در Navigation Timing API ).
تابع ابزار زیر مدت زمان بین علامتی که اضافه کردهاید و علامت پاسخ پایان ایجاد شده توسط Navigation Timing API را اندازهگیری میکند و برمیگرداند.
function measureDuration(mark, opt_reference) {
var reference = opt_reference || 'responseEnd';
var name = reference + ':' + mark;
// Clears any existing measurements with the same name.
performance.clearMeasures(name);
// Creates a new measurement from the reference point to the specified mark.
// If more than one mark with this name exists, the most recent one is used.
performance.measure(name, reference, mark);
// Gets the value of the measurement just created.
var measure = performance.getEntriesByName(name)[0];
// Returns the measure duration.
return measure.duration;
}
برای شروع استفاده از این تابع ابزار، یک فایل جدید با نام perf-analytics.js
(در همان دایرکتوری فایل index.html
) ایجاد کنید و کد بالا را کپی و در آن قرار دهید.
اکنون که این تابع تعریف شده است، می توانید آن را فراخوانی کرده و نام علامت "css:unblock" را ارسال کنید. برای اینکه با بارگذاری منابع دیگر تداخل نداشته باشید، باید اجرای این اندازهگیریها را تا زمانی که رویداد بارگذاری پنجره روشن شود، به تعویق بیندازید.
هنگامی که تابعی را برای فراخوانی این کد نوشتید، فایل perf-analytics.js
شما باید چیزی شبیه به این باشد:
window.onload = function() {
measureCssUnblockTime();
};
/**
* Calculates the time duration between the responseEnd timing event and when
* the CSS stops blocking rendering, then logs that value to the console.
*/
function measureCssUnblockTime() {
console.log('CSS', 'unblock', measureDuration('css:unblock'));
}
/**
* Accepts a mark name and an optional reference point in the navigation timing
* API and returns the time duration between the reference point and the last
* mark (chronologically).
* @param {string} mark The mark name.
* @param {string=} opt_reference An optional reference point from the
* navigation timing API. Defaults to 'responseEnd'.
* @return {number} The time duration
*/
function measureDuration(mark, opt_reference) {
var reference = opt_reference || 'responseEnd';
var name = reference + ':' + mark;
// Clears any existing measurements with the same name.
performance.clearMeasures(name);
// Creates a new measurement from the reference point to the specified mark.
// If more than one mark with this name exists, the most recent one is used.
performance.measure(name, reference, mark);
// Gets the value of the measurement just created.
var measure = performance.getEntriesByName(name)[0];
// Returns the measure duration.
return measure.duration;
}
در نهایت، باید اسکریپت perf-analytics.js
را از index.html
بارگیری کنید. برای انجام این کار، تگ اسکریپت زیر را به سند اصلی خود اضافه کنید. مطمئن شوید که آن را آخرین بار اضافه کنید تا با بارگیری منابع دیگر تداخل نداشته باشد.
<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->
پس از تکمیل این مرحله، کد شما باید با آنچه در فهرست 01-css
مخزن آزمایشگاه کد وجود دارد مطابقت داشته باشد.
اگر صفحه را در مرورگر بارگذاری کنید و کنسول توسعه دهنده را باز کنید، باید چیزی شبیه خروجی زیر مشاهده کنید:
فونت های وب معمولاً از طریق یک شیوه نامه خارجی بارگذاری می شوند، همانطور که در فایل آزمایشی اولیه مشاهده می شود:
<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->
از آنجایی که این یک تگ <link>
به یک فایل CSS است، ممکن است به نظر برسد که تعیین زمان بارگیری و آماده استفاده فونت ها به سادگی اضافه کردن یک علامت در داخل یک تگ <script>
بلافاصله پس از <link>
است، درست مانند مرحله 1.
متاسفانه، به این سادگی نیست.
Stylesheets اجرای جاوا اسکریپت را مسدود می کند زیرا محتویات شیوه نامه ها برای ساخت CSSOM استفاده می شود و از آنجایی که ممکن است جاوا اسکریپت در حال بارگیری نیاز به دسترسی به CSSOM داشته باشد، اجرا باید تا زمانی که CSSOM به طور کامل ساخته شود به تعویق بیفتد.
نکته مهم این است که مرورگر می تواند بدون بارگیری فونت، CSSOM را بسازد، به این معنی که اگر علامتی را از طریق یک تگ اسکریپت درون خطی به DOM بلافاصله بعد از تگ <link> stylesheet فونت اضافه کنید، این احتمال وجود دارد که علامت قبل از فونت به طور کامل بارگذاری شده است.
تا زمانی که رویدادهای بارگذاری فونت در مرورگرها در دسترس قرار گیرند، جاوا اسکریپت برای تعیین اینکه یک فونت واقعاً فعال و آماده استفاده در صفحه است، مورد نیاز است. خوشبختانه، بارگذاری فونت ها از طریق جاوا اسکریپت نیز یک برد عملکردی است، زیرا نیازی به درخواست مسدود کردن اضافی برای یک فایل CSS ندارد.
بیشتر فونتهای وب (از جمله فونتهای Google، typekit و فونتهای font.com) را میتوان از طریق اسکریپت webfont.js که توسط Google و Typekit توسعه داده شده است بارگیری کرد.
برای به روز رسانی سند اصلی برای استفاده از webfont.js برای بارگیری فونت ها (به جای تگ <link>)، بخش فونت های کد را با موارد زیر جایگزین کنید:
<!-- Start fonts -->
<script>
window.WebFontConfig = {
google: {families: ['Roboto:400,700,400italic']},
timeout: 10000,
active: function() {
performance.mark('fonts:active');
}
};
</script>
<script async src="https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
<!-- End fonts -->
دو نکته مهم در مورد کد بالا وجود دارد:
- این یک علامت "fonts:active" در پاسخ به تماس فعال ایجاد می کند، بنابراین می توانید بعداً مدت زمان بارگیری فونت ها را اندازه بگیرید.
- تگ
<script>
که webfonts.js را بارگیری می کند حاوی ویژگیasync
است، بنابراین تجزیه یا رندر بقیه سند را مسدود نمی کند (که برای تگ های<link>
درست نیست).
در حالی که کدهای بالا یک علامت "fonts:active" ایجاد می کنند، اندازه گیری این علامت و ثبت آن در کنسول به سادگی علامت "css:unblock" نیست. دلیل آن این است که بارگیری فونت اکنون به صورت ناهمزمان انجام می شود، بنابراین اگر بخواهید علامت "fonts:active" را در window.onload
اندازه گیری کنید (همانطور که با "css:unblock" انجام دادید)، ممکن است فونت این کار را نکند. هنوز بارگیری شود
برای حل این مشکل، می توانید یک وعده ایجاد کنید که پس از بارگذاری فونت حل شود. تابع زیر این کار را برای شما انجام می دهد. آن را کپی کرده و در فایل perf-analytics.js قرار دهید:
/**
* Creates a promise that is resolved once the web fonts are fully load or
* is reject if the fonts fail to load. The resolved callback calculates the
* time duration between the responseEnd timing event and when the web fonts
* are downloaded and active. If an error occurs loading the font, this fact
* is logged to the console.
*/
function measureWebfontPerfAndFailures() {
new Promise(function(resolve, reject) {
// The classes `wf-active` or `wf-inactive` are added to the <html>
// element once the fonts are loaded (or error).
var loaded = /wf-(in)?active/.exec(document.documentElement.className);
var success = loaded && !loaded[1]; // No "in" in the capture group.
// If the fonts are already done loading, resolve immediately.
// Otherwise resolve/reject in the active/inactive callbacks, respectively.
if (loaded) {
success ? resolve() : reject();
}
else {
var originalAciveCallback = WebFontConfig.active;
WebFontConfig.inactive = reject;
WebFontConfig.active = function() {
originalAciveCallback();
resolve();
};
// In case the webfont.js script fails to load, always reject the
// promise after the timeout amount.
setTimeout(reject, WebFontConfig.timeout);
}
})
.then(function() {
console.log('Fonts', 'active', measureDuration('fonts:active'));
})
.catch(function() {
console.error('Error loading web fonts')
});
}
همچنین برای فراخوانی این تابع جدید، window.onload
را به روز کنید
window.onload = function() {
measureCssUnblockTime();
measureWebfontPerfAndFailures();
};
هنگامی که این مرحله را کامل کردید، کد شما باید با آنچه در فهرست 02-fonts
مخزن کد آزمایشگاهی وجود دارد مطابقت داشته باشد.
اگر صفحه را در مرورگر بارگذاری کنید و کنسول توسعه دهنده را باز کنید، باید چیزی شبیه خروجی زیر مشاهده کنید:
دانستن اینکه چه زمانی یک تصویر قابل مشاهده است به آن سادگی که به نظر می رسد نیست. از مراحل قبلی می دانید که شیوه نامه ها و تگ های همگام <script>
می توانند رندر، تجزیه و اجرای اسکریپت را مسدود کنند. چیزی که ممکن است ندانید این است که هیچ یک از آنها اسکنر پیش بارگذاری مرورگر را مسدود نمی کنند.
اسکنر پیش بارگذاری چیزی است که تمام مرورگرهای مدرن به عنوان یکی از تلاشهای متعدد برای بهبود عملکرد، حتی در سایتهای غیرمعقول که دارای داراییهای مسدودکننده زیادی هستند، اجرا میکنند. ایده این است که در حالی که برخی از دارایی ها ممکن است تجزیه یا رندر یا اجرای اسکریپت را مسدود کنند، لازم نیست دانلودها را مسدود کنند. بنابراین مرورگر فایل HTML را قبل از شروع ساخت DOM اسکن می کند و به دنبال دارایی هایی می گردد که می تواند بلافاصله دانلود شود.
تا آنجایی که به تصاویر مربوط می شود، این بدان معناست که این احتمال وجود دارد که تصاویر شما تا زمانی که به DOM اضافه شوند، دانلود شوند. این همچنین به این معنی است که نقطه ای که در آن یک تصویر دانلود می شود لزوماً معیار عملکرد خوبی نیست . معیار عملکردی که باید به آن اهمیت دهید، نقطه ای است که در آن یک تصویر برای کاربر قابل مشاهده است.
وقتی یک تصویر قبل از اضافه شدن به DOM دانلود می شود، نقطه ای که در آن قابل مشاهده می شود، نقطه ای است که در DOM است. از سوی دیگر، اگر تصویری قبل از اضافه شدن به DOM دانلود نشود، نقطه ای که در آن قابل مشاهده می شود زمانی است که کنترل کننده onload
آن فعال می شود.
بنابراین، برای اینکه بدانید چه زمانی یک تصویر قابل مشاهده است، باید هر دو مورد را مدیریت کنید.
شما می توانید این کار را با اضافه کردن علائم در کنترل کننده بارگذاری هر تصویر و همچنین در یک تگ <script> درون خطی بلافاصله بعد از آخرین تصویر در DOM انجام دهید. ایده این است که علامتی که آخرین رخ می دهد، علامتی باشد که نشان دهنده زمانی است که همه تصاویر قابل مشاهده هستند.
برای اضافه کردن علامت برای هر دو هنگام بارگیری و رندر شدن تصاویر، کد تصاویر را در index.html
به صورت زیر به روز کنید:
<!-- Start images -->
<div class="gallery">
<img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
<img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
<img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>performance.mark('img:visible')</script>
<!-- End images -->
از آنجایی که روش performance.measure
برای یک نام علامت خاص همیشه از آخرین علامت استفاده میکند (اگر چندین علامت با یک نام پیدا کند)، تابع ابزار measureDuration
در فایل perf-analytics.js
میتواند بدون هیچ گونه تغییر اضافی برای این کار استفاده شود. :
/**
* Calculates the time duration between the responseEnd timing event and when
* all images are loaded and visible on the page, then logs that value to the
* console.
*/
function measureImagesVisibleTime() {
console.log('Images', 'visible', measureDuration('img:visible'));
}
تابع بالا را به فایل perf-analytics.js
اضافه کنید و سپس handler window.onload
را برای فراخوانی آن به روز کنید:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
};
هنگامی که این مرحله را کامل کردید، کد شما باید با آنچه در فهرست 03-images
مخزن کد آزمایشگاه است مطابقت داشته باشد.
اگر صفحه را در مرورگر بارگذاری کنید و کنسول توسعه دهنده را باز کنید، باید چیزی شبیه خروجی زیر مشاهده کنید:
از آنجایی که تگهای <script>
بدون ویژگی async
، تجزیه DOM را مسدود میکنند تا زمانی که هم دانلود و هم اجرا شوند، میتوانید نقطه پایان اجرای تمام اسکریپتها را با افزودن علامتی در تگ اسکریپت درون خطی بلافاصله پس از آخرین <script>
همگام تعیین کنید. <script>
در DOM.
توجه داشته باشید که استفاده از onload
handlers در این مورد کار نخواهد کرد زیرا مرورگر باید اسکریپت را پس از بارگیری آن اجرا کند و این زمان می برد. اسکریپتی که سریع بارگذاری می شود اما اجرای آن کند است می تواند به همان اندازه بد باشد که یک اسکریپت بارگذاری کند.
برای پیگیری زمان بارگیری و اجرای تمام جاوا اسکریپت در سند اصلی، بخش جاوا اسکریپت را در index.html
با کد زیر به روز کنید:
<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>performance.mark('js:execute');</script>
<!-- End JavaScript -->
این یک علامت به نام "js:execute" را بلافاصله پس از دانلود اسکریپت های پلاگین های jQuery و Bootstrap و پایان اجرای آن اضافه می کند.
برای اندازهگیری مدت زمانی که طول میکشد، تابع زیر را به perf-analytics.js
اضافه کنید:
/**
* Calculates the time duration between the responseEnd timing event and when
* all synchronous JavaScript files have been downloaded and executed, then
* logs that value to the console.
*/
function measureJavaSciptExecutionTime() {
console.log('JavaScript', 'execute', measureDuration('js:execute'));
}
و سپس آن را از handler window.onload
فراخوانی کنید:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
measureJavaSciptExecutionTime();
};
هنگامی که این مرحله را کامل کردید، کد شما باید با آنچه در فهرست راهنمای 04-javascript
مخزن آزمایشگاه کد وجود دارد مطابقت داشته باشد.
اگر صفحه را در مرورگر بارگذاری کنید و کنسول توسعه دهنده را باز کنید، باید چیزی شبیه خروجی زیر مشاهده کنید:
همه مرورگرها از وعدههای جاوا اسکریپت یا User Timing API پشتیبانی نمیکنند و اگر کدی را که تاکنون نوشتهاید بدون پشتیبانی از یکی از این ویژگیها در مرورگر اجرا کنید، با خطا مواجه میشوید.
برای مقابله با این، می توانید از تشخیص ویژگی استفاده کنید. بلافاصله قبل از بخش فونت، بیت کد دنبال را اضافه کنید. این خط از جاوا اسکریپت پشتیبانی از روش performance.mark
را شناسایی می کند، بنابراین باید قبل از استفاده از آن روش به صفحه اضافه شود:
<!-- Start feature detects -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End feature detects -->
در مرحله بعد، در هر نقطه از index.html
که در آن performance.mark
را صدا میزنید، پیشوند آن را با ویژگی detect قرار دهید. در اینجا یک مثال است که کد موجود در بلوک تصویر را به روز می کند، اما باید مطمئن شوید که بخش های دیگر را نیز به روز کنید.
<!-- Start images -->
<div class="gallery">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>__perf && performance.mark('img:visible')</script>
<!-- End images -->
اکنون که متغیر __perf
در window
تنظیم شده است، می توانید از آن در perf-analytics.js
نیز استفاده کنید تا مطمئن شوید که روشی را که در مرورگر فعلی پشتیبانی نمی شود، فراخوانی نمی کنید.
تابع measureDuration
باید برای اضافه کردن شرطی زیر به روز شود:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
}
}
در نهایت، از آنجایی که همه مرورگرها از وعدههای جاوا اسکریپت پشتیبانی نمیکنند، تابع measureWebfontPerfAndFailures
نیز باید در یک شرطی پیچیده شود:
function measureWebfontPerfAndFailures() {
if (window.Promise) {
// ...
}
}
اکنون باید بتوانید کد خود را در هر مرورگری بدون مشکل اجرا کنید.
هنگامی که این مرحله را کامل کردید، کد شما باید با آنچه در فهرست 05-feature-detects
مخزن آزمایشگاه کد وجود دارد مطابقت داشته باشد.
آخرین مرحله در این کد لبه این است که دادههایی را که در حال ثبت نام هستند به کنسول ببرید و در عوض به Google Analytics ارسال کنید. و قبل از اینکه بتوانید دادهها را به Google Analytics ارسال کنید، باید کتابخانه analytics.js و قطعه ردیابی پیشفرض را به صفحه خود اضافه کنید.
کد زیر را بعد از بلوک اصلی جاوا اسکریپت اما قبل از بارگیری اسکریپت perf-analytics.js
به index.html
اضافه کنید:
<!-- Start analytics tracking snippet -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics_debug.js"></script>
<!-- End analytics tracking snippet -->
اگر قبلاً Google Analytics را به وبسایتی اضافه کردهاید، میدانید که باید «UA-XXXXXX-Y» را با شناسه ردیابی که هنگام ایجاد یک ویژگی جدید در Google Analytics دریافت کردهاید جایگزین کنید.
قطعه ردیابی analytics.js چهار کار اصلی را انجام می دهد:
- یک عنصر
<script>
ناهمزمان ایجاد می کند که کتابخانه JavaScript analytics.js را دانلود می کند. - یک تابع
ga()
سراسری (به نام صف فرمان ga()) را راه اندازی می کند که به شما امکان می دهد دستورات را برنامه ریزی کنید تا پس از بارگیری و آماده شدن کتابخانه analytics.js اجرا شوند. - دستوری را به صف فرمان
ga()
اضافه می کند تا یک شی ردیاب جدید برای ویژگی مشخص شده از طریق پارامتر 'UA-XXXXX-Y' ایجاد کند. - دستور دیگری را به صف فرمان
ga()
اضافه می کند تا نمای صفحه را برای Google Analytics برای صفحه فعلی ارسال کند.
در حالی که دادههای جمعآوریشده از بازدید از صفحه به تنهایی مفید هستند، اما کل داستان را بیان نمیکنند. برای دریافت تصویر بهتری از نحوه تجربه کاربران سایت یا برنامه شما، باید داده های تعاملی اضافی را به Google Analytics ارسال کنید.
Google Analytics از انواع مختلفی از داده های تعامل پشتیبانی می کند: بازدید از صفحه، رویدادها ، تعاملات اجتماعی ، استثناها ، و (آخرین اما نه کم اهمیت) زمان بندی کاربر . برای ارسال داده های زمان بندی کاربر به Google Analytics، می توانید از امضای دستور زیر استفاده کنید:
ga('send', 'timing', timingCategory, timingVar, timingValue);
در جایی که timingCategory
رشتهای است که به شما امکان میدهد بازدیدهای زمانبندی را در گروههای منطقی سازماندهی کنید، timingVar
متغیری است که اندازهگیری میکنید و timingValue
مدت زمان واقعی بر حسب میلیثانیه است.
برای مشاهده نحوه عملکرد این در عمل، عبارت console.log
در تابع measureCssUnblockTime
را می توان به صورت زیر به روز کرد:
ga('send', 'timing', 'CSS', 'unblock', measureDuration('css:unblock'));
در حالی که کد بالا در برخی شرایط کار می کند، دو نکته مهم وجود دارد که باید از آنها آگاه بود:
- در مرحله قبل، تابع اندازهگیری مدت زمان بهروزرسانی شد تا فقط در صورتی اجرا شود که مرورگر از User
measureDuration
API پشتیبانی کند، به این معنی که گاهی اوقاتundefined
. از آنجایی که دلیلی برای ارسال دادههای تعریفنشده به Google Analytics وجود ندارد (در برخی موارد حتی میتواند گزارشهای شما را به هم بزند)، فقط در صورتی باید این ضربه زمانبندی را ارسال کنید کهmeasureDuration
را برگرداند. - هنگامی که
measureDuration
را برمی گرداند، یکDOMHighResTimeStamp
است که دقت آن بیشتر از میلی ثانیه است. از آنجایی کهtimingValue
در گوگل آنالیتیکس باید یک عدد صحیح باشد، باید مقدار بازگردانده شده توسطmeasureDuration
را گرد کنید.
برای محاسبه این گوچاها، عبارت بازگشتی را در تابع measureDuration به روز کنید تا مقدار بازگشتی را گرد کند:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
return Math.round(measure.duration);
}
}
و دستورات زمان بندی را به روز کنید تا فقط در صورتی اجرا شوند که مقداری برای متریک مورد نظر وجود داشته باشد. به عنوان مثال، تابع measureCssUnblockTime
باید به چیزی شبیه به این به روز شود:
function measureCssUnblockTime() {
var cssUnblockTime = measureDuration('css:unblock');
if (cssUnblockTime) {
ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
}
}
شما باید بهروزرسانیهای مشابهی را برای سایر عملکردهای اندازهگیری انجام دهید. پس از تکمیل، فایل perf-analytics.js نهایی باید به شکل زیر باشد:
window.onload = function() {
measureCssUnblockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
measureJavaSciptExecutionTime();
};
/**
* Calculates the time duration between the responseEnd timing event and when
* the CSS stops blocking rendering, then sends this measurement to Google
* Analytics via a timing hit.
*/
function measureCssUnblockTime() {
var cssUnblockTime = measureDuration('css:unblock');
if (cssUnblockTime) {
ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
}
}
/**
* Calculates the time duration between the responseEnd timing event and when
* the web fonts are downloaded and active, then sends this measurement to
* Google Analytics via a timing hit. If an error occurs loading the font, an
* error event is sent to Google Analytics.
*/
function measureWebfontPerfAndFailures() {
if (window.Promise) {
new Promise(function(resolve, reject) {
var loaded = /wf-(in)?active/.exec(document.documentElement.className);
var success = loaded && !loaded[1]; // No "in" in the capture group.
if (loaded) {
success ? resolve() : reject();
}
else {
var originalAciveCallback = WebFontConfig.active;
WebFontConfig.inactive = reject;
WebFontConfig.active = function() {
originalAciveCallback();
resolve();
};
// In case the webfont.js script failed to load.
setTimeout(reject, WebFontConfig.timeout);
}
})
.then(function() {
var fontsActiveTime = measureDuration('fonts:active');
if (fontsActiveTime) {
ga('send', 'timing', 'Fonts', 'active', fontsActiveTime);
}
})
.catch(function() {
ga('send', 'event', 'Fonts', 'error');
});
}
}
/**
* Calculates the time duration between the responseEnd timing event and when
* all images are loaded and visible on the page, then sends this measurement
* to Google Analytics via a timing hit.
*/
function measureImagesVisibleTime() {
var imgVisibleTime = measureDuration('img:visible');
if (imgVisibleTime) {
ga('send', 'timing', 'Images', 'visible', imgVisibleTime);
}
}
/**
* Calculates the time duration between the responseEnd timing event and when
* all synchronous JavaScript files are downloaded and executed, then sends
* this measurement to Google Analytics via a timing hit.
*/
function measureJavaSciptExecutionTime() {
var jsExecuteTime = measureDuration('js:execute');
if (jsExecuteTime) {
ga('send', 'timing', 'JavaScript', 'execute', jsExecuteTime);
}
}
/**
* Accepts a mark name and an optional reference point in the navigation timing
* API and returns the time duration between the reference point and the last
* mark (chronologically). The return value is rounded to the nearest whole
* number to be compatible with Google Analytics.
* @param {string} mark The mark name.
* @param {string=} opt_reference An optional reference point from the
* navigation timing API. Defaults to 'responseEnd'.
* @return {?number} The time duration as an integer or undefined if no
* matching marks can be found.
*/
function measureDuration(mark, opt_reference) {
if (window.__perf) {
var reference = opt_reference || 'responseEnd';
var name = reference + ':' + mark;
// Clears any existing measurements with the same name.
performance.clearMeasures(name);
// Creates a new measurement from the reference point to the specified mark.
// If more than one mark with this name exists, the most recent one is used.
performance.measure(name, reference, mark);
// Gets the value of the measurement just created.
var measure = performance.getEntriesByName(name)[0];
// Returns the measure duration.
return Math.round(measure.duration);
}
}
و فایل index.html نهایی باید به شکل زیر باشد:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Performance Analytics Demo</title>
<!-- Start navigation timing feature detect -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End navigation timing feature detect -->
<!-- Start fonts -->
<script>
window.WebFontConfig = {
google: {families: ['Roboto:400,700,400italic']},
timeout: 10000,
active: function() {
__perf && performance.mark('fonts:active');
}
};
</script>
<script async src="https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
<!-- End fonts -->
<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Roboto, sans-serif; margin: 1em; }
img { float: left; height: auto; width: 33.33%; }
.gallery { overflow: hidden; }
</style>
<script>__perf && performance.mark('css:unblock');</script>
<!-- End CSS -->
</head>
<body>
<div class="container">
<!-- Start images -->
<div class="gallery">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>__perf && performance.mark('img:visible')</script>
<!-- End images -->
<h1>Performance Analytics Demo</h1>
<p>Real performance data from real users.</p>
</div>
<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>__perf && performance.mark('js:execute');</script>
<!-- End JavaScript -->
<!-- Start analytics tracking snippet -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>
<!-- End analytics tracking snippet -->
<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->
</body>
</html>
اگر این صفحه را بارگیری کنید و به درخواستهای موجود در پنل شبکه نگاهی بیندازید، چیزی شبیه به شکل زیر خواهید دید:
این مفید است، اما نگاه کردن به این داده ها به عنوان یک درخواست رمزگذاری شده با URL می تواند دشوار باشد. و اگر به هر دلیلی این درخواستها را نمیبینید، ردیابی محل وقوع شکست واقعاً دشوار است.
یک رویکرد بهتر هنگام توسعه محلی، استفاده از نسخه اشکال زدایی analytics.js است، که با اجرای هر دستور analytics.js، اطلاعات اشکال زدایی مفید را در کنسول ثبت می کند. اگر شما
URL analytics.js را در index.html
به analytics_debug.js
بهروزرسانی کنید و کنسول مرورگر خود را باز کنید، عباراتی را خواهید دید که به شکل زیر چاپ شدهاند:
اکنون که نحوه اجرای اندازهگیری عملکرد برای این صفحه نمایشی را فهمیدید، میتوانید آن را به سایت خود اضافه کنید و دادههای واقعی کاربر را به Google Analytics ارسال کنید.
گزارش در مورد داده هایی که جمع آوری کرده اید
پس از چند روز جمعآوری دادههای عملکرد، میتوانید در مورد آن دادهها گزارش دهید تا بینش عملی در مورد سرعت بارگیری سایت و منابع آن برای کاربران واقعی به دست آورید.
برای دسترسی به گزارشهای زمانبندی کاربر در Google Analytics، روی تب Reporting در بالا کلیک کنید و "رفتار > سرعت سایت > زمانبندی کاربر" را از پیمایش نوار کناری انتخاب کنید (یا دستورالعملها را برای مشاهده گزارش زمانبندی کاربر از مرکز راهنمایی دنبال کنید). .
وقتی گزارش زمانبندی کاربر را در Google Analytics بارگیری میکنید، باید بتوانید دستههای زمانبندی را که با دادههایی که ارسال کردهاید مطابقت دارند، ببینید. برای مشاهده تصاویر دقیق از داده های زمان بندی خود، روی هر یک از آنها کلیک کنید. تصویر زیر نمونه ای از زمان بارگذاری فونت در یک وب سایت واقعی با استفاده از فونت های گوگل در 24 ساعت گذشته است.
تبریک می گویم! شما این آزمایشگاه کد را با موفقیت به پایان رساندید. اگر میخواهید عمیقتر بروید، در بخش بعدی چند پیشنهاد برای نحوه ساخت بالای این کد برای دستیابی به بینش بیشتر به شما ارائه میشود.
معیارهای عملکرد پوشش داده شده در این آزمایشگاه کد برای اندازه گیری نحوه بارگیری سایت شما برای کاربران واقعی بسیار مهم هستند، اما آنها تازه شروع کار هستند. اگر میخواهید عمیقتر به تجزیه و تحلیل عملکرد بروید، یکی دیگر از موارد آسان، ردیابی معیارهای بیشتر است.
در این آزمایشگاه کد، معیارهای مربوط به زمانی که منابع در دسترس کاربر بود را ردیابی کردید. اگر میخواستید، میتوانید بیشتر این موارد را حتی بیشتر از این هم تجزیه کنید. بهعنوان مثال، بهجای اندازهگیری زمان پایان اجرای جاوا اسکریپت، میتوانید زمان شروع بارگذاری، زمانی که بارگیری به پایان رسید، زمان شروع اجرا و سپس در نهایت زمانی که اجرای آن به پایان رسید را اندازه بگیرید. هر یک از این معیارها می تواند مشکلی را آشکار کند که فقط یکی از آنها ممکن است نگوید.
علاوه بر ریزتر شدن، باید در مورد استراتژی کلی تجزیه و تحلیل عملکرد خود نیز بیشتر فکر کنید. اهداف چیست؟ موفقیت چیست؟
وقتی نوبت به هر نوع تحلیلی میرسد، معمولاً میخواهید با نوعی سؤال شروع کنید و سپس نحوه استفاده از دادهها را برای پاسخ به آن سؤال بیابید.
به عنوان مثال، فهرست سؤالات زیر را در نظر بگیرید، و اینکه چگونه از دانشی که در این آزمایشگاه کد کسب کرده اید برای استفاده از تجزیه و تحلیل برای پاسخ به آنها استفاده می کنید:
- آیا مقادیر معیارهای ردیابی شما در طول زمان کاهش می یابد یا افزایش می یابد؟
- استفاده از کش آفلاین از طریق سرویس دهنده یا ذخیره سازی محلی چگونه بر عملکرد کلی سایت شما تأثیر می گذارد؟
- آیا منابع شما به طور بهینه بارگیری می شوند؟ یعنی فاصله زیادی بین زمان دانلود منبع و زمانی که منبع برای استفاده در دسترس است وجود دارد؟
- آیا بین عملکرد و سایر معیارهایی که دنبال می کنید (مثلاً نرخ ثبت نام، زمان حضور در سایت، خریدها و غیره) همبستگی وجود دارد؟
در نهایت، اگر میخواهید در مورد عملکرد وب یا Google Analytics اطلاعات بیشتری کسب کنید، در اینجا چند منبع عالی برای شروع شما وجود دارد:
- ابزارها و اطلاعاتی که به شما کمک می کند تا وب سایت هایی با کارایی بالا بسازید
https://developers.google.com/speed/ - ابزارها و APIهایی برای توسعه دهندگان برای استفاده از پلتفرم Google Analytics
https://developers.google.com/analytics/ - دوره های آنلاین که نحوه استفاده از خود محصول گوگل آنالیتیکس را به شما آموزش می دهد (که توسط افرادی تدریس می شود که روی خود گوگل آنالیتیکس کار می کنند.
https://analyticsacademy.withgoogle.com/