Ленивая загрузка JavaScript и Inline JavaScript - PullRequest
16 голосов
/ 20 января 2012

Я заметил на <head> моего сайта (для работы), там много тегов <link rel="stylesheet" type="text/css" href="" /> и <script type="text/javascript" src="">.Еще больше файлов JavaScript / CSS загружаются только для определенных страниц (мы используем CodeIgniter, а пути к файлам передаются в представление заголовка).

Я рассматривал вопрос об использовании условного / асинхронного загрузчика (например, yepnope.js, head.js и т. д.), но я заметил небольшую проблему с этим.

На наш взгляд, есть встроенный JavaScript, некоторые используют $(function(){}) некоторые используют $(document).ready(function(){}),а у некоторых просто есть код (использующий jQuery), который не находится в блоке ready.

Без редактирования КАЖДОГО файла представления, чтобы обернуть его код в функцию и вызова этого при загрузке файлов JS, есть ли способотложить встроенный код до асинхронной загрузки JavaScript?

Ответы [ 7 ]

28 голосов
/ 17 апреля 2012

Вы можете фактически бездействовать во встроенном JavaScript: 1- Измените параметр типа во встроенном сценарии на: text / delayscript

ОТ

    <!– Inline Script –>
<script type="text/javascript" language="javaScript">
             /* Code */
</script>

На

    <!– Inline Script –>
<script type="text/delayscript">
             /* Code */
</script>

Придание тегу script пользовательского типа MIME text / delayscript заставляет браузер игнорировать его содержимое (обратите внимание, что полное его исключение будет по умолчанию использовать text / javascript).

2 - Ленивая загрузка всех встроенных скриптов Однажды заголовки.js (или другой фреймворк, который вы можете использовать) подтверждает, что он загружает все ваши внешние JS лениво, затем вы можете получить содержимое всех ваших пользовательских тегов скрипта и вставить их на страницу:

<script>
head.ready(function() {
    var 
        _head = document.getElementsByTagName("head")[0],
        _script = document.createElement('script'),
        _scripts = document.getElementsByTagName("script"),
        _txt = "text/delayscript",
        _contents = []
    ;

    for(var i=0,l=_scripts.length;i<l;i++){
        var _type = _scripts[i].getAttribute("type");
            if(_type && _type.toLowerCase() ==_txt)
                _contents.push(_scripts[i].innerHTML)
    }


    _script.type = 'text/javascript';
    _script.innerHTML = _contents.join(" ");
    _head.appendChild(_script);

});

Чтобы быть еще более изящным, вы можете фактически сохранить встроенные сценарии в их исходной иерархии в дереве DOM вместо того, чтобы заклинивать все их содержимое в одном сценарии, как я предлагал выше, заменив отмеченный тег встроенного сценарияновым, который имеет тип MIME текст / JavaScript:

head.ready(function() {
var 
    _scripts = document.getElementsByTagName("script"),
    _doc = document,
    _txt = "text/delayscript"
;

for(var i=0,l=_scripts.length;i<l;i++){
    var _type = _scripts[i].getAttribute("type");
        if(_type && _type.toLowerCase() ==_txt)
            _scripts[i].parentNode.replaceChild((function(sB){
                var _s = _doc.createElement('script');
                _s.type = 'text/javascript';
                _s.innerHTML = sB.innerHTML;

                return _s;
            })(_scripts[i]), _scripts[i]);
}
});
5 голосов
/ 20 января 2012

Вы должны рассмотреть возможность перемещения встроенного кода «снаружи» и включить его в

<script defer="defer" type="text/javascript" src="">
2 голосов
/ 12 марта 2017

HTML5 представил новый параметр async для сценариев, имеющих определенный src.

Вы можете добавить его непосредственно на любой элемент <script>:

<script src='/js/script.js' async></script>

НО: имейте в виду, что он не будет работать на встроенных скриптах!

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

Установите этот логический атрибут, чтобы указать, что браузер должен, если возможно, выполнять сценарий асинхронно. Он не влияет на встроенные сценарии (т. Е. Сценарии, не имеющие атрибута src).

Например, если у вас есть следующая конфигурация:

<script src='/js/jquery.min.js' async></script>
<script>
    // --> jQuery won't be loaded when this script will be executed!
    // This will throw an error.
    $(function () {
        $('#element').doSomething();
    });
</script>
2 голосов
/ 26 января 2012

Прежде всего, я бы порекомендовал вам тщательно проанализировать загрузку скриптов на стороне клиента, причем не только для первой загрузки JavaScript, но и для загрузки тех же файлов JavaScript во второй раз или для их загрузки в другой стр. Если ETag правильно установлен в сценариях веб-сервером или если вы используете другие параметры кэширования HTTP (подробности см. В руководстве по кэшированию ) для файлов JavaScripts, то загрузка самих файлов не будет выполняться и только повторная проверка кеша будет выполнена. Так что, может быть, проблема, которую вы описываете, не так важна, как выглядит.

Если вы решили загружать некоторые сценарии динамически, вы можете использовать jQuery.getScript и поместить весь зависимый код внутри обратного вызова success. Если вам нужно загрузить один или два файла JavaScript, способ будет работать очень хорошо, но если вам нужно загрузить список файлов JavaScript с более сложной зависимостью, реализация может оказаться не такой простой. В этом случае вы можете использовать document.writeln внутри <head>. Использование метода внутри <head> практически не имеет недостатков (подробнее см. здесь ).

1 голос
/ 27 августа 2016

Вместо встроенных скриптов создайте встроенные функции. Затем в конце вашего файла JavaScript вызовите функцию, если она существует.

function inline_script() {.. code ..}

Внутри вашего составного javery + и т.д. асинхронного файла JavaScript:

if (typeof(inline_script) == 'function') inline_script()

Вам нужно будет сделать некоторые тасования, чтобы убедиться, что у вас есть только один inline_script на страницу, или использовать какое-то кэширование, чтобы собрать их вместе, если вы вызываете его более одного раза.

В нынешнем возрасте это все еще забавная проблема, хотя этот вопрос старый, асинхронные сценарии = довольно круто

1 голос
/ 18 апреля 2012

В зависимости от ваших настроек, вы можете заглянуть в сервис с www.cloudflare.com. Их текущая бета-функциональность, называемая rocket loader, делает именно это, включая встроенные скрипты.

Это бесплатный сервис. попробуй;)

Плюс вы получаете бесплатный кеширующий прокси сверху :)

0 голосов
/ 30 января 2012

Посмотрите на использование headjs . Это хорошая легкая библиотека, которая сделает все это за вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...