¿Cuál es el mejor lugar para colocar los tag <scripts src=""> en HTML?

36

13

Recientemente tuve un problema al llamar los scripts de JQuery en un pequeño script de php, por lo general los coloco después de la etiqueta body así:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>

</body>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</html>

Esto para evitar que se demore la carga de los demás elementos de la página.

El problema es que estaba haciendo una especie de template con 3 archivos php:

  1. header.php
  2. menus.php
  3. footer.php

En el header llamo todos los elementos head, por ejemplo css, meta, title; en menús creo el menú que será visible en todas las páginas, y en footer tengo el pie de pagina y los tag <script>, pero al momento de realizar algunas otra páginas y llamar alguna función de JQuery me lanza un error:

$ no está definido

La solución fue colocar todos estos scripts en el header. De tal manera que primero se cargan estos scripts y luego las etiquetas restantes.

He revisado esta pregunta en SO inglés:

https://stackoverflow.com/questions/436411/where-is-the-best-place-to-put-script-tags-in-html-markup

Sin embargo al cargarse asincronamente los scripts externos, hay ocasiones en las que sale el mismo error citado anteriormente.

Mi pregunta es: ¿Cuál es la mejor ubicación para colocar estos tags? ya que hasta ahora lo que me ha solucionado ese problema es mantenerlos en la cabecera.¿O debería pensar en otra manera de hacer el template en PHP?

Juan Pinzón

Posted 2016-09-26T17:05:33.443

Reputation: 5 772

Mira, cuando tengas una duda sobre HTML, usa el validator para que no tengas problemas con la sintaxis. Porque realmente la duda no radica en javascript sino en HTML5.

Diesan Romero 2017-10-25T16:52:24.273

2Después de leer las respuestas que hay hasta ahora, considero que sería bueno que las basaran en datos, documentos o demostraciones técnicas, no solo en gustos personales. Veo un par de respuestas que están orientadas de esa manera.Shaz 2016-09-27T01:12:49.940

Answers

59

En primer lugar, el script es una etiqueta de HTML que debe ser incluida en el header o en el body, no puede incluirse fuera, por esa razon no puedes acceder a Jquery.

Debes reemplazar:

</body>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

Por esto:

<script src="https://code.jquery.com/jquery-3.1.0.js"></script> 
</body>

¿Cuál es el mejor lugar para color las etiquetas script?

Debes evitar poner los scripts en el header. El renderizado e interpretacion del HTML se realiza a medida que el navegador encuentra los elementos en tu documento HTML. Por lo tanto si encuentra en la cabecera una etiqueta script, pues tendrá que esperar a que el navegador cargue el script para continuar con el renderizado de la pagina por lo que verías el navegador con la pantalla en blanco, comportamiento que uno desea evitar.

Adicionalmente, el comportamiento de los scripts se ven afectados por el uso de los atributos async y defer.

introducir la descripción de la imagen aquí

Etiqueta Script sin ningun atributo

Cuando definimos una etiqueta script sin ningún atributo el HTML será interpretado hasta que encuentre la etiqueta script, en ese punto la interpretación se detendrá y solicitará el archivo js(en caso sea externo), una vez que tengamos cargado el archivo entonces este sera ejecutado antes de que se continué interpretando el HTML. introducir la descripción de la imagen aquí

Async

El atributo async permite que el navegador descargue el archivo script asíncronamente(de ahí el nombre,sorprendente no?) y continuar con la interpretación del HTML, a penas termine con la descarga interrumpirá la interpretación para empezar la ejecución del script e inmediatamente después continuará con el proceso de interpretación. introducir la descripción de la imagen aquí

Defer

El atributo defer a diferencia de async, aplaza(defer) la ejecución del script después de que la interpretación del HTML ha concluido, la descarga se realiza de forma asíncrona igual que en el caso anterior pero defer nos garantiza ejecutar los scripts en el orden en el que aparecen en nuestro documento, a diferencia de async que los ejecuta a penas termina de descargar. introducir la descripción de la imagen aquí

¿Cómo decidir entre usar async o defer?

Te recomiendo leer https://somostechies.com/async-vs-defer.

Jesus Angulo

Posted 2016-09-26T17:05:33.443

Reputation: 1 405

1Sería bueno añadir algo más a la sección de "¿Cómo decidir entre usar async o defer?". Los enlaces se rompen y dejan de funcionar y puede ser una parte interesante de la respuesta.Alvaro Montoro 2017-10-25T17:17:33.907

3esta debería ser la respuesta aceptada...Augusto Herbel 2017-01-04T19:38:30.940

10

Esto está mal:

</body>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

Los scripts, por norma general se deben colocar antes del cierre del body. Sin embargo, hay casos particulares en donde es conveniente ponerlos en el header.

¿Cuál es el proceso de renderizado de un documento HTML?

  1. Parseo del documento
  2. Encuentra una etiqueta script con una archivo externo. 2.1 Carga el script y detiene la carga del documento hasta que el script haya sido completamente cargado.
  3. Se ejecutan los scripts.
  4. Finaliza la carga del documento.

¿Cuándo usar async/defer?

Async te permite cargar un script asíncronamente, es decir, no detiene la carga del documento y es ejecutado ni bien es cargado.

Supongamos el siguiente escenario:

<script async src="jquery.min.js"></script>
<script async src="bootstrap.min.js"></script>

En este caso, bootstrap puede ejecutarse antes que jquery.

Defer tampoco es bloqueante, pero a diferencia de async sí respeta el orden de los scripts.

¿Cuándo es correcto poner los scripts en el header?

Una práctica habitual es también poner los scripts en el header con async o defer, de este modo, los scripts son obtenidos inmediatamente cuando empieza el parseo pero sin bloquear el mismo.

gugadev

Posted 2016-09-26T17:05:33.443

Reputation: 14 261

9

Para mi, en este momento es mejor ponerlos antes del cierre de la etiqueta body como se menciona en una respuesta

Simplemente por una razón, async es solo soportado en Internet Explorer 10+ por tanto hay muchos usuario que pudieran tener problemas, aparte es una característica de HTML5 por tanto algunos exploradores viejos también se verán afectados.

Claro que en algunos años esto no importará por que los usuarios de IE probablemente pasen a Microsoft Edge donde ya está soportado, incluidos updates en otros navegadores, simplemente ya no se justificará.

Por otro lado, si tienes problemas con librerias como jQuery, deberías revisar el output de tu página, seguramente se ejecuta algo donde no.

Como yo utilizo mis platillas tengo una sección de de estilos y 3 para los scripts, imports, ready, functions

  1. imports donde agrego los <script src ...

  2. ready donde hay un document.ready esto para solo tener uno siempre.

  3. functions por si hay alguna funcion que no quiera meter dentro de de algún js por x o y razón

Espero te ayude

jasilva

Posted 2016-09-26T17:05:33.443

Reputation: 4 092

6

La integración de JavaScript y XHTML es muy flexible, ya que existen al menos tres formas para incluir código JavaScript en las páginas web.

Incluir JavaScript en el mismo documento XHTML

El código JavaScript se encierra entre etiquetas <script> y se incluye en cualquier parte del documento. Aunque es correcto incluir cualquier bloque de código en cualquier zona de la página, se recomienda definir el código JavaScript dentro de la cabecera del documento (dentro de la etiqueta <head>):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejemplo de código JavaScript en el propio documento</title>
<script type="text/javascript">
  alert("Un mensaje de prueba");
</script>
</head>

<body>
<p>Un párrafo de texto.</p>
</body>
</html>

Para que la página XHTML resultante sea válida, es necesario añadir el atributo type a la etiqueta <script>. Los valores que se incluyen en el atributo type están estandarizados y para el caso de JavaScript, el valor correcto es text/javascript.

Este método se emplea cuando se define un bloque pequeño de código o cuando se quieren incluir instrucciones específicas en un determinado documento HTML que completen las instrucciones y funciones que se incluyen por defecto en todos los documentos del sitio web.

El principal inconveniente es que si se quiere hacer una modificación en el bloque de código, es necesario modificar todas las páginas que incluyen ese mismo bloque de código JavaScript.

Definir JavaScript en un archivo externo

Las instrucciones JavaScript se pueden incluir en un archivo externo de tipo JavaScript que los documentos XHTML enlazan mediante la etiqueta <script>. Se pueden crear todos los archivos JavaScript que sean necesarios y cada documento XHTML puede enlazar tantos archivos JavaScript como necesite.

Ejemplo:

Archivo codigo.js

alert("Un mensaje de prueba");

Documento XHTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejemplo de código JavaScript en el propio documento</title>
<script type="text/javascript" src="/js/codigo.js"></script>
</head>

<body>
<p>Un párrafo de texto.</p>
</body>
</html>

Además del atributo type, este método requiere definir el atributo src, que es el que indica la URL correspondiente al archivo JavaScript que se quiere enlazar. Cada etiqueta <script> solamente puede enlazar un único archivo, pero en una misma página se pueden incluir tantas etiquetas <script> como sean necesarias.

Los archivos de tipo JavaScript son documentos normales de texto con la extensión .js, que se pueden crear con cualquier editor de texto como Notepad, Wordpad, EmEditor, UltraEdit, Vi, etc.

La principal ventaja de enlazar un archivo JavaScript externo es que se simplifica el código XHTML de la página, que se puede reutilizar el mismo código JavaScript en todas las páginas del sitio web y que cualquier modificación realizada en el archivo JavaScript se ve reflejada inmediatamente en todas las páginas XHTML que lo enlazan.

Incluir JavaScript en los elementos XHTML

Este último método es el menos utilizado, ya que consiste en incluir trozos de JavaScript dentro del código XHTML de la página:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ejemplo de código JavaScript en el propio documento</title>
</head>

<body>
<p onclick="alert('Un mensaje de prueba')">Un párrafo de texto.</p>
</body>
</html>

El mayor inconveniente de este método es que ensucia innecesariamente el código XHTML de la página y complica el mantenimiento del código JavaScript. En general, este método sólo se utiliza para definir algunos eventos y en algunos otros casos especiales, como se verá más adelante.

user9099

Posted 2016-09-26T17:05:33.443

Reputation:

4

Hay teorías para todos los gustos. A mi personalmente, me gusta mas ponerlos antes de la etiqueta </body>

Uno de los motivos, es que aunque falle, la codificación javascript, la página se va a cargar de todas formas, aunque a veces, lo he tenido que cargar en el head, porque sino la página me fallaba

Jose Javier Segura

Posted 2016-09-26T17:05:33.443

Reputation: 1 376

4

El problema que planteas no es la posición de elementos script, sino del orden de ejecución de la página.

En xHTML los elementos script deberían colocarse dentro del elemento head. A partir de HTML 5 es menos restrictivo y puede colocarse donde se quiera; se recomienda situarlos como últimos elementos, eso permite que todo el DOM esté cargado antes de intentar ejecutar nada y hace prescindibles métodos como ready().

Utilizar propiedades defer o async no lo resolverán, estás retrasan la carga del elemento al que afectan.

Tu problema sucede por el orden de carga/ejecución: tienes algún fragmento de código que intenta usar el alias de jQuery ($) antes de que se cargue el propio jQuery. Coloca el resto de tu código JavaScript después de la carga de jQuery.

Danos una muestra mas completa de tu código si no consigues resolverlo.

José M. Carnero

Posted 2016-09-26T17:05:33.443

Reputation: 532

3

Lo mejor siempre es colocar los "scripts" antes del cierre de "body" y después de todo tu contenido HTML div, a, span, etc, debido a que por lo general haces llamado a los elementos por ID o Clase y deben estar cargados antes de comenzar a ejecutarse.

Otra cosa que también debes tomar en cuenta a la hora de incluir tus "scripts" es colocar las dependencias primero, por ejemplo

...

</div><! Cierre de tu último tag HTML de contenido -->
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="script-que-usa-jquery-como-dependencia.js"></script>
</body>
</html>

Con esto evitaras el mensaje de

$ no está definido

debido a que jquery estará cargando antes de comenzar a ejecutar "script-que-usa-jquery-como-dependencia.js".

Josue Guol

Posted 2016-09-26T17:05:33.443

Reputation: 41

3

La pregunta es algo debatible ya que influye mucho lo que haga la página al momento de iniciar.

En mi experiencia es poner los .css en el <head> y los .js al final del <body> similar a lo siguiente

<head>
<link href="mynew.css" rel="stylesheet" type="text/css" />
</head>
<body>
... mi html
<script src="myJavaScript.js" type="text/javascript"></script>
<body>

ya que los css se cargan al principio para darle la interfaz a la pagina, y la funcionalidad que son los js se agregan al final, ya que muchas veces no se necesita funcionalidad al iniciar, de igual manera al estar de ultimo la carga es más rápida pues muestra la información al usuario, a pesar de no haber cargado la funcionalidad.

También comento que si llegas a necesitar que se ejecute una función al abrir la página puede incluir el js de dicha función en el head.

Espero te sirva de ayuda.

eezzekl

Posted 2016-09-26T17:05:33.443

Reputation: 421

0

Lo habitual es organizarlo de forma que se cargue en orden aunque le pongas 'asinc'

<html>
<head>
<script>"Carga de frameworks y js internos, lo primordial
 es que la librería de jquery este en cabeza y si lo tienes en local mejor, así no dependes del estado del repositorio"</script>
<script type="text/javascript">
        window.onload = function (){"funciones de inicio que se cargan al cargar todo el html, esto es sobre todo para funciones que toquen DOM o que dependan de el"}</script>
</head>
<body>Aquí dentro nada de js jamás</body>
<script>Funciones que no requieren una carga al inicio, como .clicks/.hover y demás</script>
</html>

Más o menos así es como solemos organizar por aquí las app. Lo esencial es que todo lo que puedas meter en un js externo, dentro de la carpeta js, lo pongas ahí y en el html escribas solo lo indispensable.

Alvargon

Posted 2016-09-26T17:05:33.443

Reputation: 1

-1

Usa un único script para crear los demás scripts y luego añades el src="..." en tu código:

<script>
//Esto creará el cuerpo.
document.write(".")
document.body.innerHTML=""
//Esto creará el script.
s=document.createElement("SCRIPT")
s.src="script.js"
document.body.appendChild(s)
</script>

Así no te hará falta colocarlo, sino que el navegador lo hará por tí.

Enderman Tesla

Posted 2016-09-26T17:05:33.443

Reputation: 75