Асинхронный и готовый документ
Я пытаюсь оптимизировать свои страницы, помещая некоторые атрибуты async
в мои скрипты. Кажется, он разбивает мой javascript, так как $(document).ready
выполняется до загрузки всех скриптов!
Я видел, что могу решить проблему, поставив $(window).load
вместо $(document).ready
, но мне было интересно, есть ли лучшее решение.
Это решение вызывает в моем случае 2 проблемы:
- Мне нужно изменить все
$(document).ready
и сообщить всем разработчикам, чтобы он больше не использовал его
- Сценарии будут выполнены после загрузки всех изображений. На моем веб-сайте много тяжелых изображений, и мне действительно нужно, чтобы некоторые сценарии исполнялись как можно скорее после того, как dom готов.
Есть ли у вас какие-то волшебные трюки? Может, положить все сценарии в конец? используйте defer
вместо async
?
Ответы
Ответ 1
После некоторых обширных исследований я могу определенно сказать, что создание сценариев в конце страницы - лучшая практика.
Yahoo соглашается со мной: http://developer.yahoo.com/performance/rules.html#js_bottom
Google не говорит об этой практике и предпочитает асинхронные скрипты: https://developers.google.com/speed/docs/best-practices/rtt#PreferAsyncResources
IMHO, размещение script в конце страницы имеет несколько преимуществ по сравнению с async/defer:
- Он будет работать для всех браузеров (да, даже IE;))
- Вы гарантируете выполнение заказа
- Вам не нужно использовать
$(document).ready
или $(window).load
- Ваши скрипты могут выполняться до загрузки изображений
- Как async/defer, ваша страница будет отображаться быстрее
- Когда DOM запускает готовое событие, все сценарии загружаются
- Может быть оптимизирован путем слияния всех js в одном файле без проблем (с помощью инструмента, такого как mod_pagespeed)
Единственный недостаток, который я вижу, заключается в том, что браузер не сможет распараллелить загрузку.
Одной из веских причин использовать async/defer вместо этого является то, что у вас есть script, который полностью независим (не нужно полагаться на порядок выполнения) и который не нужно выполнять в определенный момент времени. Пример: аналитика google.
Ответ 2
Если вы не хотите использовать загрузчик сценариев, вы можете использовать следующий подход, который позволит вам оставить на месте ваши сценарии $ (document).ready - измененные следующим образом:
$(()=>{
function checkAllDownloads() {
// Ensure your namespace exists.
window.mynamespace = window.mynamespace || {};
// Have each of your scripts setup a variable in your namespace when the download has completed.
// That way you can set async on all your scripts except jquery.
// Use the document ready event - this code - to check if all your scripts have downloaded.
if (window.mynamespace.script1 && window.mynamespace.script2){
// Proceed with page initialisation now that all scripts have been downloaded.
// [ Add your page initialisation code here ].
return;
}
// Not all downloads have completed.
// Schedule another check to give the async downloads time to complete.
setTimeout(checkAllDownloads, 500);
}
// check if it is safe to initialise the page by checking if all downloads have completed.
checkAllDownloads();
})
Ответ 3
defer
определенно лучше, чем async
потому что он:
- загружается асинхронно (как асинхронно)
- гарантирует выполнение заказа (в отличие от асинхронного)
- выполняется в конце (в отличие от асинхронного выполнения, которое выполняется параллельно, когда страница все еще загружается)
- JQuery
ready
запускается после загрузки "отложенных" скриптов (это то, что вы спрашиваете)
Этот SO-ответ имеет очень хорошую картину, иллюстрирующую порядок отложенной/асинхронной загрузки, супер-понятный.