Guía de inicio del futuro: MeteorJS


Uff, palabras fuertes y bien opinionadas las del título del artículo. Es por ello que tengo la misión en las siguientes líneas de demostrarte por qué MeteorJS tendrá un futuro próspero y brillante.

La buena noticia es que el futuro ya es hoy, pues hace solo unos pocos meses que salió la primera versión estable del framework. Actualmente se está trabajando en la versión 1.2, próxima a salir y con muchísimas novedades. La versión actual es la 1.1.0.3.

¿Qué es MeteorJS?

Uno de los primeros libros con los que debes interactuar para aprender este framework es “Discover Meteor”. En su introducción se plantea que:

Meteor es una plataforma para crear aplicaciones web en tiempo real construida sobre Node.js.

Como Meteor usa Node.js, se utiliza JavaScript en el cliente y en el servidor. Y más aún, Meteor es capaz de compartir código entre ambos entornos.

De lo anterior hay que destacar dos puntos importantes:

  1. Las aplicaciones son en tiempo real por defecto.
  2. La misma API que se utiliza en el cliente se utiliza en el lado del servidor.

El primer punto es suficiente para conocer que Meteor es un fenómeno, pues, vamos, que tu aplicación solo con nacer se comporte como un sistema real time sin tan siquiera escribir una línea de código es una bendición.

Adiós Socket.io, adiós Express, adiós MVC y la locura de los servicios a los controladores, estos a la vista con two way data-binding, adiós la necesidad de AngularJS v1 y su routing, adiós a estar creando autenticación por tokens de forma manual. Welcome Meteor!

El segundo punto describe que Meteor brinda una API isomórfica, o sea, el código que escribes puede ser compartido y ejecutado en el cliente y el servidor a la vez (sí, el mismo).

Por otra parte, si nos enfocamos en la experiencia de desarrollo, con esto me refiero a las facilidades que tiene el desarrollador de llevar su app a producción y automatizar tareas, Meteor es un campeón.

Es inevitable otra ola de adiós. ¿Recuerdas Grunt, Bower y Yeoman? ¡Adiós! No hace falta nada de eso. Véamoslo en la siguiente sección:

Instalación de MeteorJS

Nota: Recomiendo hagas la parte práctica luego de leer el artículo en su totalidad. Lo he creado de tal forma que veas el panorama completo. Te lo aseguro, aprenderás más así que haciendo las cosas a medida que vas leyendo.

El framework está disponible para Windows y Gnu/Linux. En Windows solo tienes que descargar un binario y ejecutarlo. En Gnu/Linux debes hacer esto desde tu consola:

curl http://install.meteor.com | sh

Listo! Con esto tienes Meteor instalado y listo para usar. Si por casualidad tienes problemas con el comando anterior, ya sea porque estás detrás de un proxy o Chuck Norris está hackeando tu PC, sigue estos pasos para realizar la instalación de forma manual.

Nota que no es necesario tener instalado en tu sistema NodeJS, NPM ni nada por el estilo. El comando anterior instala Meteor con todas sus dependencias en la carpeta .meteor de tu HOME (en el caso de Windows en C:\Users\usuario\AppData\Local\.meteor), este no necesita de ninguna dependencia externa. +1

Tu primera aplicación MeteorJS

El encabezado anterior es el título de un libro, te sugiero lo busques y lo leas, es muy intuitivo. Estos son los pasos para crear una app en MeteorJS:

meteor create nombreDeLaApp 
cd nombreDeLaApp
meteor

Listo!!! Con las instrucciones anteriores realizadas abre tu navegador favorito en http://localhost:3000, deberás ver algo como esto:

Fresh meteor application

Con los pasos anteriores realizados tienes:

  1. Un servidor web ejecutándo tu app en el puerto 3000, cortesía NodeJS.
  2. Cada vez que modifiques un fichero CSS los cambios se ven instantaneamente sin tener que refrescar el navegador.
  3. Cada vez que modifques un fichero HTML y JS del lado del cliente, automáticamente se actualiza el navegador para reflejar los cambios.
  4. Cada vez que modifiques un fichero JS del lado del servidor, automáticamente se reinicia el servidor web y, si detecta que es necesario, actualiza además el navegador para reflejar los cambios detectados.

El proyecto creado consta de tres ficheros: index.html, index.js y style.css. Si pones ambas ventanas en paralelo: el navegador y tu editor de código y modificas el fichero CSS, por ejemplo, agregándole al body un fondo rojo: body { background:red }, verás que el cambio es instantáneo al salvar los cambios.

Los puntos tres y cuatro hablan sobre código del lado del cliente y del servidor ¿Cómo identificar qué código se ejecuta en qué lugar?

Estructura de ficheros del proyecto

La app que creé no presenta ninguna estructura de carpetas, solo son tres ficheros en la raíz del proyecto. En este caso el código de estos ficheros se ejecutará en ambos lados: el cliente y el servidor a la vez.

Por supuesto, el código HTML y CSS no tienen ningún significado para el lado del servidor, por eso me refiero al código albergado en index.js.

Meteor ejecutará el código en ambos lados por defecto si no se le especifica lo contrario, tal y como sucede en index.js, donde explícitamente se está diciendo: ¡Meteor, este código quiero que lo ejecutes solo del lado del cliente, y este otro sólo del lado del servidor!

Las instrucciones encargadas de lograr lo anterior son Meteor.isClient y Meteor.isServer, por lo que debes a estas alturas percatarte que existe un objeto global llamado Meteor que es muy útil y está disponible en ambas partes.

Otra pregunta que te debe venir a la mente ahora mismo: ¿En mi aplicación tendré que tener las condicionales anteriores en todos lados para garantizar la ejecución de código en una, otra o ambas partes? NO. En Meteor todo está pensado.

Vamos a cambiar la estructura del proyecto de manera tal que podamos borrar todas las condicionales isClient e isServer del fichero index.js:

+ client/
  - index.html
  - style.css
  - index.js
+  server/
  - aleatorio.js
+ public/
  - logo.png
  - background.png
  - favicon.ico    
  + fontAwesome/
  ...
+ mis_colecciones/
  - entrada.js
  - comentario.js

Observa que el fichero aleatorio.js no existía, lo creé yo y lo copié hacia la carpeta server para mostrarte que:

  1. Todo lo que está en esta carpeta se ejecutará SOLO del lado del servidor.
  2. Todo lo que está en la carpeta client se ejecutará SOLO del lado del cliente.
  3. En la carpeta public pondrás todos tus assets: imágenes, íconos, fuentes.
  4. El código fuera de esta estructura se ejecutará en ambas partes. Así, lo que escribas en los ficheros dentro de la carpeta mis_colecciones estará accesible tanto desde el fichero index.js en el cliente, como del fichero aleatorio.js en el servidor, pudiendo así realizar diferentes tareas, en diferentes entornos con el mismo código (he aquí una aplicación isomórfica).

¿Qué necesito tener en ambos entornos en mi aplicación? Pregunta usted.

Entre otras cosas, las Colecciones. Verás, por defecto, como sistema gestor de bases de datos, Meteor utiliza MongoDB. Sí, el mismo que utilizas en tus aplicaciones MEAN, si vienes de ese entorno.

Para cada proyecto Meteor crea una carpeta .meteor que no puedes borrar, pues dentro alberga metadatos asociados a tu aplicación junto con la base de datos, la cual no tienes que crear a mano, él la crea e inicializa por ti al ejecutar el comando meteor.

No te voy a enredar mucho con el tema de las colecciones, por ahora solo confórmate con saber que son los objetos que permiten la comunicación con la base de datos, como las Entidades en las aplicaiones Symfony o el servicio $http en AngularJS.

Imagina que quieres guardar un post, que tiene título y descripción. Estas son las tareas que tendrás que hacer (a grandes rasgos) para guardarlo:

  • Fichero entrada.js (ambos entornos)
Mis_posts = new Meteor.Collection('posts');
  • Fichero index.js (solo el cliente):
Mis_posts.insert({
  titulo      : "Meteor es lo máximo",
  descripcion : "Dos días con Meteor y creé una app increíble..."
});
  • Fichero aleatorio.js (solo el servidor):
Mis_posts.allow({
  insert : function(){ return true;  },
  update : function(){ return false; },
  delete : function(){ return false; }
});

Observa cómo el objeto Mis_posts se instanció una sola vez y se utilizó en ambas partes, el cliente y el servidor.

Para darte otro punto de vista de cómo se puede sacar provecho de esta arquitectura, imagina que cuando el usuario envía un formulario debes validar que la longitud del título no exceda los 100 caracteres y que la longitud de la descripción no exceda los 500 caracteres, pero necesitas hacer la validación en ambas partes.

Crea un fichero utiles.js dentro de mis_colecciones y declara una función de esta forma:

this.minLength = function(str , limit){
  return str.length < limit;
}

Listo! se declara una vez y se utiliza en ambos lados.

En este momento puedes estar confundido sobre la importancia de esta arquitectura, pues aparentemente no lo notas porque estás utilizando JavaScript en el servidor y en el cliente.

Para verlo mejor, imagina que en un área especial declaraste la función minLength con JavaScript y que en el lado del servidor, en la carpeta server programas en PHP.

Bien, gracias a la declaración de minLength en esa “área especial”, ya existe una función PHP con el mismo nombre, lista para utilizar en tu código. La analogía sería algo como esto:

// server/aleatorio.php

$el_post = $Mis_posts.findOne({ _id : '12345' }); //un post random

$esTituloValido = minLength($el_post->titulo , 100);
$esDescValida   = minLength($el_post->descripcion, 500);

Uff, qué invento, pero creo que muestra mi punto a la perfección.

Las plantillas

Meteor trabaja con el concepto de plantilla. Cada template tiene asociado un fichero JavaScript cuyo código se limita al scope de dicho template.

Por ejemplo, en el fichero index.html se crea la plantilla hello:

<template name="hello">
<p>
  Has dado click <button> aquí </button> {{ cantidad }} veces. 
</p>
<template>

En el fichero index.js puedes acceder a los eventos de la plantilla y registrar uno que ejecute una acción cuando se de clic en el botón:

Template.hello.events({
  "click button" : function(){
    console.log('Diste clic en el botón');
  }
});

Esta es una forma peculiar de trabajo. Observa cómo los eventos se le asignan al template en forma de pares clave-valor, donde la clave está formada por el evento y un selector al estilo jQuery, el cual denota el elemento HTML al que se le asignará el evento.

En el ejemplo, el evento se registra al único botón que tiene el template. ¿Y si existiera otro botón dentro de la app, pero afuera de este template? No tendría efecto. Como mencioné anteriormente, tal evento fue registrado expresamente para el/los botones del template hello.

Por último, ¿qué es esa “variable” en el HTML llamada cantidad? Es un helper o ayudante. El sistema de trabajo aquí es que tal helper está asociado a una función JavaScript que devuelve un valor y, Spacebars, el motor de plantillas de Meteor, evalúa tal función y muestra el resultado en la vista:

// index.js
Template.hello.helpers({
  "cantidad" : function(){
    return 1;
  }
});

En este caso Spacebars siempre renderizará el valor 1, pues es lo que retornará siempre la función asociada al helper cantidad. ¿Cómo haces para que cuando se le de clic al botón se incremente cantidad? Pregunta Usted.

Compartiendo variables

Existe una variable global en el cliente que se llama Session, en pocas palabras, es un diccionario que te permite guardar valores y son accesibles desde cualquier lugar de tu código cliente, por tanto, en este caso, podremos compartir un valor entre el helper y el evento para que interactúen entre sí:

Template.hello.helpers({
  "cantidad" : function(){ 
    return Session.get('un_valor') || 0; 
  }
});

Template.hello.events({
  "click button" : function(){
    var actual = Session.get('un_valor') || 0;
    actual += 1;
    Session.set('un_valor' , actual);
  }
});

Dicho con palabras: el helper cantidad lo único que hace es retornar lo que tiene Session en su entrada un_valor, 0 en caso de no estar definida la variable (estado inicial).

Al dar clic en el botón, se obtiene dicha variable, se incrementa, y luego se asigna nuevamente a la propia entrada un_valor.

Lo elegante aquí es que en la vista, Spacebars se encarga de cambiar el valor de cantidad automáticamente, similar al two-way databinding de AngularJS. O sea, él re-evalúa la función asociada al helper cada vez que la variable Session cambia en cualquier otro lugar de la aplicación.

Esto sucede así porque Session es una fuente de datos reactiva, al igual que las colecciones. He aquí la grandeza del framework. Con pocas líneas de código, creas aplicaciones en tiempo real por defecto.

Imagina que tienes dos navegadores abiertos y la misma app ejecutándose en ambos. Atendiendo al ejemplo de insertar un post en la base de datos, verías en una ventana cómo aparece de forma automática dicho post, luego de hacer submit desde la otra ventana.

Sistema de paquetes

Por último, mostrarte el killer feature del framework: plug and play con paquetes de terceros.

La aplicación ahora no hace nada interesante. Déjame enseñarte en una línea de código cómo crear un completo sistema de autenticación y registro de usuarios basado en tokens. Dentro de la carpeta del proyecto, ejecuta en la consola:

meteor add accounts-base accounts-ui accounts-password

Ve al fichero index.html y fuera de la definición del template hello incluye el siguiente template:

{{> loginButtons }}

LISTO!!! Te puedes crear un usuario en la aplicación, autenticarte, cerrar sessión y cambiar contraseña.

Todo esto se logró con solo inyectar un template luego de instalados los tres paquetes anteriores. Increíble!

Despliegue

Por último, te cuento que este pequeño demo lo podemos poner online ahora mismo, gracias al servicio de hosting gratuito que ofrece el equipo de Meteor (MDG, siglas en ingés de Meteor Development Group). Y lo hacemos así:

meteor deploy mca.meteor.com

Deléitate accediendo a la dirección de tu demo y accede al código generado con Control + U. Te sorprenderá lo que verás.

Conclusiones

Y solo rasqué la punta del Iceberg. A pesar de la longitud del artículo, creo que valió la pena llegaras hasta aquí.

Te mostré los conceptos fundamentales del framework: reactivo por defecto, JavaScript como único lenguaje, compartir código entre los entornos cliente/servidor, el sistema de trabajo con las plantillas, los helpers, los eventos y el sistema de paquetes para agregar funcionalidades a tu app de forma rápida.

Creo que es exitante esta tecnología. Como todo lo hecho por humanos, no es perfecto, y te debes acostumbrar a su peculiar modo de trabajo, que como te mostré es muy sencillo de aprender.

El código del demo lo puedes ver en Github. No obstante lo puedes crear tú mismo pues es casi idéntico a la app que se crea por defecto cuando inicializas un proyecto nuevo con meteor create. Solo debes seguir los pasos de la sección “Sistema de paquetes” para completarlo.

A continuación te brindo algunos enlaces útiles para incrementar tu arsenal:

  1. MyCyberAcademy :)
  2. Sitio oficial de Meteor
  3. Meteor Hacks
  4. El Crater
  5. Repositorio de paquetes: La Atmósfera

Si ya conoces Meteor, cuéntame, ¿cómo te ha ido? Si deseas algún tutorial en específico o tienes dudas al respecto, plásmalo en los comentarios y enseguida estoy contigo.

  • Norberto Cabrol

    Muy bien explicado, me aclaro algunas dudas. Respecto a “Si deseas algún tutorial en específico”, podras hacer alguno con postgresql, porque intente pero no voy ni para ni para adelante,(ademas no manejo muy bien el ingles) .Probe con https://atmospherejs.com/meteorsteam/meteor-postgres, pero no lo puedo hacer funcionar. Me gustaria que hagas uno con BD postgres, no necesariamente con el paquete que use yo. Tenia ganas de ver algo con alasql, que creo te deja hacer mas cosas, pero lo dejo a tu criterio. Gracias

  • camilo florez

    Hola…. veo que manejas bien meteor… para mi ha sido muy dificil la subida al servidor…. ya que yo usualmete usaba http://ftp…. que me recomiendas que no sea tan complejo????