Carregar dinamicamente um arquivo JavaScript
-
09-06-2019 - |
Pergunta
Como você pode carregar um arquivo JavaScript de maneira confiável e dinâmica?Isso pode ser usado para implementar um módulo ou componente que, quando 'inicializado', o componente carregará dinamicamente todos os scripts da biblioteca JavaScript necessários sob demanda.
O cliente que usa o componente não é obrigado a carregar todos os arquivos de script da biblioteca (e inserir manualmente <script>
tags em sua página web) que implementam este componente - apenas o arquivo de script do componente 'principal'.
Como as principais bibliotecas JavaScript conseguem isso (Protótipo, jQuery, etc.)? Essas ferramentas mesclam vários arquivos JavaScript em uma única versão redistribuível de 'construção' de um arquivo de script?Ou eles fazem algum carregamento dinâmico de scripts auxiliares de 'biblioteca'?
Uma adição a esta pergunta: existe uma maneira de lidar com o evento após o carregamento de um arquivo JavaScript incluído dinamicamente? O protótipo tem document.observe
para eventos em todo o documento.Exemplo:
document.observe("dom:loaded", function() {
// initially hide all containers for tab content
$$('div.tabcontent').invoke('hide');
});
Quais são os eventos disponíveis para um elemento de script?
Solução
Você pode escrever tags de script dinâmicas (usando Protótipo):
new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});
O problema aqui é que não sabemos quando o arquivo de script externo está totalmente carregado.
Muitas vezes queremos nosso código dependente na próxima linha e gostamos de escrever algo como:
if (iNeedSomeMore) {
Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
myFancyMethod(); // cool, no need for callbacks!
}
Existe uma maneira inteligente de injetar dependências de script sem a necessidade de retornos de chamada.Você simplesmente precisa extrair o script por meio de um solicitação AJAX síncrona e avaliar o roteiro em nível global.
Se você usar Prototype, o método Script.load ficará assim:
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);
}
};
Outras dicas
Não há importação/inclusão/exigência em javascript, mas existem duas maneiras principais de conseguir o que você deseja:
1 - Você pode carregá-lo com uma chamada AJAX e depois usar eval.
Esta é a maneira mais direta, mas é limitada ao seu domínio por causa das configurações de segurança do Javascript, e usar eval está abrindo a porta para bugs e hacks.
2 - Adicione uma tag de script com a URL do script no HTML.
Definitivamente o melhor caminho a percorrer.Você pode carregar o script até mesmo de um servidor externo, e ele fica limpo quando você usa o analisador do navegador para avaliar o código.Você pode colocar a tag no cabeçalho da página da web ou na parte inferior do corpo.
Ambas as soluções são discutidas e ilustradas aqui.
Agora, há um grande problema que você deve conhecer.Fazer isso implica que você carregue o código remotamente.Os navegadores modernos carregarão o arquivo e continuarão executando o script atual porque carregam tudo de forma assíncrona para melhorar o desempenho.
Isso significa que se você usar esses truques diretamente, não poderá usar o código recém-carregado na próxima linha após solicitar que ele seja carregado, porque ele ainda estará carregando.
POR EXEMPLO :my_lovely_script.js contém 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
Então você recarrega a página pressionando F5.E funciona!Confuso...
Então o que fazer sobre isso ?
Bem, você pode usar o hack que o autor sugere no link que lhe dei.Em resumo, para pessoas com pressa, ele usa en event para executar uma função de retorno de chamada quando o script é carregado.Assim você pode colocar todo o código usando a biblioteca remota na função de retorno de chamada.POR EXEMPLO :
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);
}
Então você escreve o código que deseja usar APÓS o script ser carregado em uma função lambda:
var myPrettyCode = function() {
// here, do what ever you want
};
Então você executa tudo isso:
loadScript("my_lovely_script.js", myPrettyCode);
OK, entendi.Mas é uma pena escrever tudo isso.
Bem, nesse caso, você pode usar como sempre o fantástico framework jQuery gratuito, que permite fazer exatamente a mesma coisa em uma linha:
$.getScript("my_lovely_script.js", function() {
alert("Script loaded and executed.");
// here you can use anything you defined in the loaded script
});
Eu usei um versão muito menos complicada recentemente com 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>
Funcionou muito bem em todos os navegadores em que testei:IE6/7, Firefox, Safari, Ópera.
Atualizar: Versão sem 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>
Fiz basicamente a mesma coisa que você fez com Adam, mas com uma pequena modificação para ter certeza de que estava anexando à tag head para realizar o trabalho.Simplesmente criei uma função include (código abaixo) para lidar com arquivos script e css.
Esta função também verifica se o script ou arquivo CSS ainda não foi carregado dinamicamente.Ele não verifica valores codificados manualmente e pode ter havido uma maneira melhor de fazer isso, mas serviu ao propósito.
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 );
}
outra resposta incrível
$.getScript("my_lovely_script.js", function(){
alert("Script loaded and executed.");
// here you can use anything you defined in the loaded script
});
Aqui está um exemplo de código que encontrei ...alguém tem uma maneira melhor?
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);
}
Se você já carregou o jQuery, você deve usar $.getScript.
Isso tem uma vantagem sobre as outras respostas aqui, pois você tem uma função de retorno de chamada integrada (para garantir que o script seja carregado antes da execução do código dependente) e pode controlar o cache.
alguém tem uma maneira melhor?
Acho que apenas adicionar o script ao corpo seria mais fácil do que adicioná-lo ao último nó da página.Que tal agora:
function include(url) {
var s = document.createElement("script");
s.setAttribute("type", "text/javascript");
s.setAttribute("src", url);
document.body.appendChild(s);
}
usei mais uma solução que encontrei na net...este está sob Creativecommons e verifica se a fonte foi incluída antes de chamar a função ...
você pode encontrar o arquivo aqui: incluir.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);
}
}
}
Acabei de descobrir um ótimo recurso em YUI 3 (no momento em que este artigo foi escrito, disponível na versão prévia).Você pode inserir facilmente dependências em bibliotecas YUI e em módulos "externos" (o que você está procurando) sem muito código: Carregador YUI.
Também responde à sua segunda pergunta sobre a função que está sendo chamada assim que o módulo externo é carregado.
Exemplo:
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(...);
}
});
Funcionou perfeitamente para mim e tem a vantagem de gerenciar dependências.Consulte a documentação do YUI para obter um exemplo com calendário YUI 2.
Se você quiser um SINCRONIZAR carregamento do script, você precisa adicionar o texto do script diretamente à tag HTML HEAD.Adicioná-lo como irá acionar um Assíncrono carregar.Para carregar o texto do script do arquivo externo de forma síncrona, use XHR.Abaixo um exemplo rápido (está usando partes de outras respostas neste e em outros posts):
/*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()); });
A técnica que usamos no trabalho é solicitar o arquivo javascript usando uma solicitação AJAX e depois eval() o retorno.Se você estiver usando a biblioteca de protótipos, eles suportam essa funcionalidade na chamada Ajax.Request.
jquery resolveu isso para mim com sua função .append()- usei isso para carregar o pacote jquery ui completo
/*
* 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>');
}
Usar - no cabeçalho do seu html/php/etc, depois de importar o jquery.js, você apenas incluiria este arquivo para carregar toda a sua biblioteca, anexando-o ao cabeçalho ...
<script type="text/javascript" src="project.library.js"></script>
Mantenha-o agradável, curto, simples e sustentável!:]
// 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]);
}
}
Este código é simplesmente um pequeno exemplo funcional que poderia requerem funcionalidade de recursos adicionais para suporte total em qualquer plataforma (ou determinada).
Há um novo padrão ECMA proposto chamado importação dinâmica, recentemente incorporado ao Chrome e Safari.
const moduleSpecifier = './dir/someModule.js';
import(moduleSpecifier)
.then(someModule => someModule.foo()); // executes foo method in someModule
Existem scripts projetados especificamente para essa finalidade.
simnope.js está integrado ao Modernizr e laboratório.js é uma versão mais otimizada (mas menos amigável).
Eu não recomendaria fazer isso por meio de uma grande biblioteca como jquery ou protótipo - porque um dos principais benefícios de um carregador de script é a capacidade de carregar scripts antecipadamente - você não deveria ter que esperar até que o jquery e todos os seus elementos dom sejam carregados antes executando uma verificação para ver se deseja carregar um script dinamicamente.
Eu escrevi um módulo simples que automatiza o trabalho de importação/inclusão de scripts de módulo em JavaScript.Experimente e, por favor, poupe alguns comentários!:) Para obter uma explicação detalhada do código, consulte esta postagem do blog: 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
});
Estou perdido em todos esses exemplos, mas hoje precisei carregar um .js externo do meu .js principal e fiz isso:
document.write("<script src='https://www.google.com/recaptcha/api.js'></script>");
Aqui é simples, com retorno de chamada e suporte ao 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');
});
Aqui está um exemplo simples de uma função para carregar arquivos JS.Pontos relevantes:
- você não precisa do jQuery, então você pode usá-lo inicialmente para carregar também o arquivo jQuery.js
- é assíncrono com retorno de chamada
- garante o carregamento apenas uma vez, pois mantém um gabinete com o registro das urls carregadas, evitando assim o uso da rede
- contrário ao jQuery
$.ajax
ou$.getScript
você pode usar nonces, resolvendo assim problemas com CSPunsafe-inline
.Basta usar a propriedadescript.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);
}
};
}();
Agora você usa simplesmente
getScriptOnce("url_of_your_JS_file.js");
Uma frase absurda, para quem pensa que carregar uma biblioteca js não deve demorar mais que uma linha de código :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)});
Obviamente se o script que você deseja importar for um módulo, você pode usar o import(...)
função.
todas as principais bibliotecas javascript, como jscript, protótipo, YUI, têm suporte para carregar arquivos de script.Por exemplo, no YUI, após carregar o núcleo você pode fazer o seguinte para carregar o controle de calendário
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();
Eu sei que minha resposta está um pouco atrasada para esta pergunta, mas aqui está um ótimo artigo em www.html5rocks.com - Mergulhe profundamente nas águas turvas do carregamento de scripts .
Nesse artigo conclui-se que em relação ao suporte do navegador, a melhor forma de carregar dinamicamente o arquivo JavaScript sem bloquear a renderização do conteúdo é a seguinte:
Considerando que você tem quatro scripts chamados script1.js, script2.js, script3.js, script4.js
então você pode fazer isso com aplicando assíncrono = falso:
[
'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);
});
Agora, A especificação diz:Baixe juntos, execute em ordem assim que todos baixarem.
Firefox <3.6, Opera diz: Não tenho ideia do que é essa coisa “assíncrona”, mas acontece que executo scripts adicionados via JS na ordem em que são adicionados.
Safari 5.0 diz: Entendo “assíncrono”, mas não entendo defini-lo como “falso” com JS.Executarei seus scripts assim que eles chegarem, em qualquer ordem.
IE < 10 diz: Não tenho ideia sobre “async”, mas há uma solução alternativa usando “onreadystatechange”.
Todo o resto diz: Eu sou seu amigo, vamos fazer isso de acordo com as regras.
Agora, o código completo com solução alternativa para 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>');
}
}
Alguns truques e minificação depois, são 362 bytes
!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"
])
Algo assim...
<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>