عملکرد وب آسان شد - نسخه Google I/O 2018

در Google IO 2018، ما مجموعه‌ای از ابزارها، کتابخانه‌ها و تکنیک‌های بهینه‌سازی را ارائه دادیم که بهبود عملکرد وب را آسان‌تر می‌کنند. در اینجا آنها را با استفاده از برنامه The Oodles Theater توضیح می‌دهیم. همچنین در مورد آزمایش‌های خود با بارگذاری پیش‌بینی‌کننده و ابتکار جدید Guess.js صحبت می‌کنیم.

Ewa Gasperowicz

ما در طول سال گذشته بسیار مشغول تلاش برای یافتن راهی برای سریع‌تر و کارآمدتر کردن وب بوده‌ایم. این امر منجر به ابزارها، رویکردها و کتابخانه‌های جدیدی شد که می‌خواهیم در این مقاله با شما به اشتراک بگذاریم. در بخش اول، برخی از تکنیک‌های بهینه‌سازی را که در عمل هنگام توسعه برنامه The Oodles Theater استفاده کرده‌ایم، به شما نشان خواهیم داد. در بخش دوم، در مورد آزمایش‌های خود با بارگذاری پیش‌بینی‌کننده و ابتکار جدید Guess.js صحبت خواهیم کرد.

نیاز به عملکرد

اینترنت هر ساله سنگین‌تر و سنگین‌تر می‌شود. اگر وضعیت وب را بررسی کنیم، می‌بینیم که یک صفحه به طور متوسط ​​در موبایل حدود ۱.۵ مگابایت حجم دارد که بخش عمده آن را جاوا اسکریپت و تصاویر تشکیل می‌دهند.

افزایش حجم وب‌سایت‌ها، همراه با عوامل دیگری مانند تأخیر شبکه، محدودیت‌های CPU، الگوهای مسدودکننده رندر یا کدهای اضافی شخص ثالث، به این معمای پیچیده عملکرد دامن می‌زند.

اکثر کاربران سرعت را در صدر سلسله مراتب تجربه کاربری نیازهای خود قرار می‌دهند. این خیلی تعجب‌آور نیست، زیرا تا زمانی که بارگذاری یک صفحه به پایان نرسد، نمی‌توانید کار زیادی انجام دهید. نمی‌توانید از صفحه ارزشی استخراج کنید، نمی‌توانید زیبایی‌شناسی آن را تحسین کنید.

سلسله مراتب تجربه کاربری (UX) به صورت هرمی
شکل ۱. سرعت چقدر برای کاربران مهم است؟ (Speed ​​Matters، جلد ۳)

ما می‌دانیم که عملکرد برای کاربران مهم است، اما می‌تواند مانند یک راز باشد که کشف کنیم از کجا باید بهینه‌سازی را شروع کنیم. خوشبختانه، ابزارهایی وجود دارند که می‌توانند در این مسیر به شما کمک کنند.

فانوس دریایی - پایه‌ای برای گردش کار عملکرد

Lighthouse بخشی از Chrome DevTools است که به شما امکان می‌دهد وب‌سایت خود را بررسی کنید و نکاتی را در مورد چگونگی بهبود آن ارائه می‌دهد.

ما اخیراً مجموعه‌ای از ممیزی‌های عملکرد جدید را راه‌اندازی کرده‌ایم که در گردش کار روزمره توسعه واقعاً مفید هستند.

ممیزی‌های جدید لایت‌هاوس
شکل ۲. ممیزی‌های جدید لایت‌هاوس

بیایید بررسی کنیم که چگونه می‌توانید از آنها در یک مثال عملی بهره ببرید: برنامه The Oodles Theater . این یک برنامه وب آزمایشی کوچک است که در آن می‌توانید برخی از Google Doodle های تعاملی مورد علاقه ما را امتحان کنید و حتی یک یا دو بازی انجام دهید.

هنگام ساخت برنامه، می‌خواستیم مطمئن شویم که تا حد امکان عملکرد خوبی دارد. نقطه شروع بهینه‌سازی، گزارش Lighthouse بود.

گزارش Lighthouse برای اپلیکیشن Ooodles
شکل ۳. گزارش Lighthouse برای برنامه Ooodles

عملکرد اولیه برنامه ما همانطور که در گزارش Lighthouse مشاهده شد، بسیار وحشتناک بود. در یک شبکه 3G، کاربر باید 15 ثانیه برای اولین رنگ معنی‌دار یا برای تعامل با برنامه منتظر می‌ماند. Lighthouse مشکلات زیادی را در سایت ما برجسته کرد و امتیاز کلی عملکرد 23 دقیقاً همین را نشان می‌داد.

حجم صفحه حدود ۳.۴ مگابایت بود - ما به شدت نیاز داشتیم که کمی از حجم آن کم کنیم.

این اولین چالش عملکردی ما را آغاز کرد: چیزهایی را پیدا کنیم که بتوانیم به راحتی و بدون تأثیر بر تجربه کلی، حذف کنیم.

فرصت‌های بهینه‌سازی عملکرد

منابع غیرضروری را حذف کنید

چند چیز واضح وجود دارد که می‌توان با خیال راحت حذف کرد: فضای خالی و نظرات.

سود حاصل از کوچک‌سازی
شکل ۴. کوچک‌سازی و فشرده‌سازی جاوا اسکریپت و CSS

لایت‌هاوس این فرصت را در بررسی فشرده‌سازی نشده‌ی CSS و جاوا اسکریپت برجسته می‌کند. ما برای فرآیند ساخت از وب‌پک استفاده می‌کردیم، بنابراین برای فشرده‌سازی، به سادگی از افزونه‌ی Uglify JS استفاده کردیم.

کوچک‌سازی یک کار رایج است، بنابراین باید بتوانید برای هر فرآیند ساختی که استفاده می‌کنید، یک راه‌حل آماده پیدا کنید.

یکی دیگر از بررسی‌های مفید در این زمینه، فعال کردن فشرده‌سازی متن است. هیچ دلیلی برای ارسال فایل‌های فشرده نشده وجود ندارد و اکثر CDNها این روزها از این قابلیت پشتیبانی می‌کنند.

ما از Firebase Hosting برای میزبانی کد خود استفاده می‌کردیم و Firebase به طور پیش‌فرض gzip کردن را فعال می‌کند، بنابراین به لطف میزبانی کد خود روی یک CDN مناسب، آن را به صورت رایگان دریافت کردیم.

در حالی که gzip یک روش بسیار محبوب برای فشرده‌سازی است، مکانیسم‌های دیگری مانند Zopfli و Brotli نیز در حال جذب توجه هستند. Brotli در اکثر مرورگرها پشتیبانی می‌شود و می‌توانید قبل از ارسال فایل‌های خود به سرور، از یک فایل باینری برای پیش‌فشرده‌سازی آنها استفاده کنید.

از سیاست‌های کارآمد برای ذخیره‌سازی اطلاعات در حافظه پنهان (cache) استفاده کنید

قدم بعدی ما این بود که مطمئن شویم در صورت لزوم، منابع را دو بار ارسال نمی‌کنیم.

بررسی سیاست ناکارآمد کش در لایت‌هاوس به ما کمک کرد تا متوجه شویم که می‌توانیم استراتژی‌های کش خود را بهینه کنیم تا دقیقاً به این هدف برسیم. با تنظیم هدر انقضای حداکثر سن در سرور خود، مطمئن شدیم که کاربر در بازدیدهای مکرر می‌تواند از منابعی که قبلاً دانلود کرده است، دوباره استفاده کند.

در حالت ایده‌آل، شما باید تا حد امکان منابع را به صورت امن و برای طولانی‌ترین مدت زمان ممکن ذخیره کنید و توکن‌های اعتبارسنجی را برای اعتبارسنجی مجدد کارآمد منابعی که به‌روزرسانی شده‌اند، فراهم کنید.

حذف کدهای استفاده نشده

تا اینجا بخش‌های واضح دانلود غیرضروری را حذف کردیم، اما بخش‌های کم‌اهمیت‌تر چطور؟ مثلاً کدهای استفاده‌نشده.

پوشش کد در DevTools
شکل 5. پوشش کد را بررسی کنید

گاهی اوقات ما در برنامه‌های خود کدی را قرار می‌دهیم که واقعاً ضروری نیست. این اتفاق به خصوص اگر مدت زمان طولانی‌تری روی برنامه خود کار کنید، تیم یا وابستگی‌های شما تغییر کند، رخ می‌دهد و گاهی اوقات یک کتابخانه یتیم (orphan library) جا می‌ماند. این دقیقاً همان اتفاقی است که برای ما افتاد.

در ابتدا ما از کتابخانه کامپوننت‌های متریال برای نمونه‌سازی سریع برنامه خود استفاده می‌کردیم. با گذشت زمان، به یک ظاهر و حس سفارشی‌تر روی آوردیم و آن کتابخانه را کاملاً فراموش کردیم. خوشبختانه، بررسی پوشش کد به ما کمک کرد تا آن را در بسته خود دوباره کشف کنیم.

شما می‌توانید آمار پوشش کد خود را در DevTools، هم برای زمان اجرا و هم برای زمان بارگذاری برنامه‌تان، بررسی کنید. می‌توانید دو نوار قرمز بزرگ را در تصویر پایین مشاهده کنید - ما بیش از ۹۵٪ از CSS خود و مقدار زیادی جاوا اسکریپت نیز استفاده نشده داشتیم.

Lighthouse نیز این مشکل را در بررسی قوانین CSS استفاده نشده پیدا کرد. این بررسی نشان داد که بیش از ۴۰۰ کیلوبایت صرفه‌جویی بالقوه ایجاد شده است. بنابراین به کد خود برگشتیم و هر دو بخش جاوا اسکریپت و CSS آن کتابخانه را حذف کردیم.

اگر آداپتور MVC را حذف کنیم، استایل‌های ما به 10 کیلوبایت کاهش می‌یابند.
شکل ۶. اگر آداپتور MVC را حذف کنیم، حجم استایل‌های ما به ۱۰ کیلوبایت کاهش می‌یابد!

این کار حجم بسته CSS ما را ۲۰ برابر کاهش داد، که برای یک کامیت کوچک دو خطی بسیار خوب است.

البته، این باعث شد امتیاز عملکرد ما بالا برود، و همچنین زمان تعامل با بازی (Time to Interactive) خیلی بهتر شد.

با این حال، با تغییراتی از این دست، بررسی معیارها و امتیازات به تنهایی کافی نیست. حذف کد واقعی هرگز بدون ریسک نیست، بنابراین همیشه باید مراقب پسرفت‌های احتمالی باشید.

کد ما در ۹۵٪ استفاده نشده بود - هنوز این ۵٪ جایی وجود دارد. ظاهراً یکی از کامپوننت‌های ما هنوز از استایل‌های آن کتابخانه استفاده می‌کرد - فلش‌های کوچک در اسلایدر doodle. اما چون خیلی کوچک بود، می‌توانستیم به صورت دستی آن استایل‌ها را دوباره در دکمه‌ها بگنجانیم.

دکمه‌ها به دلیل نبود کتابخانه خراب شدند
شکل ۷. یکی از کامپوننت‌ها هنوز از کتابخانه‌ی حذف‌شده استفاده می‌کرد

بنابراین اگر کدی را حذف می‌کنید، فقط مطمئن شوید که یک گردش کار تست مناسب دارید تا به شما در محافظت در برابر رگرسیون‌های بصری بالقوه کمک کند.

از بارهای شبکه عظیم جلوگیری کنید

ما می‌دانیم که منابع حجیم می‌توانند سرعت بارگذاری صفحات وب را کاهش دهند. آن‌ها می‌توانند برای کاربران ما هزینه داشته باشند و تأثیر زیادی بر حجم اینترنت آن‌ها داشته باشند، بنابراین توجه به این موضوع بسیار مهم است.

لایت‌هاوس با استفاده از بررسی بار داده شبکه Enormous توانست تشخیص دهد که ما در برخی از بارهای داده شبکه خود مشکلی داریم.

تشخیص حجم عظیم داده‌های شبکه
شکل ۸. شناسایی حجم عظیمی از داده‌های شبکه

اینجا دیدیم که بیش از ۳ مگابایت کد در حال ارسال است - که مخصوصاً روی موبایل حجم زیادی است.

در صدر این لیست، Lighthouse به این نکته اشاره کرد که ما یک بسته‌ی جاوا اسکریپت داشتیم که شامل ۲ مگابایت کد فشرده نشده بود. این مشکلی است که Webpack نیز به آن اشاره کرده است.

همانطور که می‌گویند: سریع‌ترین درخواست، درخواستی است که انجام نمی‌شود.

در حالت ایده‌آل، شما باید ارزش تک تک دارایی‌هایی را که به کاربران خود ارائه می‌دهید، اندازه‌گیری کنید، عملکرد آن دارایی‌ها را بسنجید و در مورد اینکه آیا ارزش ارسال اولیه را دارد یا خیر، تصمیم بگیرید. زیرا گاهی اوقات این دارایی‌ها می‌توانند به تعویق بیفتند، یا با تنبلی بارگیری شوند، یا در زمان بیکاری پردازش شوند.

در مورد ما، از آنجایی که با تعداد زیادی بسته جاوا اسکریپت سر و کار داریم، خوش شانس بودیم زیرا جامعه جاوا اسکریپت مجموعه غنی از ابزارهای بررسی بسته‌های جاوا اسکریپت را در اختیار دارد.

حسابرسی بسته‌های جاوا اسکریپت
شکل 9. بررسی بسته جاوا اسکریپت

ما با webpack bundle analyzer شروع کردیم که به ما اطلاع داد که در حال اضافه کردن یک وابستگی به نام unicode هستیم که ۱.۶ مگابایت از جاوا اسکریپت تجزیه‌شده را تشکیل می‌دهد، که حجم نسبتاً زیادی است.

سپس به ویرایشگر خود رفتیم و با استفاده از افزونه Import Cost برای کد ویژوال، توانستیم هزینه هر ماژولی را که وارد می‌کردیم، بصری‌سازی کنیم. این به ما امکان داد تا بفهمیم کدام کامپوننت شامل کدی است که به این ماژول ارجاع می‌دهد.

سپس به ابزار دیگری به نام BundlePhobia روی آوردیم. این ابزاری است که به شما امکان می‌دهد نام هر بسته NPM را وارد کنید و ببینید که اندازه تخمینی minify و gzip شده آن چقدر است. ما یک جایگزین خوب برای ماژول slug که استفاده می‌کردیم پیدا کردیم که فقط ۲.۲ کیلوبایت حجم داشت، بنابراین آن را تغییر دادیم.

این موضوع تأثیر زیادی بر عملکرد ما داشت. با این تغییر و کشف فرصت‌های دیگر برای کاهش حجم بسته جاوا اسکریپت، ما ۲.۱ مگابایت در کد صرفه‌جویی کردیم.

با در نظر گرفتن حجم فشرده‌سازی شده و کوچک‌شده‌ی این بسته‌ها، در مجموع شاهد ۶۵ درصد بهبود بودیم. و دریافتیم که انجام این کار به عنوان یک فرآیند واقعاً ارزشش را دارد.

بنابراین، به طور کلی، سعی کنید دانلودهای غیرضروری را در سایت‌ها و برنامه‌های خود حذف کنید. فهرستی از دارایی‌های خود تهیه کنید و تأثیر عملکرد آنها را اندازه‌گیری کنید، زیرا می‌تواند تفاوت بزرگی ایجاد کند، بنابراین مطمئن شوید که دارایی‌های خود را به طور منظم حسابرسی می‌کنید.

کاهش زمان بوت شدن جاوا اسکریپت با تقسیم کد

اگرچه بارهای کاری بزرگ شبکه می‌توانند تأثیر زیادی بر برنامه ما داشته باشند، اما چیز دیگری هم وجود دارد که می‌تواند تأثیر واقعاً بزرگی داشته باشد و آن جاوا اسکریپت است.

جاوا اسکریپت گران‌ترین دارایی شماست. در موبایل، اگر حجم زیادی از جاوا اسکریپت ارسال کنید، می‌تواند باعث تأخیر در تعامل کاربران با اجزای رابط کاربری شما شود. این بدان معناست که آنها می‌توانند بدون هیچ اتفاق معناداری روی رابط کاربری کلیک کنند. بنابراین برای ما مهم است که بدانیم چرا جاوا اسکریپت اینقدر هزینه دارد.

اینگونه است که یک مرورگر جاوا اسکریپت را پردازش می‌کند.

پردازش جاوا اسکریپت
شکل 10. پردازش جاوا اسکریپت

اول از همه باید آن اسکریپت را دانلود کنیم، ما یک موتور جاوا اسکریپت داریم که سپس باید آن کد را تجزیه، کامپایل و اجرا کند.

این مراحل چیزی هستند که در دستگاه‌های پیشرفته‌ای مثل کامپیوتر رومیزی یا لپ‌تاپ، یا حتی گوشی‌های رده بالا، زمان زیادی نمی‌برند. اما در گوشی‌های موبایل معمولی، این فرآیند می‌تواند بین پنج تا ده برابر بیشتر طول بکشد. این همان چیزی است که تعامل را به تأخیر می‌اندازد، بنابراین مهم است که سعی کنیم این زمان را کاهش دهیم.

برای کمک به شما در کشف این مشکلات در برنامه‌تان، ما یک بررسی زمان بوت شدن جاوا اسکریپت جدید را به Lighthouse معرفی کردیم.

زمان بوت شدن جاوا اسکریپت
شکل ۱۱. بررسی زمان بوت شدن جاوا اسکریپت

و در مورد برنامه Oodle، به ما گفت که ۱.۸ ثانیه زمان صرف بوت شدن جاوا اسکریپت شده است. اتفاقی که می‌افتاد این بود که ما تمام مسیرها و کامپوننت‌های خود را به صورت ایستا در یک بسته یکپارچه جاوا اسکریپت وارد می‌کردیم.

یک تکنیک برای حل این مشکل، استفاده از تقسیم کد است.

تقسیم کد مثل پیتزاست

تقسیم کد به این معنی است که به جای اینکه به کاربران خود یک پیتزای کامل از جاوا اسکریپت بدهید، چه می‌شود اگر فقط یک برش را در هر زمان که به آن نیاز دارند به آنها بدهید؟

تقسیم کد می‌تواند در سطح مسیر یا سطح کامپوننت اعمال شود. این قابلیت با React و React Loadable، Vue.js، Angular، Polymer، Preact و چندین کتابخانه دیگر به خوبی کار می‌کند.

ما تقسیم کد را در برنامه خود گنجاندیم، از ایمپورت‌های استاتیک به ایمپورت‌های پویا تغییر دادیم، که به ما امکان می‌دهد کد را به صورت ناهمگام و در صورت نیاز، به صورت تنبل بارگذاری کنیم.

تقسیم کد با ایمپورت‌های پویا
شکل ۱۳. تقسیم کد با ایمپورت‌های پویا

تأثیر این کار هم کاهش اندازه بسته‌های نرم‌افزاری ما بود، و هم زمان بوت شدن جاوا اسکریپت ما را کاهش داد. این زمان به ۰.۷۸ ثانیه کاهش یافت و برنامه را ۵۶٪ سریع‌تر کرد.

به طور کلی، اگر در حال ساخت یک تجربه کاربری سنگین با جاوا اسکریپت هستید، مطمئن شوید که فقط کدی را برای کاربر ارسال می‌کنید که به آن نیاز دارد.

از مفاهیمی مانند تقسیم کد (code splitting) بهره ببرید، ایده‌هایی مانند tree shake را بررسی کنید و برای ایده‌هایی در مورد چگونگی کاهش حجم کتابخانه در صورت استفاده از وب‌پک، به مخزن webpack-libs-optimizations مراجعه کنید.

بهینه سازی تصاویر

شوخی عملکرد در حال بارگذاری تصویر

در برنامه Oodle ما از تصاویر زیادی استفاده می‌کنیم. متأسفانه، Lighthouse نسبت به ما اشتیاق کمتری به این موضوع نشان داد. در واقع، ما در هر سه ممیزی مربوط به تصویر شکست خوردیم.

ما فراموش کردیم تصاویرمان را بهینه کنیم، اندازه آنها را به درستی تنظیم نکرده بودیم، و همچنین می‌توانستیم از استفاده از فرمت‌های تصویری دیگر سود ببریم.

ممیزی تصویر
شکل ۱۴. بررسی تصاویر Lighthouse

ما با بهینه‌سازی تصاویرمان شروع کردیم.

برای دور بهینه‌سازی تک‌مرحله‌ای می‌توانید از ابزارهای بصری مانند ImageOptim یا XNConvert استفاده کنید.

یک رویکرد خودکارتر، اضافه کردن یک مرحله بهینه‌سازی تصویر به فرآیند ساخت با استفاده از کتابخانه‌هایی مانند imagemin است.

به این ترتیب مطمئن می‌شوید که تصاویری که در آینده اضافه می‌شوند، به طور خودکار بهینه می‌شوند. برخی از CDNها، به عنوان مثال Akamai یا راه‌حل‌های شخص ثالث مانند Cloudinary ، Fastly یا Uploadcare، راه‌حل‌های جامع بهینه‌سازی تصویر را به شما ارائه می‌دهند، بنابراین می‌توانید به سادگی تصاویر خود را در آن سرویس‌ها میزبانی کنید.

اگر به دلیل هزینه یا مشکلات تأخیر نمی‌خواهید این کار را انجام دهید، پروژه‌هایی مانند Thumbor یا Imageflow گزینه‌های خود-میزبانی ارائه می‌دهند.

قبل و بعد از بهینه سازی
شکل ۱۵. قبل و بعد از بهینه‌سازی

فایل PNG پس‌زمینه ما در وب‌پک به عنوان فایلی با حجم بالا علامت‌گذاری شده بود، و این درست بود. پس از تنظیم صحیح اندازه آن برای ویوپورت و اجرای آن از طریق ImageOptim، حجم آن به ۱۰۰ کیلوبایت کاهش یافت که قابل قبول است.

تکرار این کار برای چندین تصویر در سایت ما به ما این امکان را داد که وزن کلی صفحه را به میزان قابل توجهی کاهش دهیم.

از قالب مناسب برای محتوای متحرک استفاده کنید

گیف‌ها می‌توانند واقعاً گران شوند. جای تعجب است که فرمت گیف از ابتدا هرگز به عنوان یک پلتفرم انیمیشن در نظر گرفته نشده بود. بنابراین، تغییر به یک فرمت ویدیویی مناسب‌تر، صرفه‌جویی زیادی از نظر حجم فایل به شما ارائه می‌دهد.

در برنامه Oodle، ما از یک GIF به عنوان یک سکانس مقدمه در صفحه اصلی استفاده می‌کردیم. طبق گفته Lighthouse، با تغییر به یک فرمت ویدیویی کارآمدتر، می‌توانستیم بیش از ۷ مگابایت در حجم صرفه‌جویی کنیم. حجم کلیپ ما حدود ۷.۳ مگابایت بود که برای هر وب‌سایت معقولی بسیار زیاد بود، بنابراین در عوض آن را به یک عنصر ویدیویی با دو فایل منبع تبدیل کردیم - یک mp4 و یک WebM برای پشتیبانی گسترده‌تر مرورگرها.

جایگزین کردن گیف‌های متحرک با ویدیو
شکل ۱۶. جایگزین کردن GIF های متحرک با ویدیو

ما از ابزار FFmpeg برای تبدیل انیمیشن GIF به فایل mp4 استفاده کردیم. فرمت WebM حتی صرفه‌جویی بیشتری را نیز برای شما به ارمغان می‌آورد - رابط برنامه‌نویسی ImageOptim می‌تواند چنین تبدیلی را برای شما انجام دهد.

ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

به لطف این تبدیل، ما موفق شدیم بیش از ۸۰٪ از وزن کلی خود را کاهش دهیم. این باعث شد وزن ما به حدود ۱ مگابایت کاهش یابد.

با این حال، ۱ مگابایت منبع بزرگی برای بارگذاری است، مخصوصاً برای کاربری که پهنای باند محدودی دارد. خوشبختانه می‌توانیم از Effective Type API استفاده کنیم تا متوجه شویم که آنها از پهنای باند کندی استفاده می‌کنند و در عوض یک JPEG بسیار کوچکتر به آنها بدهیم.

این رابط از زمان رفت و برگشت موثر و مقادیر قطعی برای تخمین نوع شبکه‌ای که کاربر استفاده می‌کند استفاده می‌کند. این رابط به سادگی یک رشته، 2G کند، 2G، 3G یا 4G را برمی‌گرداند. بنابراین بسته به این مقدار، اگر کاربر در شبکه‌ای با سرعت کمتر از 4G باشد، می‌توانیم عنصر ویدیو را با تصویر جایگزین کنیم.

if (navigator.connection.effectiveType) { ... }

کمی از تجربه کاربری کم می‌کند، اما حداقل سایت با اتصال کند هم قابل استفاده است.

بارگذاری تنبل تصاویر خارج از صفحه

چرخ و فلک‌ها، اسلایدرها یا صفحات واقعاً طولانی اغلب تصاویر را بارگذاری می‌کنند، حتی اگر کاربر نتواند آنها را فوراً در صفحه ببیند.

لایت‌هاوس این رفتار را در بررسی تصاویر خارج از صفحه علامت‌گذاری می‌کند و شما می‌توانید خودتان آن را در پنل شبکه‌ی DevTools مشاهده کنید. اگر تعداد زیادی تصویر ورودی می‌بینید در حالی که فقط تعداد کمی از آنها در صفحه قابل مشاهده هستند، به این معنی است که شاید بتوانید بارگذاری تنبل را در نظر بگیرید.

بارگذاری تنبل هنوز به صورت بومی در مرورگر پشتیبانی نمی‌شود، بنابراین باید از جاوا اسکریپت برای اضافه کردن این قابلیت استفاده کنیم. ما از کتابخانه Lazysizes برای اضافه کردن رفتار بارگذاری تنبل به پوشش‌های Oodle خود استفاده کردیم.

<!-- Import library -->
import lazysizes from 'lazysizes'  <!-- or -->
<script src="lazysizes.min.js"></script>

<!-- Use it -->

<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>

Lazysizes هوشمندانه عمل می‌کند زیرا نه تنها تغییرات مربوط به قابلیت مشاهده عنصر را ردیابی می‌کند، بلکه به طور فعال عناصری را که نزدیک به نمایش هستند، برای تجربه کاربری بهینه، پیش‌واکشی می‌کند. همچنین امکان ادغام اختیاری IntersectionObserver را ارائه می‌دهد که جستجوی بسیار کارآمدی برای قابلیت مشاهده به شما می‌دهد.

بعد از این تغییر، تصاویر ما بر اساس تقاضا دریافت می‌شوند. اگر می‌خواهید عمیق‌تر به این موضوع بپردازید، به images.guide مراجعه کنید - یک منبع بسیار مفید و جامع.

به مرورگر کمک کنید تا منابع حیاتی را زودتر تحویل دهد

هر بایتی که به مرورگر ارسال می‌شود، از درجه اهمیت یکسانی برخوردار نیست و مرورگر این را می‌داند. بسیاری از مرورگرها برای تصمیم‌گیری در مورد اینکه ابتدا چه چیزی را باید دریافت کنند، از روش‌های اکتشافی استفاده می‌کنند. بنابراین گاهی اوقات CSS را قبل از تصاویر یا اسکریپت‌ها دریافت می‌کنند.

چیزی که می‌تواند مفید باشد این است که ما، به عنوان نویسندگان صفحه، به مرورگر اطلاع دهیم که چه چیزی واقعاً برای ما مهم است. خوشبختانه، طی چند سال گذشته، فروشندگان مرورگر تعدادی ویژگی برای کمک به ما در این زمینه اضافه کرده‌اند، مثلاً نکات مربوط به منابع مانند link rel=preconnect یا preload یا prefetch .

این قابلیت‌هایی که به پلتفرم وب آورده شده‌اند، به مرورگر کمک می‌کنند تا در زمان مناسب، اطلاعات درست را دریافت کند و می‌توانند کمی کارآمدتر از برخی از رویکردهای بارگذاری سفارشی و مبتنی بر منطق باشند که به جای آن از اسکریپت استفاده می‌کنند.

بیایید ببینیم که Lighthouse چگونه ما را به سمت استفاده مؤثر از برخی از این ویژگی‌ها راهنمایی می‌کند.

اولین چیزی که لایت‌هاوس به ما می‌گوید این است که از سفرهای رفت و برگشت پرهزینه متعدد به هر مبدا خودداری کنیم.

از سفرهای رفت و برگشت متعدد و پرهزینه به هر مبدا خودداری کنید
شکل ۱۷. از سفرهای رفت و برگشت متعدد و پرهزینه به هر مبدا اجتناب کنید

در مورد برنامه Oodle، ما در واقع به شدت از فونت‌های گوگل استفاده می‌کنیم. هر زمان که یک برگه سبک فونت گوگل را در صفحه خود قرار می‌دهید، به دو زیر دامنه متصل می‌شود. و چیزی که Lighthouse به ما می‌گوید این است که اگر بتوانیم آن اتصال را گرم کنیم، می‌توانیم تا 300 میلی‌ثانیه در زمان اتصال اولیه خود صرفه‌جویی کنیم.

با بهره‌گیری از پیش‌اتصال لینک rel، می‌توانیم به طور مؤثر تأخیر اتصال را بپوشانیم.

مخصوصاً در مورد چیزی مثل فونت‌های گوگل که CSS مربوط به فونت ما در googleapis.com و منابع فونت ما در Gstatic میزبانی می‌شود، این می‌تواند تأثیر واقعاً بزرگی داشته باشد. بنابراین ما این بهینه‌سازی را اعمال کردیم و چند صد میلی‌ثانیه صرفه‌جویی کردیم.

نکته بعدی که Lighthouse پیشنهاد می‌دهد این است که درخواست‌های کلیدی را از قبل بارگذاری کنیم.

درخواست‌های کلید را از قبل بارگیری کنید
شکل ۱۸. درخواست‌های پیش‌بارگذاری کلید

<link rel=preload> واقعاً قدرتمند است، به مرورگر اطلاع می‌دهد که به عنوان بخشی از ناوبری فعلی به یک منبع نیاز است و سعی می‌کند مرورگر را در اسرع وقت وادار به دریافت آن کند.

حالا اینجا Lighthouse به ما می‌گوید که باید برویم و منابع کلیدی فونت وب خود را از قبل بارگذاری کنیم، زیرا ما در حال بارگذاری دو فونت وب هستیم.

پیش‌بارگذاری در یک فونت وب به این شکل است - با مشخص کردن rel=preload ، شما as فونت را ارسال می‌کنید و سپس نوع فونتی را که می‌خواهید بارگذاری کنید، مانند woff2، مشخص می‌کنید.

تأثیری که این می‌تواند روی صفحه شما داشته باشد کاملاً واضح است.

تأثیر پیش بارگذاری منابع
شکل ۱۹. تأثیر پیش‌بارگذاری منابع

معمولاً، بدون استفاده از پیش‌بارگذاری لینک rel، اگر فونت‌های وب برای صفحه شما حیاتی باشند، کاری که مرورگر باید انجام دهد این است که اول از همه HTML شما را دریافت کند، CSS شما را تجزیه کند، و در جایی بسیار بعد، بالاخره فونت‌های وب شما را دریافت کند.

با استفاده از پیش‌بارگذاری rel لینک، به محض اینکه مرورگر HTML شما را تجزیه کرد، می‌تواند خیلی زودتر شروع به دریافت آن فونت‌های وب کند. در مورد برنامه ما، این روش توانست یک ثانیه از زمان لازم برای رندر متن با استفاده از فونت‌های وب ما را کاهش دهد.

حالا اگر می‌خواهید فونت‌ها را با استفاده از فونت‌های گوگل از قبل بارگذاری کنید، خیلی هم سرراست نیست، یک نکته وجود دارد.

آدرس‌های اینترنتی فونت‌های گوگل که ما در صفحات فونت خود در استایل‌شیت‌هایمان مشخص می‌کنیم، چیزی است که تیم فونت‌ها مرتباً به‌روزرسانی می‌کنند. این آدرس‌های اینترنتی می‌توانند منقضی شوند یا با فواصل منظم به‌روزرسانی شوند، بنابراین اگر می‌خواهید کنترل کاملی بر تجربه بارگذاری فونت خود داشته باشید، پیشنهاد می‌کنیم فونت‌های وب خود را خودتان میزبانی کنید. این می‌تواند عالی باشد زیرا به شما امکان دسترسی به مواردی مانند پیش‌بارگذاری لینک rel را می‌دهد.

در مورد ما، ابزار Google Web Fonts Helper واقعاً مفید بود و به ما کمک کرد تا برخی از آن فونت‌های وب را به صورت آفلاین تنظیم کنیم و آنها را به صورت محلی تنظیم کنیم، بنابراین این ابزار را بررسی کنید.

چه از فونت‌های وب به عنوان بخشی از منابع حیاتی خود استفاده کنید و چه از جاوا اسکریپت، سعی کنید به مرورگر کمک کنید تا منابع حیاتی شما را در اسرع وقت ارائه دهد.

تجربی: نکات اولویت‌دار

امروز چیز خاصی برای به اشتراک گذاشتن با شما داریم. علاوه بر ویژگی‌هایی مانند نکات مربوط به منابع و همچنین پیش‌بارگذاری، ما روی یک ویژگی آزمایشی جدید مرورگر کار می‌کنیم که آن را نکات مربوط به اولویت می‌نامیم.

اولویت را برای محتوای قابل مشاهده اولیه تنظیم کنید
شکل 20. نکات مربوط به اولویت

این یک ویژگی جدید است که به شما امکان می‌دهد به مرورگر نشان دهید که یک منبع چقدر مهم است. این ویژگی یک ویژگی جدید - اهمیت - را با مقادیر low، high یا auto نمایش می‌دهد.

این به ما اجازه می‌دهد تا اولویت منابع کم‌اهمیت‌تر، مانند استایل‌های غیرحیاتی، تصاویر یا فراخوانی‌های API مربوط به واکشی را برای کاهش تداخل کاهش دهیم. همچنین می‌توانیم اولویت موارد مهم‌تر، مانند تصاویر اصلی خود را افزایش دهیم.

در مورد اپلیکیشن Oodle ما، این در واقع منجر به یک نقطه عملی شد که می‌توانستیم در آن بهینه‌سازی کنیم.

اولویت را برای محتوای قابل مشاهده اولیه تنظیم کنید
شکل ۲۱. اولویت را برای محتوای قابل مشاهده اولیه تنظیم کنید

قبل از اینکه بارگذاری تنبل را به تصاویرمان اضافه کنیم، کاری که مرورگر انجام می‌داد این بود که ما یک چرخ فلک تصویر با تمام طرح‌هایمان داشتیم و مرورگر از همان ابتدا تمام تصاویر را با اولویت بالا در ابتدای چرخ فلک دریافت می‌کرد. متأسفانه، تصاویری که در وسط چرخ فلک بودند برای کاربر از همه مهم‌تر بودند. بنابراین کاری که ما انجام دادیم این بود که اهمیت تصاویر پس‌زمینه را بسیار کم و تصاویر پیش‌زمینه را بسیار زیاد کردیم و این کار تأثیر دو ثانیه‌ای بر سرعت پایین اینترنت ۳G داشت و اینکه چقدر سریع توانستیم آن تصاویر را دریافت و رندر کنیم. بنابراین یک تجربه مثبت خوب.

ما امیدواریم که این ویژگی را ظرف چند هفته به Canary بیاوریم، پس منتظر آن باشید.

یک استراتژی برای بارگذاری فونت وب داشته باشید

تایپوگرافی برای طراحی خوب اساسی است و اگر از فونت‌های وب استفاده می‌کنید، در حالت ایده‌آل نمی‌خواهید رندر متن شما مسدود شود و قطعاً نمی‌خواهید متن نامرئی را نشان دهید.

ما اکنون این موضوع را در Lighthouse برجسته می‌کنیم، با اجتناب از متن نامرئی در حین بررسی بارگذاری فونت‌های وب .

هنگام بارگیری فونت‌های وب، از متن نامرئی جلوگیری کنید
شکل ۲۲. هنگام بارگذاری فونت‌های وب، از نمایش متن نامرئی جلوگیری کنید

اگر فونت‌های وب خود را با استفاده از یک بلوک فونت بارگذاری کنید، به مرورگر اجازه می‌دهید در صورت طولانی شدن زمان دریافت آن فونت وب، تصمیم بگیرد چه کاری انجام دهد. برخی از مرورگرها قبل از بازگشت به فونت سیستم، تا سه ثانیه برای این کار صبر می‌کنند و در نهایت پس از دانلود، آن را با فونت جایگزین می‌کنند.

ما سعی داریم از این متن نامرئی اجتناب کنیم، بنابراین در این مورد اگر فونت وب خیلی طول می‌کشید، نمی‌توانستیم طرح‌های کلاسیک این هفته را ببینیم. خوشبختانه، با ویژگی جدیدی به نام font-display ، در واقع کنترل بسیار بیشتری بر این فرآیند خواهید داشت.

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-display: swap;
      font-weight: 400;
      src: local('Montserrat Regular'), local('Montserrat-Regular'),
          /* Chrome 26+, Opera 23+, Firefox 39+ */
          url('montserrat-v12-latin-regular.woff2') format('woff2'),
            /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
          url('montserrat-v12-latin-regular.woff') format('woff');
    }

نمایش فونت به شما کمک می‌کند تا بر اساس مدت زمان تعویض فونت‌های وب، تصمیم بگیرید که چگونه آنها رندر شوند یا جایگزین شوند.

در این مورد ما از تعویض نمایش فونت استفاده می‌کنیم. تعویض به وجه فونت یک دوره بلوک صفر ثانیه‌ای و یک دوره تعویض بی‌نهایت می‌دهد. این بدان معناست که مرورگر متن شما را تقریباً بلافاصله با یک فونت جایگزین ترسیم می‌کند اگر فونت مدتی طول بکشد تا بارگذاری شود. و به محض اینکه وجه فونت در دسترس باشد، آن را تعویض می‌کند.

در مورد برنامه ما، دلیل عالی بودن این بود که به ما اجازه داد متن معناداری را خیلی زود نمایش دهیم و پس از آماده شدن، به فونت وب منتقل شویم.

نتیجه نمایش فونت
شکل ۲۳. نتیجه نمایش فونت

به طور کلی، اگر از فونت‌های وب استفاده می‌کنید، همانطور که درصد زیادی از وب این کار را می‌کند، یک استراتژی خوب برای بارگذاری فونت‌های وب داشته باشید.

ویژگی‌های پلتفرم وب زیادی وجود دارد که می‌توانید برای بهینه‌سازی تجربه بارگذاری فونت‌ها از آنها استفاده کنید، اما همچنین می‌توانید مخزن Web Font Recipes از Zach Leatherman را نیز بررسی کنید، زیرا واقعاً عالی است.

کاهش اسکریپت‌های مسدودکننده رندر

بخش‌های دیگری از برنامه ما وجود دارد که می‌توانیم آنها را زودتر در زنجیره دانلود قرار دهیم تا حداقل یک تجربه کاربری اولیه را کمی زودتر ارائه دهیم.

در نوار تایم‌لاین Lighthouse می‌توانید ببینید که در طول این چند ثانیه اول که همه منابع در حال بارگذاری هستند، کاربر واقعاً نمی‌تواند هیچ محتوایی را ببیند.

کاهش احتمال مسدود شدن رندر توسط استایل‌شیت‌ها
شکل ۲۴. کاهش احتمال مسدود شدن رندر در استایل‌شیت‌ها

دانلود و پردازش استایل‌شیت‌های خارجی، مانع از پیشرفت فرآیند رندرینگ ما می‌شود.

می‌توانیم با ارائه برخی از استایل‌ها کمی زودتر، مسیر رندر بحرانی خود را بهینه کنیم.

اگر استایل‌هایی که مسئول این رندر اولیه هستند را استخراج کنیم و آنها را در HTML خود به صورت inline قرار دهیم، مرورگر می‌تواند آنها را مستقیماً و بدون انتظار برای رسیدن stylesheetهای خارجی رندر کند.

در مورد ما، ما از یک ماژول NPM به نام Critical برای درج محتوای حیاتی خود در index.html در طول مرحله ساخت استفاده کردیم.

اگرچه این ماژول بخش عمده‌ی کار سنگین را برای ما انجام داد، اما هنوز هم کمی دشوار بود که این ماژول را به راحتی در مسیرهای مختلف به کار بگیریم.

اگر دقت نکنید یا ساختار سایت شما واقعاً پیچیده باشد، اگر از ابتدا معماری پوسته برنامه را برنامه‌ریزی نکرده باشید، معرفی این نوع الگو می‌تواند واقعاً دشوار باشد.

به همین دلیل است که در نظر گرفتن ملاحظات عملکرد از همان ابتدا بسیار مهم است. اگر از ابتدا برای عملکرد طراحی نکنید، احتمال زیادی وجود دارد که بعداً در انجام آن با مشکلاتی مواجه شوید.

در نهایت ریسک ما نتیجه داد، ما توانستیم آن را عملی کنیم و برنامه خیلی زودتر شروع به ارائه محتوا کرد و زمان اولین رنگ‌آمیزی معنادار ما را به طور قابل توجهی بهبود بخشید.

نتیجه

این لیست بلندی از بهینه‌سازی‌های عملکردی بود که ما روی سایت خود اعمال کردیم. بیایید نگاهی به نتیجه بیندازیم. این نحوه بارگذاری برنامه ما روی یک دستگاه تلفن همراه متوسط ​​​​در شبکه 3G، قبل و بعد از بهینه‌سازی است.

امتیاز عملکرد Lighthouse از ۲۳ به ۹۱ افزایش یافت. این پیشرفت بسیار خوبی از نظر سرعت است. تمام این تغییرات با بررسی و دنبال کردن مداوم گزارش Lighthouse توسط ما تقویت شده است. اگر مایلید ببینید که ما چگونه از نظر فنی تمام پیشرفت‌ها را پیاده‌سازی کرده‌ایم، می‌توانید نگاهی به مخزن ما ، به خصوص PRهایی که در آنجا قرار گرفته‌اند، بیندازید.

عملکرد پیش‌بینی‌کننده - تجربیات کاربری مبتنی بر داده

ما معتقدیم که یادگیری ماشینی فرصتی هیجان‌انگیز برای آینده در بسیاری از زمینه‌ها است. یکی از ایده‌هایی که امیدواریم آزمایش‌های بیشتری را در آینده برانگیزد، این است که داده‌های واقعی می‌توانند تجربیات کاربری که ما ایجاد می‌کنیم را هدایت کنند.

امروزه، ما تصمیمات خودسرانه زیادی در مورد آنچه کاربر ممکن است بخواهد یا نیاز داشته باشد، و بنابراین چه چیزی ارزش پیش‌دریافت، پیش‌بارگذاری یا پیش‌ذخیره‌سازی را دارد، می‌گیریم. اگر درست حدس بزنیم، می‌توانیم مقدار کمی از منابع را اولویت‌بندی کنیم، اما مقیاس‌بندی آن برای کل وب‌سایت واقعاً دشوار است.

ما در واقع داده‌هایی در دسترس داریم که می‌توانیم بهینه‌سازی‌های خود را بهتر انجام دهیم. با استفاده از API گزارش‌دهی گوگل آنالیتیکس می‌توانیم نگاهی به صفحه برتر بعدی و درصد خروج برای هر URL در سایت خود بیندازیم و بنابراین در مورد اینکه کدام منابع را باید در اولویت قرار دهیم، نتیجه‌گیری کنیم.

اگر این را با یک مدل احتمال خوب ترکیب کنیم، از هدر رفتن داده‌های کاربر با پیش‌واکشی بیش از حد محتوا جلوگیری می‌کنیم. می‌توانیم از داده‌های گوگل آنالیتیکس بهره ببریم و از یادگیری ماشین و مدل‌هایی مانند زنجیره‌های مارکوف یا شبکه عصبی برای پیاده‌سازی چنین مدل‌هایی استفاده کنیم.

بسته‌بندی داده‌محور برای برنامه‌های وب
شکل ۲۵. بسته‌بندی مبتنی بر داده برای برنامه‌های وب

برای تسهیل این آزمایش‌ها، خوشحالیم که از یک ابتکار جدید به نام Guess.js رونمایی کنیم.

حدس.js
شکل ۲۶. Guess.js

Guess.js پروژه‌ای است که بر تجربیات کاربری مبتنی بر داده برای وب تمرکز دارد. ما امیدواریم که این پروژه الهام‌بخش کاوش در استفاده از داده‌ها برای بهبود عملکرد وب و فراتر رفتن از آن باشد. این پروژه متن‌باز است و امروز در GitHub در دسترس است. این پروژه با همکاری جامعه متن‌باز توسط Minko Gechev، Kyle Matthews از Gatsby، Katie Hempenius و تعدادی دیگر ساخته شده است.

Guess.js را بررسی کنید، نظرتان را با ما در میان بگذارید.

خلاصه

امتیازها و معیارها در بهبود سرعت وب مفید هستند، اما آنها فقط وسیله هستند، نه خود هدف.

همه ما کندی بارگذاری صفحات را در حال حرکت تجربه کرده‌ایم، اما اکنون فرصتی داریم تا به کاربران خود تجربیات لذت‌بخش‌تری ارائه دهیم که واقعاً سریع بارگذاری می‌شوند.

بهبود عملکرد یک سفر است. بسیاری از تغییرات کوچک می‌توانند به دستاوردهای بزرگی منجر شوند. با استفاده از ابزارهای بهینه‌سازی مناسب و توجه به گزارش‌های Lighthouse، می‌توانید تجربه بهتر و جامع‌تری را برای کاربران خود فراهم کنید.

با تشکر ویژه از: وارد پیترز، مینکو گچف، کایل متیوز، کیتی همپنیوس، دام فارولینو، یوآو وایس، سوزی لو، یوسوکه اوتسونومیا، تام انکرز، لایت‌هاوس و گوگل دودلز.