Вопрос

Как можно надежно и динамически загружать файл JavaScript?Это можно использовать для реализации модуля или компонента, который при «инициализации» компонента будет динамически загружать все необходимые сценарии библиотеки JavaScript по требованию.

Клиенту, использующему этот компонент, не требуется загружать все файлы сценариев библиотеки (и вручную вставлять их). <script> теги на свою веб-страницу), которые реализуют этот компонент — просто файл сценария «основного» компонента.

Как это делают основные библиотеки JavaScript (Prototype, jQuery и т. д.)? Объединяют ли эти инструменты несколько файлов JavaScript в одну распространяемую версию файла сценария «сборки»?Или они выполняют динамическую загрузку вспомогательных «библиотечных» сценариев?

Дополнение к этому вопросу: Есть ли способ обработать это событие после загрузки динамически включенного файла JavaScript? Прототип имеет document.observe для событий всего документа.Пример:

document.observe("dom:loaded", function() {
  // initially hide all containers for tab content
  $$('div.tabcontent').invoke('hide');
});

Какие события доступны для элемента сценария?

Это было полезно?

Решение

Вы можете писать динамические теги скриптов (используя Опытный образец):

new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});

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

Мы часто хотим, чтобы наш зависимый код находился на следующей строке, и нам нравится писать что-то вроде:

if (iNeedSomeMore) {
    Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
    myFancyMethod(); // cool, no need for callbacks!
}

Существует разумный способ внедрения зависимостей сценария без необходимости использования обратных вызовов.Вам просто нужно вытащить скрипт через синхронный запрос AJAX и оцените сценарий на глобальном уровне.

Если вы используете Prototype, метод Script.load выглядит следующим образом:

var Script = {
    _loadedScripts: [],
    include: function(script) {
        // include script only once
        if (this._loadedScripts.include(script)) {
            return false;
        }
        // request file synchronous
        var code = new Ajax.Request(script, {
            asynchronous: false,
            method: "GET",
            evalJS: false,
            evalJSON: false
        }).transport.responseText;
        // eval code on global level
        if (Prototype.Browser.IE) {
            window.execScript(code);
        } else if (Prototype.Browser.WebKit) {
            $$("head").first().insert(Object.extend(
                new Element("script", {
                    type: "text/javascript"
                }), {
                    text: code
                }
            ));
        } else {
            window.eval(code);
        }
        // remember included script
        this._loadedScripts.push(script);
    }
};

Другие советы

В javascript нет импорта/включения/требования, но есть два основных способа добиться желаемого:

1. Вы можете загрузить его с помощью вызова AJAX, а затем использовать eval.

Это самый простой способ, но он ограничен вашим доменом из-за настроек безопасности Javascript, а использование eval открывает двери для ошибок и хаков.

2. Добавьте тег сценария с URL-адресом сценария в HTML.

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

Оба эти решения обсуждаются и иллюстрируются здесь.

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

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

Э.Г:my_lovely_script.js содержит MySuperObject

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

Затем вы перезагружаете страницу, нажимая F5.И это работает!Сбивает с толку...

Так что же с этим делать?

Что ж, вы можете использовать хак, который предлагает автор по ссылке, которую я вам дал.Таким образом, для тех, кто спешит, он использует событие en event для запуска функции обратного вызова при загрузке сценария.Таким образом, вы можете поместить весь код, используя удаленную библиотеку, в функцию обратного вызова.Э.Г:

function loadScript(url, callback)
{
    // adding the script tag to the head as suggested before
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.src = url;

   // then bind the event to the callback function 
   // there are several events for cross browser compatibility
   script.onreadystatechange = callback;
   script.onload = callback;

   // fire the loading
   head.appendChild(script);
}

Затем вы пишете код, который хотите использовать ПОСЛЕ загрузки скрипта в лямбда-функцию:

var myPrettyCode = function() {
    // here, do what ever you want
};

Затем вы запускаете все это:

loadScript("my_lovely_script.js", myPrettyCode);

Ладно, я понял.Но писать все это больно.

Что ж, в этом случае вы можете использовать, как всегда, фантастическую бесплатную среду jQuery, которая позволяет вам сделать то же самое в одной строке:

$.getScript("my_lovely_script.js", function() {
    alert("Script loaded and executed.");
    // here you can use anything you defined in the loaded script
});

Я использовал гораздо менее сложная версия в последнее время с jQuery:

<script src="scripts/jquery.js"></script>
<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  var $head = $("head");
  for (var i = 0; i < js.length; i++) {
    $head.append("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

Он отлично работал во всех браузерах, в которых я его тестировал:IE6/7, Firefox, Сафари, Опера.

Обновлять: Версия без jQuery:

<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  for (var i = 0, l = js.length; i < l; i++) {
    document.getElementsByTagName("head")[0].innerHTML += ("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

Я сделал в основном то же самое, что вы сделали с Адамом, но с небольшими изменениями, чтобы убедиться, что я добавляю тег head для выполнения работы.Я просто создал функцию включения (код ниже) для обработки файлов сценариев и CSS.

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

function include( url, type ){
    // First make sure it hasn't been loaded by something else.
    if( Array.contains( includedFile, url ) )
        return;

    // Determine the MIME-type
    var jsExpr = new RegExp( "js$", "i" );
    var cssExpr = new RegExp( "css$", "i" );
    if( type == null )
        if( jsExpr.test( url ) )
            type = 'text/javascript';
        else if( cssExpr.test( url ) )
            type = 'text/css';

    // Create the appropriate element.
    var tag = null;
    switch( type ){
        case 'text/javascript' :
            tag = document.createElement( 'script' );
            tag.type = type;
            tag.src = url;
            break;
        case 'text/css' :
            tag = document.createElement( 'link' );
            tag.rel = 'stylesheet';
            tag.type = type;
            tag.href = url;
            break;
    }

    // Insert it to the <head> and the array to ensure it is not
    // loaded again.
    document.getElementsByTagName("head")[0].appendChild( tag );
    Array.add( includedFile, url );
}

еще один потрясающий ответ

$.getScript("my_lovely_script.js", function(){


   alert("Script loaded and executed.");
  // here you can use anything you defined in the loaded script

 });

https://stackoverflow.com/a/950146/671046

Вот пример кода, который я нашел...есть ли у кого-нибудь лучший способ?

  function include(url)
  {
    var s = document.createElement("script");
    s.setAttribute("type", "text/javascript");
    s.setAttribute("src", url);
    var nodes = document.getElementsByTagName("*");
    var node = nodes[nodes.length -1].parentNode;
    node.appendChild(s);
  }

Если у вас уже загружен jQuery, вам следует использовать $.getScript.

Это имеет преимущество перед другими ответами здесь в том, что у вас есть встроенная функция обратного вызова (чтобы гарантировать загрузку сценария до запуска зависимого кода), и вы можете управлять кешированием.

есть ли у кого-нибудь лучший способ?

Я думаю, что проще добавить скрипт в тело, чем добавлять его в последний узел на странице.Как насчет этого:

function include(url) {
  var s = document.createElement("script");
  s.setAttribute("type", "text/javascript");
  s.setAttribute("src", url);
  document.body.appendChild(s);
}

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

вы можете найти файл здесь: включить.js

/** include - including .js files from JS - bfults@gmail.com - 2005-02-09
 ** Code licensed under Creative Commons Attribution-ShareAlike License 
 ** http://creativecommons.org/licenses/by-sa/2.0/
 **/              
var hIncludes = null;
function include(sURI)
{   
  if (document.getElementsByTagName)
  {   
    if (!hIncludes)
    {
      hIncludes = {}; 
      var cScripts = document.getElementsByTagName("script");
      for (var i=0,len=cScripts.length; i < len; i++)
        if (cScripts[i].src) hIncludes[cScripts[i].src] = true;
    }
    if (!hIncludes[sURI])
    {
      var oNew = document.createElement("script");
      oNew.type = "text/javascript";
      oNew.src = sURI;
      hIncludes[sURI]=true;
      document.getElementsByTagName("head")[0].appendChild(oNew);
    }
  }   
} 

Только что узнал об замечательной функции в ЮИ 3 (на момент написания доступна в предварительной версии).Вы можете легко вставлять зависимости в библиотеки YUI и во «внешние» модули (то, что вы ищете) без лишнего кода: ЮИ-загрузчик.

Это также отвечает на ваш второй вопрос относительно функции, вызываемой сразу после загрузки внешнего модуля.

Пример:

YUI({
    modules: {
        'simple': {
            fullpath: "http://example.com/public/js/simple.js"
        },
        'complicated': {
            fullpath: "http://example.com/public/js/complicated.js"
            requires: ['simple']  // <-- dependency to 'simple' module
        }
    },
    timeout: 10000
}).use('complicated', function(Y, result) {
    // called as soon as 'complicated' is loaded
    if (!result.success) {
        // loading failed, or timeout
        handleError(result.msg);
    } else {
        // call a function that needs 'complicated'
        doSomethingComplicated(...);
    }
});

У меня отлично сработало и есть преимущество в управлении зависимостями.Обратитесь к документации YUI для пример с календарем YUI 2.

Если вы хотите СИНХРОНИЗАЦИЯ при загрузке сценария вам необходимо добавить текст сценария непосредственно в тег HTML HEAD.Добавление его as вызовет Асинхронный режим нагрузка.Чтобы синхронно загрузить текст сценария из внешнего файла, используйте XHR.Ниже приведен краткий образец (он использует части других ответов в этом и других сообщениях):

/*sample requires an additional method for array prototype:*/

if (Array.prototype.contains === undefined) {
Array.prototype.contains = function (obj) {
    var i = this.length;
    while (i--) { if (this[i] === obj) return true; }
    return false;
};
};

/*define object that will wrap our logic*/
var ScriptLoader = {
LoadedFiles: [],

LoadFile: function (url) {
    var self = this;
    if (this.LoadedFiles.contains(url)) return;

    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                self.LoadedFiles.push(url);
                self.AddScript(xhr.responseText);
            } else {
                if (console) console.error(xhr.statusText);
            }
        }
    };
    xhr.open("GET", url, false);/*last parameter defines if call is async or not*/
    xhr.send(null);
},

AddScript: function (code) {
    var oNew = document.createElement("script");
    oNew.type = "text/javascript";
    oNew.textContent = code;
    document.getElementsByTagName("head")[0].appendChild(oNew);
}
};

/*Load script file. ScriptLoader will check if you try to load a file that has already been loaded (this check might be better, but I'm lazy).*/

ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
/*this will be executed right after upper lines. It requires jquery to execute. It requires a HTML input with id "tb1"*/
$(function () { alert($('#tb1').val()); });

Техника, которую мы используем на работе, заключается в запросе файла javascript с помощью запроса AJAX, а затем eval() возврата.Если вы используете библиотеку прототипов, они поддерживают эту функцию в своем вызове Ajax.Request.

jquery разрешил это для меня с помощью функции .append()— использовал это для загрузки полного пакета jquery ui

/*
 * FILENAME : project.library.js
 * USAGE    : loads any javascript library
 */
    var dirPath = "../js/";
    var library = ["functions.js","swfobject.js","jquery.jeditable.mini.js","jquery-ui-1.8.8.custom.min.js","ui/jquery.ui.core.min.js","ui/jquery.ui.widget.min.js","ui/jquery.ui.position.min.js","ui/jquery.ui.button.min.js","ui/jquery.ui.mouse.min.js","ui/jquery.ui.dialog.min.js","ui/jquery.effects.core.min.js","ui/jquery.effects.blind.min.js","ui/jquery.effects.fade.min.js","ui/jquery.effects.slide.min.js","ui/jquery.effects.transfer.min.js"];

    for(var script in library){
        $('head').append('<script type="text/javascript" src="' + dirPath + library[script] + '"></script>');
    }

Использовать - в заголовке вашего html/php/etc после импорта jquery.js вы просто включите этот один файл, чтобы загрузить всю вашу библиотеку, добавив его в заголовок...

<script type="text/javascript" src="project.library.js"></script>

Пусть он будет красивым, коротким, простым и удобным в сопровождении!:]

// 3rd party plugins / script (don't forget the full path is necessary)
var FULL_PATH = '', s =
[
    FULL_PATH + 'plugins/script.js'      // Script example
    FULL_PATH + 'plugins/jquery.1.2.js', // jQuery Library 
    FULL_PATH + 'plugins/crypto-js/hmac-sha1.js',      // CryptoJS
    FULL_PATH + 'plugins/crypto-js/enc-base64-min.js'  // CryptoJS
];

function load(url)
{
    var ajax = new XMLHttpRequest();
    ajax.open('GET', url, false);
    ajax.onreadystatechange = function ()
    {
        var script = ajax.response || ajax.responseText;
        if (ajax.readyState === 4)
        {
            switch(ajax.status)
            {
                case 200:
                    eval.apply( window, [script] );
                    console.log("library loaded: ", url);
                    break;
                default:
                    console.log("ERROR: library not loaded: ", url);
            }
        }
    };
    ajax.send(null);
}

 // initialize a single load 
load('plugins/script.js');

// initialize a full load of scripts
if (s.length > 0)
{
    for (i = 0; i < s.length; i++)
    {
        load(s[i]);
    }
}

Этот код представляет собой просто короткий функциональный пример, который мог требуются дополнительные функциональные возможности для полной поддержки на любой (или данной) платформе.

Предлагается новый стандарт ECMA под названием динамический импорт, недавно включенный в Chrome и Safari.

const moduleSpecifier = './dir/someModule.js';

import(moduleSpecifier)
   .then(someModule => someModule.foo()); // executes foo method in someModule

Есть скрипты, которые созданы специально для этой цели.

yepnope.js встроен в Modernizr, и lab.js — более оптимизированная (но менее удобная для пользователя версия).

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

Я написал простой модуль, который автоматизирует работу по импорту/включению скриптов модулей в JavaScript.Попробуйте и, пожалуйста, оставьте отзыв!:) Подробное объяснение кода можно найти в этом сообщении в блоге: http://stamat.wordpress.com/2013/04/12/javascript-require-import-include-modules/

var _rmod = _rmod || {}; //require module namespace
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
    scripts: {},
    length: 0
};

_rmod.findScriptPath = function(script_name) {
    var script_elems = document.getElementsByTagName('script');
    for (var i = 0; i < script_elems.length; i++) {
        if (script_elems[i].src.endsWith(script_name)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
            return url.substring(href.length+1, url.length);
        }
    }
    return '';
};

_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark the root directory of your library, any library


_rmod.injectScript = function(script_name, uri, callback, prepare) {

    if(!prepare)
        prepare(script_name, uri);

    var script_elem = document.createElement('script');
    script_elem.type = 'text/javascript';
    script_elem.title = script_name;
    script_elem.src = uri;
    script_elem.async = true;
    script_elem.defer = false;

    if(!callback)
        script_elem.onload = function() {
            callback(script_name, uri);
        };

    document.getElementsByTagName('head')[0].appendChild(script_elem);
};

_rmod.requirePrepare = function(script_name, uri) {
    _rmod.loading.scripts[script_name] = uri;
    _rmod.loading.length++;
};

_rmod.requireCallback = function(script_name, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[script_name];
    _rmod.imported[script_name] = uri;

    if(_rmod.loading.length == 0)
        _rmod.onReady();
};

_rmod.onReady = function() {
    if (!_rmod.LOADED) {
        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
            _rmod.on_ready_fn_stack[i]();
        });
        _rmod.LOADED = true;
    }
};

//you can rename based on your liking. I chose require, but it can be called include or anything else that is easy for you to remember or write, except import because it is reserved for future use.
var require = function(script_name) {
    var np = script_name.split('.');
    if (np[np.length-1] === '*') {
        np.pop();
        np.push('_all');
    }

    script_name = np.join('.');
    var uri = _rmod.libpath + np.join('/')+'.js';
    if (!_rmod.loading.scripts.hasOwnProperty(script_name) 
     && !_rmod.imported.hasOwnProperty(script_name)) {
        _rmod.injectScript(script_name, uri, 
            _rmod.requireCallback, 
                _rmod.requirePrepare);
    }
};

var ready = function(fn) {
    _rmod.on_ready_fn_stack.push(fn);
};

// ----- USAGE -----

require('ivar.util.array');
require('ivar.util.string');
require('ivar.net.*');

ready(function(){
    //do something when required scripts are loaded
});

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

document.write("<script src='https://www.google.com/recaptcha/api.js'></script>");

Здесь простой с обратным вызовом и поддержкой IE:

function loadScript(url, callback) {

    var script = document.createElement("script")
    script.type = "text/javascript";

    if (script.readyState) { //IE
        script.onreadystatechange = function () {
            if (script.readyState == "loaded" || script.readyState == "complete") {
                script.onreadystatechange = null;
                callback();
            }
        };
    } else { //Others
        script.onload = function () {
            callback();
        };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

loadScript("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {

     //jQuery loaded
     console.log('jquery loaded');

});

Вот простой пример функции для загрузки файлов JS.Соответствующие моменты:

  • вам не нужен jQuery, поэтому вы можете использовать его изначально для загрузки файла jQuery.js.
  • это асинхронно с обратным вызовом
  • он гарантирует загрузку только один раз, поскольку сохраняет вложение с записью загруженных URL-адресов, что позволяет избежать использования сети
  • в отличие от jQuery $.ajax или $.getScript вы можете использовать одноразовые номера, решая таким образом проблемы с CSP unsafe-inline.Просто используйте свойство script.nonce
var getScriptOnce = function() {

    var scriptArray = []; //array of urls (closure)

    //function to defer loading of script
    return function (url, callback){
        //the array doesn't have such url
        if (scriptArray.indexOf(url) === -1){

            var script=document.createElement('script');
            script.src=url;
            var head=document.getElementsByTagName('head')[0],
                done=false;

            script.onload=script.onreadystatechange = function(){
                if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
                    done=true;
                    if (typeof callback === 'function') {
                        callback();
                    }
                    script.onload = script.onreadystatechange = null;
                    head.removeChild(script);

                    scriptArray.push(url);
                }
            };

            head.appendChild(script);
        }
    };
}();

Теперь вы используете его просто

getScriptOnce("url_of_your_JS_file.js");

Абсурдная однострочная фраза для тех, кто думает, что загрузка библиотеки js не должна занимать более одной строки кода: P

await new Promise((resolve, reject) => {let js = document.createElement("script"); js.src="mylibrary.js"; js.onload=resolve; js.onerror=reject; document.body.appendChild(js)});

Очевидно, что если скрипт, который вы хотите импортировать, является модулем, вы можете использовать import(...) функция.

все основные библиотеки javascript, такие как jscript, прототип, YUI, поддерживают загрузку файлов сценариев.Например, в YUI после загрузки ядра вы можете сделать следующее, чтобы загрузить элемент управления календарем

var loader = new YAHOO.util.YUILoader({

    require: ['calendar'], // what components?

    base: '../../build/',//where do they live?

    //filter: "DEBUG",  //use debug versions (or apply some
                        //some other filter?

    //loadOptional: true, //load all optional dependencies?

    //onSuccess is the function that YUI Loader
    //should call when all components are successfully loaded.
    onSuccess: function() {
        //Once the YUI Calendar Control and dependencies are on
        //the page, we'll verify that our target container is 
        //available in the DOM and then instantiate a default
        //calendar into it:
        YAHOO.util.Event.onAvailable("calendar_container", function() {
            var myCal = new YAHOO.widget.Calendar("mycal_id", "calendar_container");
            myCal.render();
        })
     },

    // should a failure occur, the onFailure function will be executed
    onFailure: function(o) {
        alert("error: " + YAHOO.lang.dump(o));
    }

 });

// Calculate the dependency and insert the required scripts and css resources
// into the document
loader.insert();

Я знаю, что мой ответ на этот вопрос немного запоздал, но вот отличная статья в www.html5rocks.com - Глубокое погружение в мутные воды загрузки скриптов .

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

Учитывая, что у вас есть четыре сценария с именем script1.js, script2.js, script3.js, script4.js тогда ты сможешь сделать это с применение асинхронного = ложь:

[
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

Сейчас, Спец говорит:Скачиваем вместе, выполняем по порядку, как только все скачаются.

Firefox <3.6, Opera говорит: Я понятия не имею, что такое «асинхронность», но так уж получилось, что я выполняю скрипты, добавленные через JS, в том порядке, в котором они были добавлены.

Сафари 5.0 говорит: Я понимаю «асинхронность», но не понимаю, как установить для него значение «false» с помощью JS.Я выполню ваши сценарии, как только они прибудут, в любом порядке.

IE <10 говорит: Понятия не имею об «асинхронности», но есть обходной путь с использованием «onreadystatechange».

Все остальное говорит: Я твой друг, мы собираемся сделать это по правилам.

Теперь полный код с обходным решением IE <10:

var scripts = [
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];

// Watch scripts load in IE
function stateChange() {
  // Execute as many scripts in order as we can
  var pendingScript;
  while (pendingScripts[0] && pendingScripts[0].readyState == 'loaded') {
    pendingScript = pendingScripts.shift();
    // avoid future loading events from this script (eg, if src changes)
    pendingScript.onreadystatechange = null;
    // can't just appendChild, old IE bug if element isn't closed
    firstScript.parentNode.insertBefore(pendingScript, firstScript);
  }
}

// loop through our script urls
while (src = scripts.shift()) {
  if ('async' in firstScript) { // modern browsers
    script = document.createElement('script');
    script.async = false;
    script.src = src;
    document.head.appendChild(script);
  }
  else if (firstScript.readyState) { // IE<10
    // create a script and add it to our todo pile
    script = document.createElement('script');
    pendingScripts.push(script);
    // listen for state changes
    script.onreadystatechange = stateChange;
    // must set src AFTER adding onreadystatechange listener
    // else we’ll miss the loaded event for cached scripts
    script.src = src;
  }
  else { // fall back to defer
    document.write('<script src="' + src + '" defer></'+'script>');
  }
}

Несколько уловок и минификации спустя, это 362 байта.

!function(e,t,r){function n(){for(;d[0]&&"loaded"==d[0][f];)c=d.shift(),c[o]=!i.parentNode.insertBefore(c,i)}for(var s,a,c,d=[],i=e.scripts[0],o="onreadystatechange",f="readyState";s=r.shift();)a=e.createElement(t),"async"in i?(a.async=!1,e.head.appendChild(a)):i[f]?(d.push(a),a[o]=n):e.write("<"+t+' src="'+s+'" defer></'+t+">"),a.src=s}(document,"script",[
  "//other-domain.com/1.js",
  "2.js"
])

Что-то вроде этого...

<script>
     $(document).ready(function() {
          $('body').append('<script src="https://maps.googleapis.com/maps/api/js?key=KEY&libraries=places&callback=getCurrentPickupLocation" async defer><\/script>');
     });
</script>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top