Prefacio
Creo que todos han encontrado muchos problemas con respecto a la carga de script de JavaScript. Principalmente en varios puntos -
1> Problemas con la carga de archivo, dependencia de archivos y orden de ejecución causada por scripts sincrónicos y scripts asíncronos
2> Problemas de optimización del rendimiento causados por scripts sincrónicos y scripts asincrónicos
Una comprensión profunda de todos los aspectos de la carga de script no solo conduce a resolver problemas prácticos, sino también conduciendo a comprender y ejecutar la optimización del rendimiento.
Primero busque cualquier código de etiqueta de script -
La copia del código es la siguiente:
<script src = "js/myapp.js"> </script>
Si se coloca en <cead>, bloqueará todo el trabajo de representación de la página, lo que hace que el usuario permanezca en un estado de "pantalla blanca de la muerte" hasta que el script se cargue y ejecute. El script al final de <body> solo permitirá al usuario ver la página estática sin vitalidad. Donde se supone que la representación del cliente se dispersa con controles ineficaces y cajas vacías. Tome un caso de prueba -
La copia del código es la siguiente:
<! Doctype html>
<html>
<head lang = "en">
<meta charset = "utf-8">
<title> Async Carging Script </title>
<script src = "js/test.js"> </script>
</ablo>
<Body>
<Div> Estoy contento </div>
<img src = "img/test.jpg">
</body>
</html>
Entre ellos, el contenido en Test.js -
La copia del código es la siguiente:
alerta ('¡Soy el código de script en la cabeza. Después de ejecutar el JS aquí, ¡comienza la representación del contenido del cuerpo!');
Veremos que la alerta es un punto de pausa, y en este momento, la página está en blanco. Sin embargo, tenga en cuenta que toda la página se ha cargado en este momento. Si el cuerpo contiene etiquetas para ciertos atributos SRC (como la etiqueta IMG anterior), el navegador ha comenzado a cargar el contenido relevante en este momento. En resumen, debe tenerse en cuenta que el tiempo de trabajo del motor JS y el motor de representación son mutuamente excluyentes (algunos libros lo llaman hilo de interfaz de usuario).
Por lo tanto, necesitamos que los scripts responsables de hacer que la página se vea mejor y use mejor debe cargarse de inmediato, y los scripts que se pueden cargar más tarde se cargarán más adelante.
1. Retraso de ejecución de script
Ahora se está volviendo cada vez más popular colocar guiones al final de la etiqueta de página <Body>. De esta manera, por un lado, el usuario puede ver la página más rápido y, por otro lado, el script puede operar directamente los elementos DOM que se han cargado. Este "movimiento" es una gran mejora para la mayoría de los guiones. El modelo de página es el siguiente -
La copia del código es la siguiente:
<! Doctype html>
<html>
<head lang = "en">
<!-Metadatos y hojas de guión van aquí->
<script src = "headscript.js"> </script>
</ablo>
<Body>
<!-El contenido va aquí->
<script src = "backyscript.js"> </script>
</body>
</html>
Esto acelera enormemente el tiempo de representación de la página, pero tenga en cuenta que esto puede dar a los usuarios la oportunidad de interactuar con la página antes de que se cargue BodyScript. La razón por la cual el navegador no puede cargar los scripts antes de cargar el documento completo es un gran cuello de botella para documentos grandes transmitidos a través de conexiones lentas.
Idealmente, la carga del script debe hacerse simultáneamente con la carga del documento y no afecta la representación del DOM. De esta manera, una vez que el documento está listo, el script se puede ejecutar porque el script correspondiente se ha cargado en el orden de la etiqueta <script>.
Podemos lograr este requisito utilizando diferencias, es decir,
La copia del código es la siguiente:
<script src = "deferredscript.js"> </script>
Agregar el atributo Difer es equivalente a decirle al navegador: comience a cargar este script de inmediato, pero espere hasta que el documento esté listo y todos los scripts con el atributo de diferencias hayan terminado de ejecutarlo antes de ejecutarlo.
De esta manera, poner los scripts de retraso en la etiqueta de la cabeza traerá todos los beneficios de colocar scripts en la etiqueta del cuerpo, y puede mejorar enormemente la velocidad de carga de documentos grandes. El modo de página en este momento es -
La copia del código es la siguiente:
<! Doctype html>
<html>
<head lang = "en">
<!-Metadatos y hojas de guión van aquí->
<script src = "headscript.js"> </script>
<script src = "deferredScript.js" Defer> </script>
</ablo>
<Body>
<!-El contenido va aquí->
</body>
</html>
Sin embargo, no todos los navegadores admiten diferir (para algunos navegadores modernos, si se declara diferido, sus scripts internos no realizarán documentos. Write y DOM Rendering Operations. Ambos Ie4+ soportan los atributos de diferir). Esto significa que si desea asegurarse de que su script de retraso pueda ejecutarse después de cargar el documento, debe encapsular el código de todos los scripts de retraso en una estructura como el $ (documento). Esto vale la pena, porque casi el 97% de los visitantes pueden disfrutar de los beneficios de la carga paralela, mientras que otro 3% de los visitantes aún pueden usar JavaScript con todas las funciones.
2. Completa paralelización de scripts
Deje que los scripts se carguen y ejecuten un paso más rápido. No quiero esperar hasta que los scripts de diferir se ejecuten uno tras otro (DERFER nos recuerda a un escenario de colas ordenado donde el documento espera silenciosamente que se cargue el documento), y no quiero esperar hasta que el documento esté listo antes de ejecutar estos scripts. Quiero cargar y ejecutar estos scripts lo antes posible. Aquí pensamos en el atributo asíncrono de HTML5, pero ten en cuenta que es una anarquía caótica.
Por ejemplo, cargamos dos scripts de terceros completamente irrelevantes, y la página funciona bien sin ellos, y no le importa quién corre primero y quién corre más tarde. Por lo tanto, usar el atributo Async en estos scripts de terceros es equivalente a mejorar su velocidad de carrera sin gastar un centavo.
El atributo Async se agrega recientemente a HTML5. La función es similar a diferir, es decir, permite la representación de DOM al descargar scripts. Sin embargo, se ejecutará lo antes posible después de la descarga (es decir, el motor JS está inactivo y se ejecuta de inmediato), y no hay garantía de que el script se ejecutará en orden. Se completarán antes del evento Onload.
Firefox 3.6, Opera 10.5, IE 9 y los últimos Chrome y Safari admiten el atributo Async. Async y Difer se pueden usar al mismo tiempo, de modo que todos los IE después de IE 4 admiten la carga asíncrona, pero tenga cuidado de que Async sobrescriba la aplazamiento.
Entonces el modelo de página en este momento es el siguiente -
La copia del código es la siguiente:
<! Doctype html>
<html>
<head lang = "en">
<!-Metadatos y hojas de guión van aquí->
<script src = "headscript.js"> </script>
<script src = "deferredScript.js" Defer> </script>
</ablo>
<Body>
<!-El contenido va aquí->
<script src = "asyncscript1.js" async aplazar> </script>
<script src = "asyncscript2.js" async aplazar> </script>
</body>
</html>
Preste atención a la orden de ejecución aquí: cada archivo de script se carga, luego se ejecuta HeadScript.js y luego DefferedScript.js se carga en segundo plano mientras DOM representa. Luego, DefferedScript.js y los dos scripts asincrónicos se ejecutarán al final de la representación de DOM. Tenga en cuenta que para los navegadores que admiten el atributo Async, estos dos scripts se quedará sin orden.
3. Carga de script programable
Aunque las funciones de las dos propiedades de script anteriores son muy atractivas, no se usan ampliamente debido a problemas de compatibilidad. Por lo tanto, usamos scripts para cargar otros scripts más. Por ejemplo, solo queremos cargar un script para los usuarios que cumplen con ciertas condiciones, que es la "carga perezosa" a menudo mencionada.
En el nivel de la API del navegador, hay dos formas razonables de rastrear y ejecutar scripts de servidor -
1> Generar la solicitud de AJAX y usar la función EV para procesar la respuesta
2> Inserte la etiqueta <script> en el DOM
El último método es mejor porque el navegador se preocupará por generar solicitudes HTTP para nosotros. Además, Eval también tiene algunos problemas prácticos: filtración de alcance, depuración es desordenada y también puede reducir el rendimiento. Por lo tanto, si desea cargar un script llamado Funcionar.js, debemos usar un código como el siguiente:
La copia del código es la siguiente:
var head = document.getElementsByTagName ('Head') [0];
var script = document.createElement ('script');
script.src = 'sports.js';
head.appendChild (script);
Por supuesto, necesitamos lidiar con la escucha de devolución de llamada, y la especificación HTML5 define una propiedad de ENCARGA que puede vincular las devoluciones de llamada.
La copia del código es la siguiente:
script.Onload = function () {
console.log ('Script cargado ...');
}
Sin embargo, las versiones IE8 y más antiguas no admiten Onload, admiten OnreadyStateChange. Además, todavía hay muchas cosas extrañas para lidiar con los errores. Aquí, puede consultar algunas bibliotecas de carga populares basadas en la escuela, como LABJS, Yepnope, Requestjs, etc.
De la siguiente manera, encapsula un archivo de carga simple yo mismo -
La copia del código es la siguiente:
var loadjs = function (url, devolución de llamada) {
var head = document.getElementsByTagName ('Head') [0];
var script = document.createElement ('script');
script.src = url;
script.type = "text/javaScript";
head.appendChild (script);
// Etiqueta de script, hay un evento OnreadyStateChange en IE, y hay un evento Onload bajo el estándar W3C
// IE9+ también es compatible con la carga de W3C Standard
var ua = navigator.useragent,
ua_version;
// ie6/7/8
if (/msie ([^;]+)/. test (ua)) {
ua_version = parsefloat (regexp ["$ 1"], 10);
if (ua_version <= 8) {
script.onreadystateChange = function () {
if (this.readyState == "cargado") {
llamar de vuelta();
}
}
} demás {
script.Onload = function () {
llamar de vuelta();
};
}
} demás {
script.Onload = function () {
llamar de vuelta();
};
}
};
No hablaré sobre la carga asíncrona de scripts en document.write. Ahora pocas personas hacen esto porque las diferencias del navegador son realmente abrumadoras.
Tenga en cuenta que usar el objeto de imagen para precargar los archivos JS de manera asincrónica, el código JS en el interior no se ejecutará.
Finalmente, hablemos sobre el guión de carga asíncrono en Requirjs.
RequestJS no garantiza que los scripts de destino se ejecuten secuencialmente, pero solo asegura que su orden de ejecución pueda cumplir con sus respectivos requisitos de dependencia. Por lo tanto, nos aseguramos de que todos los scripts se carguen en paralelo lo antes posible y los ejecuten de manera ordenada de acuerdo con la topología de dependencia.
4. Resumen
Ok, cuando se trata de esto, la declaración del script de carga asíncrono ha terminado. Permítanme hablar sobre el orden de optimización aquí nuevamente -
1> De la manera tradicional, usamos etiquetas de script para incrustarlos directamente en documentos HTML. Aquí hay dos situaciones -
A> Incorporar en la etiqueta de cabeza: tenga cuidado de que hacerlo no afecte la carga paralela de otros archivos de recursos estáticos en el contenido del documento. Afecta la representación del contenido del documento, es decir, la representación DOM en este momento se bloqueará y se presentará la pantalla blanca.
b> Incorporar en la parte inferior de la etiqueta del cuerpo: para evitar el fenómeno de la pantalla blanca, damos la prioridad de representar el DOM y luego ejecutar el script, pero el problema vuelve a aparecer. Hablemos primero sobre la primera pregunta: si el contenido del documento DOM es relativamente grande, la vinculación del evento de interacción se retrasará y la experiencia será un poco peor. Por supuesto, debemos hacer que los scripts importantes se ejecuten primero según las necesidades. Hablemos sobre el segundo problema: debido a que los archivos de script son hasta la parte inferior del cuerpo, la carga de estos scripts se retrasa en comparación con los scripts en la cabeza. Por lo tanto, en cuanto al fondo del cuerpo, no es el punto final de optimización.
c> Agregar Atributo de diferencias: esperamos que el script se cargue en paralelo lo antes posible, y aún así pondremos este lote de scripts en la cabeza. La carga del script debe hacerse simultáneamente con la carga del documento y no afecta la representación del DOM. De esta manera, el script se puede ejecutar una vez que el documento esté listo. Entonces hay un atributo diferido. Pero preste atención a su compatibilidad. Para los navegadores que no admiten el atributo de diferir, necesitamos encapsular el código en un $ (documento). Listo como jQuery. Cabe señalar que todos los scripts con atributos diferidos se ejecutan en secuencia de acuerdo con su orden de apariencia, por lo que también están estrictamente sincronizados.
2> El punto anterior se trata de scripts de ejecución sincrónicos (tenga en cuenta que el proceso de carga de estos scripts es paralelo, pero la diferencia entre quién desencadena primero la solicitud y quién activa la solicitud). El siguiente punto de optimización es "Scripts de ejecución paralelos". Por supuesto, sabemos que en un momento, solo se ejecuta un archivo JS. El "paralelo" aquí significa que quien carga primero, siempre y cuando el motor JS esté inactivo en este momento, se ejecutará de inmediato. La optimización aquí se divide en dos tipos -
A> Agregar la propiedad Async: de hecho, puede completar el punto de optimización que mencionamos anteriormente, pero tiene altas limitaciones, es decir, es solo para la carga de script no dependencia. El ejemplo más apropiado es introducir múltiples scripts de terceros. Además, la combinación con el atributo Deffer es realmente un gran problema. Por supuesto, también tiene problemas de compatibilidad. Los tres problemas anteriores han llevado a su aplicación poco frecuente. Al usar Async, debe prestar mucha atención a los problemas de dependencia.
B> Scripting Scripts: obviamente, usamos esto para lograr el propósito de "ejecución paralela de scripts". Al mismo tiempo, también facilitamos el control de las dependencias de scripts, por lo que utilizamos la gestión de carga inteligente para la carga asincrónica en requisitos.
Ok, eso es todo.
Aquí, solo estoy hablando del contenido relacionado con los scripts de carga asincrónicos. Hay otra parte del contenido, que es la carga asincrónica de archivos de estilo u otros recursos estáticos. continuará......