Estoy usando varios complementos, widgets personalizados y algunas otras bibliotecas de JQuery. Como resultado, tengo varios archivos .js y .css. Necesito crear un cargador para mi sitio porque tarda un poco en cargar. Sería bueno si puedo mostrar el cargador antes de importar todo el:
<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
He encontrado varios tutoriales que me permiten importar una biblioteca de JavaScript de forma asincrónica. por ejemplo puedo hacer 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 alguna razón, cuando hago lo mismo para todos mis archivos, las páginas no funcionan. He intentado durante mucho tiempo tratar de encontrar dónde está el problema, pero simplemente no puedo encontrarlo. Primero pensé que probablemente era porque algunas funciones de JavaScript dependían de las demás. pero los cargué en el orden correcto usando la función de tiempo de espera cuando se completó, pasé al siguiente y la página todavía se comporta de manera extraña. por ejemplo, no puedo hacer clic en enlaces, etc ... aunque las animaciones todavía funcionan ...
De todos modos
Esto es lo que he estado pensando ... Creo que los navegadores tienen un caché, por eso lleva mucho tiempo cargar la página por primera vez y la próxima vez que sea rápida. así que lo que estoy pensando hacer es reemplazar mi página index.html con una página que carga todos estos archivos de forma asincrónica. cuando ajax termina de cargar todos esos archivos redirigen a la página que planeo usar. cuando use esa página, no debería demorar mucho en cargar, ya que los archivos ya deberían estar incluidos en la memoria caché del navegador. en mi página de índice (página donde se cargan los archivos .js y .css de forma asíncrona) No me importa recibir errores. Solo mostraré un cargador y redirigiré la página cuando termine ...
¿Es esta idea una buena alternativa? ¿O debería seguir intentando implementar los métodos asincrónicos?
EDITAR
la forma en que cargo todo asíncrono es 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
Y la parte extraña es que todo el trabajo del estilo más todas las funciones de JavaScript. Sin embargo, la página está congelada por alguna razón ...
fuente
document.head.appendChild
, sin embargo, hay algunos problemas de nicho al agregar scripts a<head>
; nada que impida que los scripts se carguen y ejecuten.document.write
antes de que se cargue el documento, la secuencia de comandos se ejecutará sincrónicamente como parte de la carga de la página y no incluirá ningún comportamiento de devolución de llamada asíncrono por sí solo. Si está creando un elemento de secuencia de comandos y lo agrega a la página, tendrá acceso para agregar oyentes de eventos para que se activen de forma asincrónica. tl; dr: depende de cómo esté cargando el script con JS.Se supone que el nuevo atributo 'asíncrono' de HTML5 funciona. 'aplazar' también es compatible con la mayoría de los navegadores si te interesa IE.
async - El HTML
diferir - El HTML
Al analizar el nuevo código de bloque de anuncios adsense, noté el atributo y una búsqueda me condujo aquí: http://davidwalsh.name/html5-async
fuente
async
odefer
bloqueará el renderizado mientras se carga. La configuraciónasync
le indicará que no bloquee y ejecute el script lo antes posible. La configuracióndefer
le indicará que no se bloquee, pero espere con la ejecución del script hasta que se complete la página. Por lo general, no es un problema ejecutar scripts lo antes posible siempre que no tengan dependencias (por ejemplo, jQuery). Si un script tiene dependencias de otro, utilíceloonLoad
para esperarlo.Cargué los scripts de forma asincrónica (html 5 tiene esa característica) cuando todos los scripts se cargaron, redirigí la página a index2.html donde index2.html usa las mismas bibliotecas. Debido a que los navegadores tienen una memoria caché una vez que la página redirige a index2.html, index2.html se carga en menos de un segundo porque tiene todo lo que necesita para cargar la página. En mi página index.html también cargo las imágenes que planeo usar para que el navegador coloque esas imágenes en el caché. entonces mi index.html se ve así:
Otra cosa buena de esto es que puedo colocar un cargador en la página y cuando la página termine de cargarse, el cargador desaparecerá y en cuestión de milisegundos la nueva página se ejecutará.
fuente
Ejemplo de google
fuente
Varias notas:
s.async = true
no es muy correcto para HTML5 doctype, correcto ess.async = 'async'
(en realidad el usotrue
es correcto , gracias a amn que lo señaló en el comentario a continuación)Dado que hay una razón reciente para cargar archivos de forma asincrónica, pero en orden, recomendaría un poco más de manera funcional sobre su ejemplo (eliminar
console.log
para uso de producción :)):fuente
s.async = true
es correcta . La propiedadasync
se especifica explícitamente como un booleano en la recomendación HTML 5 del W3C en w3.org/TR/html5/scripting-1.html#attr-script-async . Está confundiendo elasync
atributo con laasync
propiedad expuesta por los objetos que implementan laHTMLScriptElement
interfaz DOM. De hecho, al manipular el atributo correspondiente del elemento a través de algo asíElement.setAttribute
, debe usarloelement.setAttribute("async", "async")
ya que todos los atributos HTML son, ante todo, texto.Gracias a HTML5, ahora puede declarar los scripts que desea cargar de forma asincrónica agregando "async" en la etiqueta:
Nota: El atributo asíncrono es solo para scripts externos (y solo debe usarse si el atributo src está presente).
Nota: Hay varias formas de ejecutar un script externo:
Vea esto: http://www.w3schools.com/tags/att_script_async.asp
fuente
Completaría la respuesta de zzzzBov con una comprobación de la presencia de devolución de llamada y permitiría pasar argumentos:
fuente
Aquí hay una gran solución contemporánea para la carga de scripts asíncronos, aunque solo aborda el script js con async false .
Hay un gran artículo escrito en www.html5rocks.com : sumérgete en las aguas turbias de la carga de guiones .
Después de considerar muchas soluciones posibles, el autor concluyó que agregar scripts js al final del elemento body es la mejor manera posible de evitar el bloqueo de la representación de páginas por scripts js.
Mientras tanto, el autor agregó otra buena solución alternativa para aquellas personas que están desesperadas por cargar y ejecutar scripts de forma asincrónica.
Teniendo en cuenta que tiene cuatro scripts nombrados
script1.js, script2.js, script3.js, script4.js
, puede hacerlo aplicando async = false :Ahora, Spec dice : Descargar juntos, ejecutar en orden tan pronto como se descargue todo.
Firefox <3.6, Opera dice: No tengo idea de qué es esta cosa "asíncrona", pero sucede que ejecuto scripts agregados a través de JS en el orden en que se agregaron.
Safari 5.0 dice: Entiendo "async", pero no entiendo configurarlo en "false" con JS. Ejecutaré tus scripts tan pronto como lleguen, en cualquier orden.
IE <10 dice: No tengo idea sobre "async", pero hay una solución alternativa usando "onreadystatechange".
Todo lo demás dice: soy tu amigo, vamos a hacer esto según el libro.
Ahora, el código completo con IE <10 solución alternativa:
fuente
Una razón por la cual sus scripts podrían cargarse tan lentamente es si estaba ejecutando todos sus scripts mientras cargaba la página, de esta manera:
en vez de:
Este segundo fragmento de secuencia de comandos espera hasta que el navegador haya cargado por completo todo su código Javascript antes de comenzar a ejecutar cualquiera de sus secuencias de comandos, lo que hace que parezca que la página se ha cargado más rápido.
Si está buscando mejorar la experiencia del usuario al disminuir el tiempo de carga, no elegiría la opción "pantalla de carga". En mi opinión, eso sería mucho más molesto que simplemente hacer que la página se cargue más lentamente.
fuente
Te sugiero que eches un vistazo a Modernizr . Es una biblioteca pequeña y liviana que puede cargar asincrónicamente su javascript con características que le permiten verificar si el archivo está cargado y ejecutar el script en el otro que especifique.
Aquí hay un ejemplo de carga de jquery:
fuente
Escribí una pequeña publicación para ayudar con esto, puedes leer más aquí https://timber.io/snippets/asynchronously-load-a-script-in-the-browser-with-javascript/ , pero adjunto la clase de ayuda a continuación. Esperará automáticamente a que se cargue un script y devolverá un atributo de ventana especificado una vez que lo haga.
El uso es así:
fuente
Puede encontrar este artículo wiki interesante: http://ajaxpatterns.org/On-Demand_Javascript
Explica cómo y cuándo usar dicha técnica.
fuente
Bueno,
x.parentNode
devuelve el elemento HEAD, por lo que está insertando el script justo antes de la etiqueta head. Quizás ese sea el problema.Intenta en su
x.parentNode.appendChild()
lugar.fuente
Echa un vistazo a este https://github.com/stephen-lazarionok/async-resource-loader . Tiene un ejemplo que muestra cómo cargar JS, CSS y múltiples archivos de una sola vez.
fuente
Puedes usar LABJS o RequreJS
Los cargadores de scripts como
LABJS
,RequireJS
mejorarán la velocidad y la calidad de su código.fuente
¿Has considerado usar Fetch Injection? Hice rodar una biblioteca de código abierto llamada fetch-inject para manejar casos como estos. Así es como se vería su cargador usando la lib:
Para la compatibilidad con la versión anterior, aproveche la detección de funciones y recurra a XHR Injection o Script DOM Elements, o simplemente inserte las etiquetas en la página usando
document.write
.fuente
Aquí está mi solución personalizada para eliminar JavaScript que bloquea el renderizado:
En resumen, carga todos sus scripts de forma asíncrona y luego los ejecuta en consecuencia.
Repo de Github : https://github.com/mudroljub/js-async-loader
fuente
No 'Access-Control-Allow-Origin' header is present on the requested resource
Aquí una pequeña función ES6 si alguien quiere usarla en React, por ejemplo
fuente
Sugeriría buscar minificar los archivos primero y ver si eso te da un aumento de velocidad lo suficientemente grande. Si su host es lento, podría intentar poner ese contenido estático en un CDN.
fuente