¿Por que se dice que los scripts de javascript deben ir en el cierre?
En la web existen muchas recomendaciones acerca de que deben poner el javascript al final del sitio justo antes del cierre del </body>, la razón argumentada es sencilla, los navegadores leían secuencialmente los scripts y bloqueaban el render de la página hasta haberla leído el script, pero entonces ¿por qué razón Ruby on Rails, que supuestamente es construido por expertos carga javascript dentro de la etiqueta <head> </head> en lugar del cierre de la página?.
¿Entonces por qué Rails los pone al principio?
Hay 2 razones:
La primera es porque todos los navegadores modernos (incluyendo internet explorer 8) a partir del 2008 incorporaron un sistema llamado preload scanning que les permite cargar todos los scripts paralelamente sin causar bloqueos (bueno, realmente los bloqueos todavía existen, pero son parciales y ya ahondaremos más sobre como eliminarlos).
El segundo problema de agregar javascript al inicio consiste en que a veces alguna funcionalidad crítica de la página (o de tu negocio) depende de esos javascript, por ejemplo si pones google analytics al final, en el cierre del body y el usuario sale del sitio antes de terminar cargar la página entonces pierdes la data del usuario, otra de las funcionalidades críticas de Rails viene dada por jquery-ujs, si esto se cargara al final de la página tendríamos un problema con los usuarios que son del tipo Quicky Clicker y presionan el los links antes de que la página termine de cargar.
Más sobre Preload Scanning
Preload Scanning no evita completamente el bloqueo, su implementación cambia dependiendo del navegador, pero en términos básicos consiste en un light weight process que se levanta para seguir leyendo archivos css, imágenes u otros scripts cuando se topa con un script. Pero esta lectura es sólo de forma parcial, por lo que sigue siendo recomendado en muchos casos poner javascript al final.
Otra forma de optimizar el proceso es ponerlo en el head junto con los atributos async o defer, este thread de stackoverflow es bastante aclarativo sobre las diferencias, sin embargo como todo lo asincrónico se recomienda implementar con cuidado.
¿Que dice google al respecto?
Técnicamente el guideline oficial de google developers dice que debes evitar en lo posible bloquear, en otras palabras cargar javascript, si lo haces, hazlo al final, ocupa async y defer cuando puedas y si el script es pequeño, es mejor tenerlo dentro del html (esto último si que me lo esperaba) debido que al evitar el llamado disminuyes la latencia de los requests.
Sugerencias finales:
Nada de lo leído quiere decir que uno pueda poner en cualquier parte cualquier script, muchos de ellos tienen dependencias, otros necesitan el DOM cargado y como no están bien programados hay que agregarlos necesariamente al final, a fin de cuentas el preload scanning lo que lo logra es evitar que la lectura de un script de javascript bloquee la lectura del HTML.
En resumen:
si las funcionalidad es crítica en el head, sino en el cierre del body, si el javascript consiste sólo en un par de líneas puede ir inline para optimizar la carga.
Referencias:
http://andydavies.me/blog/2013/10/22/how-the-browser-pre-loader-makes-pages-load-faster/
http://railsapps.github.io/rails-javascript-include-external.html
http://stackoverflow.com/questions/436411/where-is-the-best-place-to-put-script-tags-in-html-markup
https://developers.google.com/speed/docs/insights/BlockingJS