Compilador de cierres para OpenLayers 3.x
Publicado el 02 de diciembre de 2010 Actualizado el 24 de enero de 2017

Seguramente habrás oído hablar de las Google Closure Tools de JavaScript que fueron publicadas como código abierto (licencia Apache 2.0) por Google hace más de un año. Es un conjunto de herramientas que se utilizan para el desarrollo de Gmail, Google Maps, Reader, Docs y otros productos populares de Google.
En esta entrada del blog me gustaría resumir qué características geniales ofrecen las Closure Tools a los desarrolladores de grandes proyectos JavaScript de código abierto, y me gustaría sugerir (re)escribir OpenLayers 3. 0 de la manera, que es totalmente utilizable con Closure Tools. Todos podemos beneficiarnos de lo que ya existe - y escribir aplicaciones web y móviles más pequeñas y más rápidas más fácil con las futuras versiones de OpenLayers, si decidimos ir por este camino.
La herramienta más importante de Closure es el compilador. Todas las demás herramientas son opcionales y se construyen alrededor de las características del compilador. El compilador se puede utilizar desde la línea de comandos o como una aplicación web. También puedes enviar tu código fuente por HTTP POST y obtener el código compilado. El compilador puede ser utilizado por los scripts de construcción existentes de OpenLayers fácilmente.
El compilador tiene varias características interesantes:
- Compila el JavaScript legible en un JavaScript comprimido y legible por la máquina.
- La documentación del código con las etiquetas JSDoc es importante: el compilador la lee y se obtienen advertencias durante la compilación por errores en la documentación, uso incorrecto de un @constructor, tipo incorrecto de una variable, uso incorrecto de un campo anotado con @private y @protected, etc.
- Si escribe una biblioteca JavaScript reutilizable, como OpenLayers, exporta formal mente su API pública y el compilador optimiza su código interno.
- Las aplicaciones finales pueden ser compiladas junto con la biblioteca - y luego las partes no utilizadas de la biblioteca se eliminan del código producido. Las dependencias son resueltas automáticamente por el compilador.
- El compilador acepta constantes para eliminar la funcionalidad no deseada - esto permite la compilación sólo para un navegador en particular como Mobile WebKit, para sólo uno de los modos Quirks o modo estricto, compilación sin soporte de IE6, etc.
- Ladepuración con FireBug es posible incluso para la versión compilada del código fuente.
- El compilador admite la generación de módulos cargables dinámicamente, lo que puede acelerar significativamente la carga de la aplicación final, ya que el código para la funcionalidad avanzada puede cargarse sólo cuando se requiere.
Repasemos estos puntos uno por uno:
1. Compila el JavaScript legible en un JavaScript comprimido y legible por la máquina.
El compilador carga todo el código fuente de la aplicación JavaScript suministrada en la memoria, hace un análisis detallado del código, prepara el gráfico interno de dependencia y mientras conoce la sintaxis y en parte también la semántica del lenguaje JavaScript, hace la compilación.
Si utilizas la opción por defecto "SIMPLE_OPTIMIZATION" entonces Closure Compiler se comporta como otro minimizador de JavaScript: eliminación de espacios en blanco y comentarios, renombrando las variables locales y los parámetros de las funciones a nombres más cortos (sólo los símbolos que son locales a las funciones). Se puede utilizar directamente con los perfiles de construcción de OpenLayers como están disponibles ahora - y se obtiene alrededor de un 20% más pequeño archivo OpenLayers.js en la salida, en comparación con la minimización basada en jsmin por defecto del código. Comprueba también los últimos #2871 y #2873 si quieres tener resultados más pequeños para OL. Por cierto, las versiones oficiales de jQuery ahora se minimizan con el compilador Closure y SIMPLE_OPTIMIZATION.
Lo verdaderamente potente es el compilador cuando se utiliza con la "OPTIMIZACIÓN_ADVANZADA". Entonces utiliza varios trucos para acortar aún más el código, incluyendo la eliminación de código muerto y la inlinación de funciones. Pero el código JavaScript debe estar listo para la compilación y no puede contener patrones de código con errores. Esto significa que los programadores son empujados a escribir su código JavaScript de una manera más legible y mantenible. El problema típico es el uso de "this" fuera de los constructores y métodos prototipo. Los programadores no pueden utilizar algunas de las técnicas que ofrece el lenguaje JavaScript, pero estas restricciones también ayudan a mantener el código legible y reutilizable por otras personas más adelante. En general, los programadoresdeben seguir las reglas descritas en la Guía de Estilo de JavaScript. También existe una herramienta de comprobación y corrección automática del código JavaScript llamada Linter que puede ayudar. OpenLayers 2.x no sigue estas reglas ahora mismo, pero creo que para OpenLayers 3.0 tendría sentido escribir el código teniendo en cuenta estas reglas.
2. La documentación del código con JSDoc Tags es importante: el compilador la lee
OpenLayers 2.x, al igual que otros grandes proyectos de JavaScript, utiliza comentarios JSDoc para la documentación en línea del código fuente. El compilador de Google Closure analiza estas etiquetas JSDoc y las utiliza para mejorar el proceso de optimización del código y para imprimir advertencias durante la compilación de patrones de código potencialmente defectuosos o errores, si se utiliza con "-warning_level=VERBOSE".
De hecho, a través de los comentarios de JSDoc, el lenguaje JavaScript se ha mejorado con un completo sistema de tipos para las variables y con la visibilidad de los objetos.
El conjunto de anotaciones y expresiones de tipoJSDoc que el compilador Google Closure entiende se describe en http://code.google.com/closure/compiler/docs/js-for-compiler.html.
El sistema de tipos introducido es potente. OpenLayers puede beneficiarse de la posibilidad de definir sus propios tipos de objetos, por ejemplo el objeto "OpenLayers.Location" puede ser un nuevo tipo que siempre debe contener ".x" y ".y" con tipo float. El compilador puede imponer esto: siempre que una función espere "OpenLayers.Location" como parámetro, recibirá una advertencia durante la compilación si utiliza un objeto que no lo cumple.
3. La API pública está formalizada: el compilador la necesita
Es importante tener una definición formal de la API pública que está exportando de la biblioteca como OpenLayers - la compilación de una biblioteca JavaScript públicamente utilizable no es posible sin eso. Significa que usted es empujado a mantener la API limpia - así como documentado correctamente con JSDoc.
4. Las aplicaciones finales pueden compilarse junto con la biblioteca
Las aplicaciones para el usuario final se pueden programar de forma tradicional: Así, la biblioteca OpenLayers se utiliza como un script OpenLayers.js independiente, que se incluye en el sitio web en la cabecera HTML. La aplicación en sí tiene una base de código independiente, y utiliza la API pública de OpenLayers. Este enfoque es común con OpenLayers 2.x.
Un enfoque alternativo es que el código de la aplicación se fusione con el código de la biblioteca y luego el resultado se compile conjuntamente - de esta manera las partes no utilizadas de la biblioteca se eliminan automáticamente del código final. Las dependencias en el código son resueltas por el compilador. Sólo la funcionalidad de JavaScript, que es realmente en uso por la aplicación final es entonces parte del archivo final compilado .js, que se utiliza para el despliegue y el uso de producción.
5. Constantes definidas durante la compilación para eliminar la funcionalidad no deseada
Las variables anotadas con la etiqueta @define JSDoc pueden ser redefinidas durante la compilación, y entonces el compilador puede reconocer bloques de código condicionados con tales variables como inalcanzables. Porque el código muerto es eliminado automáticamente - tal código fuente es completamente despojado del archivo .js resultante.
El caso de uso típico para esto es un bloque de código que se ejecuta sólo si alguna variable DEBUG se establece como verdadera, pero también hay otros casos de uso:
El código fuente de una librería JavaScript puede contener muchas funciones para manejar las diferencias entre el modo Quirks y el modo Strict de un navegador web, determinado por la etiqueta DOCTYPE al principio de la página HTML. La biblioteca JavaScript general debe soportar ambos modos, pero si usted es un desarrollador de una aplicación web, usted controla en qué modo de renderizado se utiliza su aplicación. Esto significa que el manejo del modo Quirks puede ser fácilmente despojado de la biblioteca que está utilizando.
Del mismo modo, si está desarrollando una aplicación web móvil para la plataforma iPhone o Android, no necesita realmente en su aplicación un código específico para Internet Explorer o para versiones antiguas de Firefox u otros navegadores.
La Closure Library, la biblioteca estándar de JavaScript que viene con Closure Tools, ya soporta este tipo de compilación condicional para diferentes navegadores (a través de goog.userAgent.ASSUME_MOBILE_WEBKIT) y modos de renderizado (goog.dom.ASSUME_STANDARDS_MODE).
Vi en FOSS4G que para OpenLayers 3.x está prevista una interoperabilidad más estrecha con las bibliotecas generales existentes como Prototype, jQuery o Closure Library para acceder al DOM, operar sobre cadenas u otras funcionalidades básicas - para no reinventar la rueda dentro de OpenLayers y eliminar el código duplicado para la misma funcionalidad en las aplicaciones finales, que ya están utilizando una de estas bibliotecas de todos modos. La compilación condicional con constantes soportadas por el compilador Closure puede ayudar en este caso.
6. Depuración con FireBug
El código JavaScript minimizado es normalmente muy difícil de depurar, porque el código está ofuscado y no hay referencia a los nombres de formato y variables originales.
Closure Compiler viene con dos enfoques útiles para depurar el código compilado en el modo ADVANCED_OPTIMIZATION:
El primero es el parámetro "-debug=true", que hace que las variables renombradas que normalmente se acortan a una o dos letras mantengan nombres significativos - por ejemplo, "OpenLayers.Location.prototype.setValue" se convierte en $$OpenLayers$$Location$$$$$setValue$$
en lugar de "aa", por ejemplo. Este parámetro se utiliza muy a menudo con "-formatting=PRETTY_PRINT".
La segunda opción es utilizar el código final compilado junto con la extensión Inspector para Firefox. El compilador genera un archivo de asignación entre el código fuente original y el código compilado y la extensión simplifica la depuración con Firebug, una vez que se carga dicho archivo de asignación.
7. Módulos cargables dinámicamente
La API de Google Maps V3, así como otros productos de Google, están compilados para cargar sólo un pequeño núcleo (bootstrap) de la funcionalidad necesaria y posteriormente cargar las extensiones con más código. Este enfoque puede acelerar significativamente la primera aparición de una aplicación web, lo que es importante especialmente en los dispositivos móviles.
El compilador Closure, por supuesto, soporta esta forma de compilación, con parámetros en la línea de comandos.
Todo el proyecto puede ser compilado con un simple Makefile o con scripts de fusión y compilación personalizados, pero también hay varias herramientas disponibles para simplificar la compilación, las dependencias de los módulos y el manejo del código que está repartido en varios archivos - estas herramientas son útiles especialmente si estás usando Closure Library o necesitas compilar en módulos: Plovr, ClosureBuilder, o Closure Modules. Con la biblioteca Closure viene también closurebuilder.py y depswriter.py.
Estoy muy interesado en discutir con los desarrolladores de OpenLayers y la comunidad la aplicación del compilador Closure y sus ventajas y desventajas.
Ya hemos utilizado el compilador y la biblioteca Closure en algunos proyectos que ahora están en producción, por lo que tenemos experiencia práctica con estas herramientas, por ejemplo desde el desarrollo de la interfaz web de nuestro producto MapRank Search.
Si hay interés puedo publicar otra entrada en el blog con el código de un proyecto sencillo y una guía paso a paso que demuestre el uso del compilador y la biblioteca Closure.
Las herramientas de Closure son definitivamente dignas de atención para cualquier desarrollador web. Por favor, escribe en los comentarios lo que piensas sobre el tema de Closure Compiler y OpenLayers V3.