بهینه‌سازی راه‌اندازی جاوا اسکریپت

As we build sites more heavily reliant on JavaScript, we sometimes pay for what we send down in ways that we can’t always easily see. در این مقاله، توضیح می‌دهیم که چرا کمی نظم می‌تواند به شما کمک کند تا سایتتان در دستگاه‌های همراه سریع‌تر بار شود و تعاملی باشد. ارائه جاوا اسکریپت کمتر می‌تواند به‌معنای زمان کمتر در انتقال شبکه، صرف زمان کمتر برای از حالت فشرده خارج کردن کد، و زمان کمتر برای تجزیه و کامپایل کردن این جاوا اسکریپت باشد.

شبکه

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

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

این می‌تواند مشکل‌ساز باشد، زیرا نوع اتصال شبکه مؤثر که کاربر دارد ممکن است درواقع 3G،‏ 4G، یا Wi-Fi نباشد. ممکن است به Wi-Fi قهوه‌سرا متصل باشید اما به نقطه اتصال تلفن همراه با سرعت 2G وصل شده باشید.

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

  • فقط کدی را که کاربر نیاز دارد ارسال می‌کند.
    • از تقسیم کد برای تقسیم کردن جاوا اسکریپت به بخش‌های حیاتی و غیرحیاتی استفاده کنید. بسته‌بندهای واحد مثل webpack از تقسیم کد پشتیبانی می‌کنند.
    • بار کردن کُند در کدی که غیرمهم است.
  • کوچک‌سازی
  • فشرده‌سازی
    • حداقل از gzip برای فشرده‌سازی منابع مبتنی بر نوشتار استفاده کنید.
    • استفاده از Brotli ~q11 را درنظر بگیرید. Brotli ازنظر نسبت فشرده‌سازی از gzip بهتر عمل می‌کند. این ابزار به CertSimple کمک کرد ٪۱۷ در اندازه بایت‌های JS فشرده‌شده صرفه‌جویی کند و به LinkedIn کمک کرد ٪۴ در زمان بار کردن صرفه‌جویی کند.
  • برداشتن کد استفاده‌نشده.
    • با پوشش کد DevTools، فرصت‌های کدی را که می‌توان حذف کرد یا به‌صورت کُند بار کرد شناسایی کنید.
    • از babel-preset-env و browserlist استفاده کنید تا از ترجمه مبدأ به مبدأ ویژگی‌هایی که درحال‌حاضر در مرورگرهای نو وجود دارند اجتناب کنید. توسعه‌دهندگان پیشرفته ممکن است متوجه شوند که تجزیه‌وتحلیل دقیق بسته‌های webpack به شناسایی فرصت‌هایی برای حذف وابستگی‌های غیرضروری کمک می‌کند.
    • برای حذف کد، به tree-shaking، بهینه‌سازی‌های پیشرفته Closure Compiler، و افزایه‌های پیرایش کتابخانه مانند lodash-babel-plugin یا ContextReplacementPlugin webpack برای کتابخانه‌هایی مانند Moment.js مراجعه کنید.
  • کد ذخیره‌سازی موقت برای به‌حداقل رساندن سفرهای شبکه.
    • از ذخیره‌سازی HTTP در حافظه نهان استفاده کنید تا مطمئن شوید مرورگرها پاسخ‌ها را به‌طور مؤثر در حافظه نهان ذخیره می‌کنند. طول عمر بهینه را برای اسکریپت‌ها (max-age) تعیین کنید و کدهای اعتبارسنجی (ETag) را ارائه دهید تا از انتقال بایت‌های تغییرنیافته جلوگیری شود.
    • ذخیره مؤقت Service Worker می‌تواند برنامه شما را دربرابر شبکه مقاوم کند و به شما دسترسی مشتاقانه به ویژگی‌هایی مثل حافظه پنهان کد V8 بدهد.
    • از ذخیره موقت بلندمدت استفاده کنید تا مجبور نباشید منابعی را که تغییر نکرده‌اند دوباره واکشی کنید. اگر از Webpack استفاده می‌کنید، درهم‌سازی نام فایل را ببینید.

تجزیه/ترجمه کردن

پس‌از بارگیری، یکی از سنگین‌ترین هزینه‌های جاوا اسکریپت، زمان لازم برای موتور جاوا اسکریپت برای تجزیه/کامپایل این کد است. در Chrome DevTools، تجزیه و کامپایل کردن بخشی از زمان زرد «اسکریپت‌سازی» در پانل «عملکرد» است.

ALT_TEXT_HERE

برگه‌های «پایین به بالا» و «درخت فراخوانی» زمان‌بندی دقیق تجزیه/ترجمه را به شما نشان می‌دهند:

ALT_TEXT_HERE
Chrome DevTools Performance panel > Bottom-Up. با فعال کردن «آمار تماس زمان اجرای V8»، می‌توانیم زمان صرف‌شده در فازهایی مانند «تجزیه» و «کامپایل» را ببینیم

اما چرا این موضوع اهمیت دارد؟

ALT_TEXT_HERE

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

بایت به بایت، پردازش جاوا اسکریپت برای مرورگر گران‌تر از تصویر یا قلم وب با اندازه معادل است — تام دیل

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

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

وقتی می‌گوییم تجزیه و کامپایل کردن کند است، بافت مهم است — در اینجا درباره تلفن‌های همراه متوسط صحبت می‌کنیم. کاربران معمولی ممکن است تلفن‌هایی با CPU و GPU کند، بدون حافظه پنهان L2/L3، و حتی با محدودیت حافظه داشته باشند.

قابلیت‌های شبکه و قابلیت‌های دستگاه همیشه باهم مطابقت ندارند. کاربری که اتصال Fiber فوق‌العاده‌ای دارد لزوماً بهترین CPU را برای تجزیه و ارزیابی جاوا اسکریپت ارسال‌شده به دستگاهش ندارد. این موضوع برعکس هم صادق است… اتصال شبکه بسیار بد، اما واحد پردازش مرکزی بسیار سریع. — کریستوفر بکستر، LinkedIn

در زیر می‌توانیم هزینه تجزیه کردن حدود ۱ مگابایت جاوا اسکریپت ازفشرده‌خارج‌شده (ساده) را در سخت‌افزار رده‌پایین و رده‌بالا ببینیم. بین سریع‌ترین تلفن‌های موجود در بازار و تلفن‌های معمولی، ۲ تا ۵ برابر تفاوت در زمان تجزیه/کامپایل کد وجود دارد.

ALT_TEXT_HERE
این نمودار زمان‌های تجزیه را برای یک بسته ۱ مگابایتی جاوا اسکریپت (تقریباً ۲۵۰ کیلوبایت فشرده‌شده با gzip) در دستگاه‌های رایانه و تلفن همراه از کلاس‌های مختلف برجسته می‌کند. هنگام بررسی هزینه تجزیه، باید ارقام ازحالت فشرده خارج‌شده را درنظر گرفت، مثلاً JS فشرده‌شده با gzip با حجم حدود ۲۵۰ کیلوبایت به حدود ۱ مگابایت کد ازحالت فشرده خارج می‌شود.

درباره سایت‌های دنیای واقعی، مثل CNN.com، چطور؟

در iPhone 8 رده‌بالا، تجزیه/کامپایل کردن JS مربوط به CNN فقط حدود ۴ ثانیه طول می‌کشد، درحالی‌که در یک تلفن متوسط (Moto G4) حدود ۱۳ ثانیه طول می‌کشد. این امر می‌تواند تأثیر قابل‌توجهی بر سرعت تعامل کامل کاربر با این سایت داشته باشد.

ALT_TEXT_HERE
در بالا زمان‌های تجزیه را می‌بینیم که عملکرد تراشه A11 Bionic شرکت Apple را با Snapdragon 617 در سخت‌افزار Android معمولی‌تر مقایسه می‌کند.

این امر اهمیت آزمایش روی سخت‌افزار معمولی (مانند Moto G4) را به‌جای آزمایش روی تلفنی که ممکن است در جیب شما باشد، برجسته می‌کند. بافت مهم است بااین‌حال: برای شرایط دستگاه و شبکه‌ای که کاربران شما دارند بهینه‌سازی کنید.

ALT_TEXT_HERE
Google Analytics می‌تواند اطلاعات آماری درباره کلاس‌های دستگاه همراه که کاربران واقعی شما بااستفاده از آن‌ها به سایتتان دسترسی پیدا می‌کنند ارائه دهد. این کار می‌تواند فرصت‌هایی را برای درک محدودیت‌های واقعی CPU/GPU که با آن‌ها کار می‌کنند فراهم کند.

آیا واقعاً جاوا اسکریپت زیادی ارسال می‌کنیم؟ شاید :)

بااستفاده از HTTP Archive (تقریباً ۵۰۰ هزار سایت برتر) برای تجزیه‌وتحلیل وضعیت جاوا اسکریپت در تلفن همراه، می‌توانیم ببینیم که ۱۴ ثانیه طول می‌کشد تا ۵۰٪ سایت‌ها تعاملی شوند. این سایت‌ها تا ۴ ثانیه را فقط صرف تجزیه و کامپایل JS می‌کنند.

ALT_TEXT_HERE

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

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

زمان اجرا

فقط تجزیه و کامپایل نیست که می‌تواند هزینه داشته باشد. اجرای جاوا اسکریپت (اجرای کد پس‌از تجزیه/کامپایل شدن) یکی از عملیاتی است که باید در رشته اصلی اتفاق بیفتد. زمان‌های اجرای طولانی همچنین می‌تواند زمان تعامل کاربر با سایت شما را به تأخیر بیندازد.

ALT_TEXT_HERE

اگر اجرای اسکریپت بیش‌از ۵۰ میلی‌ثانیه طول بکشد، زمان تعاملی به‌اندازه کل مدت‌زمانی که برای بارگیری، کامپایل، و اجرای JS لازم است به‌تأخیر می‌افتد — الکس راسل

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

سایر هزینه‌ها

جاوا اسکریپت می‌تواند به روش‌های دیگری بر عملکرد صفحه تأثیر بگذارد:

  • حافظه. صفحه‌ها ممکن است به‌دلیل GC (جمع‌آوری زباله) به‌طور مکرر دچار لرزش یا توقف شوند. وقتی مرورگر حافظه را بازپس می‌گیرد، اجرای JS موقتاً متوقف می‌شود، بنابراین مرورگری که به‌طور مکرر زباله جمع‌آوری می‌کند می‌تواند اجرا را بیشتر از آنچه ما می‌خواهیم موقتاً متوقف کند. از نشت حافظه و وقفه‌های مکرر gc اجتناب کنید تا صفحات بدون لرزش باقی بمانند.
  • درطول زمان اجرا، جاوا اسکریپت طولانی‌مدت می‌تواند رشته اصلی را مسدود کند و باعث شود صفحه‌ها پاسخگو نباشند. تقسیم کردن کار به بخش‌های کوچک‌تر (بااستفاده از requestAnimationFrame() یا requestIdleCallback() برای زمان‌بندی) می‌تواند مشکلات پاسخ‌دهی را به‌حداقل برساند که این امر می‌تواند به بهبود تعامل با نقاشی بعدی (INP) کمک کند.

الگوهای کاهش هزینه ارائه جاوا اسکریپت

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

PRPL

PRPL (Push, Render, Pre-cache, Lazy-load) الگویی است که برای تعامل ازطریق تقسیم کد و ذخیره در حافظه نهان تهاجمی بهینه‌سازی می‌کند:

ALT_TEXT_HERE

بیایید تأثیری را که می‌تواند داشته باشد تجسم کنیم.

ما زمان بارگیری سایت‌های تلفن همراه پرطرفدار و برنامه‌های وب پیش‌رو را بااستفاده از «آمار تماس زمان اجرای» V8 تجزیه‌وتحلیل می‌کنیم. همان‌طور که می‌بینیم، زمان تجزیه (به رنگ نارنجی نشان داده شده است) بخش قابل‌توجهی از زمانی است که بسیاری از این سایت‌ها صرف می‌کنند:

ALT_TEXT_HERE

Wego، سایتی که از PRPL استفاده می‌کند، موفق شده است زمان تجزیه پایینی برای مسیرهایش حفظ کند و خیلی سریع تعاملی شود. Many of the other sites above adopted code-splitting and performance budgets to try lowering their JS costs.

راه‌اندازی تدریجی

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

مراقب باشید — این کار هزینه‌های خودش را دارد. شما ۱) معمولاً پاسخ HTML بزرگتری ارسال می‌کنید که می‌تواند تعامل‌پذیری ما را تحت فشار قرار دهد، ۲) می‌توانید کاربر را در دره وهمی رها کنید که نیمی از تجربه نمی‌تواند واقعاً تعاملی باشد تا زمانی که پردازش JavaScript به پایان برسد.

«راه‌اندازی تدریجی» ممکن است رویکرد بهتری باشد. صفحه‌ای با حداقل عملکرد (متشکل از HTML/JS/CSS موردنیاز برای مسیر فعلی) ارسال کنید. با رسیدن منابع بیشتر، برنامه می‌تواند بارگیری کُند انجام دهد و ویژگی‌های بیشتری را باز کند.

ALT_TEXT_HERE
Progressive Bootstrapping نوشته Paul Lewis

بار کردن کد متناسب با آنچه در نما است، هدف نهایی است. PRPL و Progressive Bootstrapping الگوهایی هستند که می‌توانند به انجام این کار کمک کنند.

نتیجه‌گیری‌ها

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

تیم‌ها با اتخاذ بودجه‌های عملکردی سخت‌گیرانه برای پایین نگه داشتن زمان انتقال و تجزیه/ترجمه جاوا اسکریپت خود به موفقیت دست یافته‌اند. به مقاله الکس راسل با عنوان «Can You Afford It?: بودجه‌های عملکرد وب در دنیای واقعی» برای راهنمایی درباره بودجه‌های تلفن همراه.

ALT_TEXT_HERE
مفید است که درنظر بگیریم تصمیمات معماری که می‌گیریم چقدر «فضای خالی» JS می‌تواند برای منطق برنامه باقی بگذارد.

اگر درحال ساختن سایتی هستید که دستگاه‌های همراه را هدف قرار می‌دهد، تمام تلاش خود را بکنید تا روی سخت‌افزار نمونه توسعه دهید، زمان‌های تجزیه/ترجمه JavaScript خود را پایین نگه دارید و یک «بودجه عملکرد» اتخاذ کنید تا مطمئن شوید تیم شما می‌تواند هزینه‌های JavaScript خود را زیرنظر داشته باشد.

بیشتر بدانید