Estou usando vários plugins, widgets personalizados e algumas outras bibliotecas do JQuery. Como resultado, tenho vários arquivos .js e .css. Preciso criar um carregador para o meu site, pois leva algum tempo para carregar. será bom se eu puder exibir o carregador antes de importar todos os:
<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/myFunctions.js"></script>
<link type="text/css" href="css/main.css" rel="stylesheet" />
...
....
etc
Encontrei vários tutoriais que me permitem importar uma biblioteca JavaScript de forma assíncrona. por exemplo, eu posso fazer algo como:
(function () {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'js/jquery-ui-1.8.16.custom.min.js';
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
})();
por algum motivo, quando faço a mesma coisa em todos os meus arquivos, as páginas não funcionam. Eu venho tentando há tanto tempo tentar descobrir onde está o problema, mas simplesmente não consigo encontrá-lo. Primeiro, pensei que era provavelmente porque algumas funções javascript dependiam das outras. mas eu os carreguei na ordem correta, usando a função de tempo limite, quando uma foi concluída, continuei com a próxima e a página ainda se comporta de forma estranha. por exemplo, não consigo clicar nos links etc ... as animações ainda funcionam ..
Enfim
Aqui está o que eu tenho pensado ... Acredito que os navegadores tenham um cache, por isso leva muito tempo para carregar a página pela primeira vez e na próxima vez que é rápido. então o que estou pensando em fazer é substituir minha página index.html por uma página que carregue todos esses arquivos de forma assíncrona. quando o ajax terminar de carregar todos os arquivos redirecionados para a página que pretendo usar. ao usar essa página, não deve demorar muito para carregar, pois os arquivos já devem ser incluídos no cache do navegador. na minha página de índice (página em que os arquivos .js e .css são carregados de forma assíncrona), não me importo de obter erros. Vou apenas exibir um carregador e redirecionar a página quando terminar ...
Essa ideia é uma boa alternativa? ou devo continuar tentando implementar os métodos assíncronos?
EDITAR
do jeito que eu carrego tudo assíncrono é como:
importScripts();
function importScripts()
{
//import: jquery-ui-1.8.16.custom.min.js
getContent("js/jquery-1.6.2.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
//s.async = true;
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext1,1);
});
//import: jquery-ui-1.8.16.custom.min.js
function insertNext1()
{
getContent("js/jquery-ui-1.8.16.custom.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext2,1);
});
}
//import: jquery-ui-1.8.16.custom.css
function insertNext2()
{
getContent("css/custom-theme/jquery-ui-1.8.16.custom.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext3,1);
});
}
//import: main.css
function insertNext3()
{
getContent("css/main.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext4,1);
});
}
//import: jquery.imgpreload.min.js
function insertNext4()
{
getContent("js/farinspace/jquery.imgpreload.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext5,1);
});
}
//import: marquee.js
function insertNext5()
{
getContent("js/marquee.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext6,1);
});
}
//import: marquee.css
function insertNext6()
{
getContent("css/marquee.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext,1);
});
}
function insertNext()
{
setTimeout(pageReadyMan,10);
}
}
// get the content of url and pass that content to specified function
function getContent( url, callBackFunction )
{
// attempt to create the XMLHttpRequest and make the request
try
{
var asyncRequest; // variable to hold XMLHttpRequest object
asyncRequest = new XMLHttpRequest(); // create request object
// register event handler
asyncRequest.onreadystatechange = function(){
stateChange(asyncRequest, callBackFunction);
}
asyncRequest.open( 'GET', url, true ); // prepare the request
asyncRequest.send( null ); // send the request
} // end try
catch ( exception )
{
alert( 'Request failed.' );
} // end catch
} // end function getContent
// call function whith content when ready
function stateChange(asyncRequest, callBackFunction)
{
if ( asyncRequest.readyState == 4 && asyncRequest.status == 200 )
{
callBackFunction(asyncRequest.responseText);
} // end if
} // end function stateChange
e a parte estranha é que todo o trabalho do estilo, além de todas as funções javascript. a página está congelada por algum motivo ...
fonte
document.head.appendChild
, no entanto, existem alguns problemas de nicho ao adicionar scripts ao<head>
; nada que impeça o carregamento e a execução de scripts.document.write
antes do carregamento do documento, o script será executado de forma síncrona como parte do carregamento da página e não incluirá nenhum comportamento de retorno de chamada assíncrono. Se você estiver criando um elemento de script e adicionando-o à página, terá acesso para adicionar ouvintes de eventos a serem acionados de forma assíncrona. tl; dr: depende de como você está carregando o script com JS.O novo atributo 'assíncrono' do HTML5 deve fazer o truque. 'adiar' também é suportado na maioria dos navegadores, se você se importa com o IE.
async - O HTML
adiar - o HTML
Ao analisar o novo código do bloco de anúncios do adsense, observei o atributo e uma pesquisa me levou aqui: http://davidwalsh.name/html5-async
fonte
async
oudefer
ele bloqueará a renderização enquanto carrega. A configuraçãoasync
diz para ele não bloquear e executar o script o mais rápido possível. A configuraçãodefer
diz para ele não bloquear, mas aguarde a execução do script até que a página esteja pronta. Normalmente, não há problema em executar scripts o mais rápido possível, desde que eles não tenham nenhuma dependência (por exemplo, jQuery). Se um script tiver dependências em outro, useonLoad
para aguardar.Carreguei os scripts de forma assíncrona (o html 5 possui esse recurso) quando todos os scripts foram carregados, redirecionei a página para index2.html, onde index2.html usa as mesmas bibliotecas. Como os navegadores têm um cache depois que a página é redirecionada para index2.html, o index2.html é carregado em menos de um segundo, porque ele tem tudo o que precisa para carregar a página. Na minha página index.html, também carrego as imagens que pretendo usar para que o navegador as coloque no cache. então meu index.html se parece com:
Outra coisa interessante é que posso colocar um carregador na página e, quando a página terminar de carregar, o carregador desaparecerá e, em um fosco de milissegundos, a nova página estará em execução.
fonte
Exemplo do google
fonte
Várias notas:
s.async = true
não é muito correto para o doctype HTML5, o correto és.async = 'async'
(na verdade, usartrue
está correto , graças a amn que apontou no comentário logo abaixo)Como existe um motivo recente para carregar arquivos de forma assíncrona, mas em ordem, eu recomendaria uma maneira um pouco mais funcional sobre o seu exemplo (remova
console.log
para uso em produção :)):fonte
s.async = true
está correto . A propriedadeasync
é especificada explicitamente como um booleano na recomendação HTML 5 do W3C em w3.org/TR/html5/scripting-1.html#attr-script-async . Você está confundindo oasync
atributo com aasync
propriedade exposta por objetos que implementam aHTMLScriptElement
interface DOM. De fato, ao manipular o atributo correspondente do elemento por meio de algo comoElement.setAttribute
, você deve usar,element.setAttribute("async", "async")
pois todos os atributos HTML são, antes de tudo, texto.Graças ao HTML5, agora você pode declarar os scripts que deseja carregar de forma assíncrona, adicionando "async" na tag:
Nota: O atributo async é apenas para scripts externos (e deve ser usado apenas se o atributo src estiver presente).
Nota: Existem várias maneiras de executar um script externo:
Veja isto: http://www.w3schools.com/tags/att_script_async.asp
fonte
Gostaria de concluir a resposta do zzzzBov com uma verificação da presença de retorno de chamada e permitir a passagem de argumentos:
fonte
Aqui está uma ótima solução contemporânea para o carregamento de script assíncrono, embora ele endereça apenas o script js com async false .
Há um ótimo artigo escrito em www.html5rocks.com - Mergulhe nas águas turvas do carregamento de scripts .
Depois de considerar muitas soluções possíveis, o autor concluiu que a adição de scripts js ao elemento final do corpo é a melhor maneira possível de evitar o bloqueio da renderização da página pelos scripts js.
Nesse meio tempo, o autor adicionou outra boa solução alternativa para aquelas pessoas que estão desesperadas para carregar e executar scripts de forma assíncrona.
Considerando que você tem quatro scripts nomeados
script1.js, script2.js, script3.js, script4.js
, pode fazê-lo com a aplicação de async = false :Agora, Spec diz : Faça o download em conjunto, execute em ordem assim que o download for feito.
Firefox <3.6, o Opera diz: Não tenho idéia do que é essa coisa de "assíncrono", mas acontece que executo scripts adicionados via JS na ordem em que são adicionados.
O Safari 5.0 diz: Eu entendo "assíncrono", mas não entendo configurá-lo como "falso" com JS. Vou executar seus scripts assim que eles chegarem, em qualquer ordem.
O IE <10 diz: Nenhuma idéia sobre "assíncrono", mas existe uma solução alternativa usando "onreadystatechange".
Tudo o resto diz: Eu sou seu amigo, vamos fazer isso de acordo com o livro.
Agora, o código completo com o IE <10 solução alternativa:
fonte
Uma razão pela qual seus scripts podem ser carregados tão lentamente é se você estivesse executando todos os seus scripts enquanto carregava a página, assim:
ao invés de:
Esse segundo bit de script aguarda até que o navegador carregue completamente todo o seu código Javascript antes de começar a executar qualquer um dos seus scripts, fazendo parecer ao usuário que a página foi carregada mais rapidamente.
Se você deseja melhorar a experiência do usuário diminuindo o tempo de carregamento, eu não usaria a opção "tela de carregamento". Na minha opinião, isso seria muito mais irritante do que apenas carregar a página mais lentamente.
fonte
Eu sugiro que você dê uma olhada no Modernizr . É uma pequena biblioteca leve que você pode carregar assincronamente seu javascript com recursos que permitem verificar se o arquivo está carregado e executar o script na outra que você especificar.
Aqui está um exemplo de carregamento do jquery:
fonte
Eu escrevi um pequeno post para ajudar com isso, você pode ler mais aqui https://timber.io/snippets/asynchronously-load-a-script-in-the-browser-with-javascript/ , mas eu anexei a classe auxiliar abaixo. Ele aguardará automaticamente o carregamento de um script e retornará um atributo de janela especificado.
O uso é assim:
fonte
Você pode achar este artigo wiki interessante: http://ajaxpatterns.org/On-Demand_Javascript
Explica como e quando usar essa técnica.
fonte
Bem,
x.parentNode
retorna o elemento HEAD, para que você esteja inserindo o script antes da tag head. Talvez esse seja o problema.Tente em
x.parentNode.appendChild()
vez disso.fonte
Confira este https://github.com/stephen-lazarionok/async-resource-loader . Ele tem um exemplo que mostra como carregar JS, CSS e vários arquivos com uma única captura.
fonte
Você pode usar LABJS ou RequreJS
Os carregadores de scripts
LABJS
, como ,RequireJS
melhorarão a velocidade e a qualidade do seu código.fonte
Você já pensou em usar a injeção de busca? Criei uma biblioteca de código-fonte aberto chamada fetch-inject para lidar com casos como esses. Aqui está a aparência do seu carregador usando a lib:
Para compatibilidade com versões anteriores, aproveite a detecção de recursos e faça o retorno aos Elementos DOM de Injeção XHR ou Script, ou simplesmente coloque as tags na página usando
document.write
.fonte
Aqui está minha solução personalizada para eliminar o JavaScript de bloqueio de renderização:
Em resumo, ele carrega todos os seus scripts de forma assíncrona e os executa consequentemente.
Repo do Github : https://github.com/mudroljub/js-async-loader
fonte
No 'Access-Control-Allow-Origin' header is present on the requested resource
Aqui está uma pequena função do ES6 se alguém quiser usá-lo no React, por exemplo
fonte
Eu sugeriria procurar primeiro reduzir os arquivos e ver se isso oferece um aumento de velocidade grande o suficiente. Se o seu host estiver lento, tente colocar esse conteúdo estático em uma CDN.
fonte