در این نرم افزار کد، یاد می گیرید که چگونه از Google Analytics و User Timings 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 ایجاد میکند نیز استفاده کنید).
تابع ابزار زیر، مدت زمان بین علامتی که اضافه کردهاید و علامت answerEnd ایجاد شده توسط 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 اجرای جاوا اسکریپت را مسدود می کند زیرا محتویات stylesheet برای ساخت CSSOM استفاده می شود و از آنجایی که ممکن است جاوا اسکریپت در حال بارگیری نیاز به دسترسی به CSSOM داشته باشد، اجرا باید تا زمانی که CSSOM به طور کامل ساخته شود به تعویق بیفتد.
نکته مهم این است که مرورگر می تواند CSSOM را بدون بارگیری واقعی فونت بسازد، به این معنی که اگر علامتی را از طریق یک تگ اسکریپت درون خطی به DOM بلافاصله پس از برچسب <link> صفحه سبک فونت اضافه کنید، این احتمال وجود دارد که علامت قبل از بارگیری کامل فونت رخ دهد.
تا زمانی که رویدادهای بارگذاری فونت در مرورگرها در دسترس قرار نگیرند، جاوا اسکریپت برای تعیین زمانی که یک فونت واقعاً فعال و آماده برای استفاده در صفحه است، مورد نیاز است. خوشبختانه، بارگذاری فونت ها از طریق جاوا اسکریپت نیز یک پیروزی عملکردی است، زیرا نیازی به درخواست مسدود کردن اضافی برای یک فایل 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> همزمان در 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'));در حالی که کد بالا در برخی شرایط کار می کند، دو نکته مهم وجود دارد که باید از آنها آگاه بود:
- در مرحله قبل، تابع
measureDurationبهروزرسانی شد تا فقط در صورتی اجرا شود که مرورگر از User Timeings API پشتیبانی کند، به این معنی که گاهی اوقاتundefinedبرمیگردد. از آنجایی که دلیلی برای ارسال دادههای تعریفنشده به Google Analytics وجود ندارد (در برخی موارد حتی میتواند گزارشهای شما را به هم بزند)، فقط در صورتی باید این ضربه زمانبندی را ارسال کنید کهmeasureDurationمقداری را برگرداند. - هنگامی که
measureDurationمقداری برمیگرداند، یکDOMHighResTimeStampاست که دقت آن بیش از میلیثانیه است. از آنجایی کهtimingValueدر گوگل آنالیتیکس باید یک عدد صحیح باشد، باید مقدار بازگردانده شده توسطmeasureDurationرا گرد کنید.
برای محاسبه این گوچاها، عبارت return را در تابع 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/