مداخله در برابر document.write()

آیا اخیراً اخطاری مانند زیر را در Developer Console خود در Chrome دیده‌اید و فکر کرده‌اید که این هشدار چیست؟

(index):34 A Parser-blocking, cross-origin script,
https://paul.kinlan.me/ad-inject.js, is invoked via document.write().
This may be blocked by the browser if the device has poor network connectivity.

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

یکی از دلایل شناخته شده عملکرد ضعیف، استفاده از document.write() در داخل صفحات است، به ویژه آن دسته از کاربردهایی که اسکریپت ها را تزریق می کنند. همانطور که به نظر می رسد بی ضرر است، می تواند مشکلات واقعی را برای کاربران ایجاد کند.

document.write('<script src="https://example.com/ad-inject.js"></script>');

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

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

ما داده‌ها را از یک آزمایش میدانی 28 روزه روی 1٪ از کاربران پایدار Chrome جمع‌آوری کردیم که محدود به کاربرانی در اتصالات 2G است. ما دیدیم که 7.6٪ از تمام صفحات بارگذاری شده در 2G شامل حداقل یک اسکریپت متقاطع و مسدودکننده تجزیه کننده است که از طریق document.write() در سند سطح بالا درج شده است. در نتیجه مسدود کردن بارگذاری این اسکریپت ها، شاهد پیشرفت های زیر در آن بارها بودیم:

  • 10 درصد بارگذاری بیشتر صفحه به اولین رنگ محتوا (یک تأیید بصری برای کاربر مبنی بر اینکه صفحه به طور مؤثر بارگیری می شود)، 25 درصد بارگذاری بیشتر صفحه به حالت کاملاً تجزیه شده و 10 درصد بارگذاری مجدد کمتر که نشان دهنده کاهش ناامیدی کاربر است.
  • 21% کاهش میانگین زمان (بیش از یک ثانیه سریعتر) تا اولین رنگ پر محتوا
  • کاهش 38 درصدی به میانگین زمان تجزیه یک صفحه، که نشان دهنده بهبودی نزدیک به شش ثانیه است و زمان نمایش آنچه برای کاربر مهم است را به طور چشمگیری کاهش می دهد.

با در نظر گرفتن این داده‌ها، Chrome، از نسخه 55 شروع می‌کند، زمانی که این الگوی بد شناخته شده را با تغییر نحوه استفاده document.write() در Chrome (به وضعیت Chrome مراجعه کنید) از طرف همه کاربران مداخله می‌کند . به طور خاص Chrome عناصر <script> تزریق شده از طریق document.write() را زمانی که همه شرایط زیر برآورده می شود اجرا نمی کند:

  1. کاربر در یک اتصال آهسته است، به ویژه زمانی که کاربر در 2G است. (در آینده، این تغییر ممکن است به سایر کاربرانی که اتصالات آهسته دارند، مانند 3G کند یا وای فای کند، گسترش یابد.)
  2. document.write() در یک سند سطح بالا است. این مداخله برای اسکریپت های document.written در iframes اعمال نمی شود زیرا نمایش صفحه اصلی را مسدود نمی کنند.
  3. اسکریپت موجود در document.write() تجزیه کننده است. اسکریپت‌هایی با ویژگی‌های « async » یا « defer » همچنان اجرا می‌شوند.
  4. اسکریپت در همان سایت میزبانی نمی شود. به عبارت دیگر، Chrome برای اسکریپت‌هایی با eTLD+1 منطبق (مثلاً اسکریپتی که در js.example.org درج شده در www.example.org میزبانی می‌شود) دخالت نمی‌کند.
  5. اسکریپت از قبل در حافظه پنهان HTTP مرورگر وجود ندارد. اسکریپت های موجود در حافظه نهان دچار تاخیر شبکه نمی شوند و همچنان اجرا می شوند.
  6. درخواست صفحه بارگذاری مجدد نیست. اگر کاربر بارگیری مجدد را راه اندازی کند، کروم مداخله نمی کند و صفحه را به طور معمول اجرا می کند.

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

چگونه این را درست کنم؟

این پاسخ ساده این است که اسکریپت ها را با استفاده از document.write() تزریق نکنید. ما مجموعه ای از خدمات شناخته شده را برای پشتیبانی از لودر ناهمزمان نگهداری می کنیم که شما را تشویق می کنیم به بررسی آنها ادامه دهید.

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

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

اگر ارائه‌دهنده‌تان قطعه‌ای به شما بدهد که شامل document.write() ، ممکن است برای شما یک ویژگی async به عنصر اسکریپت اضافه کنید، یا اینکه عناصر اسکریپت را با DOM API مانند document.appendChild() یا اضافه کنید. parentNode.insertBefore() .

چگونه تشخیص دهیم که سایت شما تحت تأثیر قرار گرفته است

تعداد زیادی معیار وجود دارد که تعیین می کند آیا محدودیت اجرا شده است، بنابراین چگونه می دانید که آیا تحت تأثیر قرار گرفته اید؟

تشخیص زمانی که کاربر در 2G است

برای درک تأثیر بالقوه این تغییر ابتدا باید بدانید که چه تعداد از کاربران شما در 2G خواهند بود. می‌توانید با استفاده از Network Information API که در Chrome موجود است، نوع شبکه و سرعت فعلی کاربر را تشخیص دهید و سپس به سیستم‌های تحلیلی یا معیارهای کاربر واقعی (RUM) خود هشدار ارسال کنید.

if(navigator.connection &&
    navigator.connection.type === 'cellular' &&
    navigator.connection.downlinkMax <= 0.115) {
    // Notify your service to indicate that you might be affected by this restriction.
}

دریافت هشدارها در Chrome DevTools

از Chrome 53، DevTools هشدارهایی را برای عبارات مشکل‌ساز document.write() صادر می‌کند. به طور خاص، اگر یک درخواست document.write() با معیارهای 2 تا 5 مطابقت داشته باشد (Chrome معیارهای اتصال را هنگام ارسال این هشدار نادیده می گیرد)، هشدار چیزی شبیه به:

هشدار نوشتن سند

دیدن اخطارها در Chrome DevTools عالی است، اما چگونه می‌توانید این را در مقیاس تشخیص دهید؟ می‌توانید سرصفحه‌های HTTP را که در زمان انجام مداخله به سرور شما ارسال می‌شوند، بررسی کنید.

هدرهای HTTP خود را در منبع اسکریپت بررسی کنید

وقتی یک اسکریپت درج شده از طریق document.write مسدود شد، Chrome هدر زیر را به منبع درخواستی ارسال می‌کند:

Intervention: <https://shorturl/relevant/spec>;

وقتی یک اسکریپت درج شده از طریق document.write پیدا می‌شود و می‌تواند در شرایط مختلف مسدود شود، Chrome ممکن است ارسال کند:

Intervention: <https://shorturl/relevant/spec>; level="warning"

هدر مداخله به عنوان بخشی از درخواست GET برای اسکریپت (در صورت مداخله واقعی به صورت ناهمزمان) ارسال می شود.

آینده چه چیزی در انتظار شماست؟

برنامه اولیه این است که این مداخله را زمانی اجرا کنیم که معیارها را برآورده کنیم. ما با نمایش فقط یک هشدار در Developer Console در Chrome 53 شروع کردیم. (بتا در جولای 2016 بود. انتظار داریم Stable در سپتامبر 2016 برای همه کاربران در دسترس باشد.)

ما برای مسدود کردن اسکریپت‌های تزریق شده برای کاربران 2G که به طور آزمایشی در Chrome 54 شروع می‌شود، مداخله خواهیم کرد، که تخمین زده می‌شود در اواسط اکتبر 2016 برای همه کاربران عرضه شود. برای به‌روزرسانی‌های بیشتر، ورودی وضعیت Chrome را بررسی کنید.

با گذشت زمان، ما به دنبال مداخله در زمانی هستیم که هر کاربری اتصال کندی دارد (یعنی سرعت 3G یا WiFi کند). این ورودی وضعیت Chrome را دنبال کنید.

می خواهید بیشتر بدانید؟

برای کسب اطلاعات بیشتر، این منابع اضافی را ببینید: