Вызовет ли один и тот же `<script>` в DOM дважды вызовет второй запрос в любом браузере? - PullRequest
4 голосов
/ 12 августа 2010

Я работал над небольшим количеством кода JavaScript, который при определенных условиях лениво загружает пару различных библиотек ( Clicky Web Analytics и механизм выбора Sizzle ).

Этот скрипт загружается миллионы раз в день, поэтому оптимизация производительности является серьезной проблемой.На сегодняшний день я использовал пару флагов, таких как script_loading и script_loaded, чтобы убедиться, что я не загружаю ни одну библиотеку более одного раза (под "нагрузкой" я имею в виду запрос сценариев после загрузки страницы путем вставкиэлемент <script> в DOM).

Мой вопрос: вместо того, чтобы полагаться на эти флаги, которые стали немного громоздкими и трудными для понимания в моем коде (вспомним обратные вызовы и все ловушки асинхронногокод), кросс-браузер безопасен (т. е. обратно в IE 6) и не влияет на производительность, просто вызывая простую функцию для вставки элемента <script> всякий раз, когда я достигаю ветви кода, для которой нужна одна из этих библиотек?

Последний по-прежнему гарантирует, что я загружаю любую библиотеку только тогда, когда она мне нужна, а также упрощает и уменьшает вес моей кодовой базы, но я должен быть абсолютно уверен, что это не приведет к дополнительным, ненужнымзапросы браузера.

Я догадываюсь, что добавление элемента <script> несколько раз не будет вредным, так как я предполагаю, что браузеры должныognize дубликат URL src и использование локальной кэшированной копии.Но вы знаете, что происходит, когда мы предполагаем ...

Я надеюсь, что кто-то достаточно знаком с поведением различных современных (и не очень современных, таких как IE 6) браузеров, чтобы иметь возможностьговорить с тем, что произойдет в этом случае.

А пока я напишу тест, чтобы попытаться ответить на этот вопрос из первых рук.Я сомневаюсь, что это может быть трудным и громоздким, чтобы с уверенностью проверить в каждом браузере, что мой скрипт должен поддерживать.

Заранее благодарен за любую помощь и / или ввод!

Ответы [ 3 ]

2 голосов
/ 12 августа 2010

Есть альтернативное решение.

В тот момент, когда вы вставляете новый элемент сценария в DOM, не могли бы вы выполнить быстрое сканирование существующих элементов сценария, чтобы выяснить, есть ли другой элемент с таким же src? Если есть, не вставить другой?

Код Javascript на той же странице не может работать в многопоточном режиме, поэтому вы не получите никаких условий гонки в середине этого или чего-либо еще.

В противном случае вы просто полагаетесь на поведение кэширования текущих браузеров (и HTTP-прокси).

1 голос
/ 12 августа 2010

Страница обрабатывается как поток.Если вы загружаете один и тот же скрипт несколько раз, он будет запускаться каждый раз, когда он включается.Очевидно, что из-за кеша браузера он будет запрашиваться с сервера только один раз.

Я бы держался подальше от такого подхода - вставлять теги сценария для одного и того же сценария несколько раз.Я решаю эту проблему, чтобы иметь функцию «тест» для каждого скрипта, чтобы увидеть, если он загружен.Например, для sizzle это будет "function () {return !! window ['Sizzle'];}".Тег сценария вставляется только в том случае, если тестовая функция возвращает false.

0 голосов
/ 14 августа 2010

Каждый раз, когда вы добавляете скрипт на свою страницу, даже если он имеет тот же src, браузер может найти его в локальном кеше или спросить у сервера, изменился ли контент.

Использование переменной для проверкиесли скрипт включен, это хороший способ уменьшить загрузку, и он очень прост: например, это может работать для вас:

var LOADED_JS=Object();
function js_isIncluded(name){//returns true if the js is already loaded
   return LOADED_JS[name]!==undefined;
}
function include_js(name){
    if(!js_isIncluded(name)){
        YOUR_LAZY_LOADING_FUNCTION(name);
        LOADED_JS[name]=true;
    }
}

вы также можете получить все элементы скрипта и проверить src, мое решение лучшепотому что он снижает скорость и простоту хеш-массива, а скрипт src имеет абсолютный путь, даже если вы задаете его с относительным путем.
вы также можете захотеть запустить массив с нормально загруженными скриптами (без отложенной загрузки)на странице init, чтобы избежать двойного запроса.

...