Javascript está con nosotros desde hace más de 20 años, si bien ha pasado por momentos donde fue considerado mala palabra y una representación de todo lo malo en un lenguaje de desarrollo, estos últimos años ha ganado gran popularidad, al punto de convertirse en el lenguaje casi único para todo lo relacionado con el Front-end.

A medida que entramos en el mundo Javascript y nuestros desarrollos empiezan a ser más avanzados empezamos a requerir de herramientas adicionales que simplifiquen nuestro trabajo o que automaticen procesos tediosos. Acá es donde entran en escena herramientas como npm, Bower, Webpack, Grunt, Gulp, Browserify, y otro tanto más que son usadas cotidianamente. Entre tantas herramientas uno empieza a preguntarse que hace cada una de ellas y para que sirven. En este artículo vamos a tratar de dar una explicación rápida para tener una idea inicial de cuando utilizar cada una de ellas.

Antes de empezar a explicar cada una de estas herramientas debemos agruparlas, ya que varias de ellas persiguen el mismo objetivo o nos permiten hacer lo mismo, de esta forma podemos comparar herramientas similares y seleccionar la más adecuada para nuestro proyecto. Inicialmente tenemos 2 grandes grupos

  • Herramientas que se dedican a instalar cosas (Administradores de Paquetes).
  • Herramientas que hacen cosas por nosotros (que no sea instalar, como bundling, etc).

Administrador de Paquetes

Un Administrador de Paquete (Package Manager) gestiona la instalación y actualización de las librerías de un proyecto, incluyendo sus dependencias. Librerías tales como jQuery, Bootstrap, AngularJS, etc, cualquiera que sea utilizada en nuestra aplicación y que no ha sido escrita por nosotros.

Estos Administradores de Paquetes permiten gestionar desde unos simples comandos de consola la descarga, copiado e instalación en el proyecto de los archivos provistos por la librería (o paquete), así como las dependencias del mismo (otras librerías que son utilizadas por el paquete que estamos instalando).

Dentro de los Administradores de Paquetes encontramos a npm, Bower y Yarn.

  • npm: Esta herramienta de gestión de paquetes es provista de forma conjunta con Node.js, desde la cual podemos administrar todas las librerías externas que necesita nuestro proyecto. NPM permite manejar librerías de front-end (como jQuery, Bootstrap, AngularJS, etc) como de back-end (como Express, etc), y todas las dependencias que ellas requieran. Todas las librerías descargadas son instaladas dentro de la carpeta  /node_modules/ , y es una práctica muy útil la utilizacioón del archivo llamado package.json, el cual funciona como un descriptor de los modulos instalados y gestionados por npm.
  • Bower: Es similar a npm pero solo para librerías de front-end. Todas las librerías necesarias son definidas en el archivo bower.json y solo requerimos ejecutar bower install en la línea de comandos para que todas nuestras librerías sean descargadas e instaladas dentro de la carpeta  /bower_components/.
  • Yarn: Desarrollado por Facebook, Google y otros, Yarn es un CLI client que descarga librerías utilizando el registro de npm. De esta forma Yarn nos permite utilizar todo el arsenal de paquetes de npm (que superan los 350.000) agregando funcionalidades como archivos de lock (yarn.lock que funciona como el viejo y querido composer.lock), mejora en la interfaz de salida, descarga paralela y offline (lo cual mejora sustancialmente el tiempo de descarga).

Las herramientas mencionadas anteriormente son las más conocidas y utilizadas para la gestión de paquetes en los proyectos con tecnología Javascript. Seguramente estoy dejando de lado algunas más, pero es tanta la cantidad de gestores que se van agregando que es imposible seguirles el paso a cada una de ellas.

Cargadores de Módulos / Empaquetadores

Antes de comenzar a describir estas herramientas debemos explicar un poco que son los módulos en Javascript. Los módulos son a los programas lo que los capítulos son a los libros. Un módulo no es más que un conjunto de lineas de código de un programa (funcionalidades) que deben ser lo suficientemente auto-contenidas como para poder ser intercambiadas sin alterar el sistema. De esta forma, al utilizar módulos mejoramos sustancialmente la mantenibilidad, reusabilidad y el nombramiento (namespacing) de los distintos elementos intervinientes en un programa. Los módulos se implementan con la idea de simular el concepto de clase.

Hasta acá venimos todo bien, el problema o complejidad surge en que existen diferentes estándares o especificaciones respecto a la implementación de los módulos, las cuales son:

  • CommonJS: Es la primer especificación de módulos y está orientada al server-side, Node.js está implementado utilizando CommonJS. Su mayor fortaleza es la sencillez sintáctica.
  • AMD: (Asynchronous Module Definition), nacio como una reacción a CommonJS, donde un grupo de desarrolladores no estaba satisfecho con la dirección adoptada. La principal diferencia entre AMD y CommonJS está en que AMD soporta la carga de módulos asíncrona, sacrificando sencillez sintáctica. AMD está orientado al front-end.
  • UMD: Esta especificación (Universal Module Definition) permite soportar las funcionalidades provistas por AMD y CommonJS, pudiendo trabajando tanto en backend como en frontend.
  • Native JS: Es la especificación de los módulos build-in introducidos en EMACScript 6 (ES6). Esta especificación permite utilizar lo mejor de CommonJS y AMD, una sintaxis compacta y carga asíncrona, además de otras mejoras.

Esta definición de que son los módulos, para que sirven y los tipos posibles de los mismos son de vital importancia para entender que hacen y como funcionan las herramientas de bundling y loader como RequireJS, Webpack, etc. En la parte 2 de este post entraremos en los detalle de como funcionan esta herrmientas y cuando conviene utilizarlas.