Migré de Svelte a EmberJS y Fue Para Bien

El año pasado empecé un proyecto en el que aprendí sobre la API de Vídeo de Twilio y a usar una nueva librería JavaScript llamada Svelte. Sin embargo, por diferentes situaciones y problemas necesitaba cambiar Svelte por otro framework o librería.

Creí que me iba a estancar y el proyecto no lo podría seguir pero al final sí fue posible, en poco tiempo y sin quedarme calvo. En este artículo contaré al respecto de este proceso migratorio de Svelte a EmberJS.

La idea que tenía una idea era crear un servicio para hacer vídeo llamadas desde un navegador web del mismo modo que funcionan otros servicios como Whereby, Team.Video, Join.me.

Investigué un tiempo y crear la infraestructura para soportar ese tipo de desarrollo era un proyecto por sí solo. Entonces decidí que había que usar un servicio que ya me diera la capacidad de crear una llamada/vídeo llamada desde un navegador web.

En esa mini investigación aparecieron algunos servicios interesantes con una muy buena oferta pero poco asequibles para alguien sin presupuesto, como este autor. La mejor opción entonces pintaba en Twilio y su capa gratuita para probar y su bajo coste cuando se decida pasar a una cuenta paga.

¿React o No React?

Ya había probado en varias ocasiones, en proyectos pequeños, React. Me pareció una buena alternativa a otras librerías como jQuery o frameworks como Angular, Backbone(?).

Incluso hice una aplicación que integraba la API de Lugares de Google y tuve dificultades variadas por las muchas opciones y por el manejo del estado global que en ocasiones parece que solo se pudiera con Redux.

En fin, hablé con un amigo y me presentó un nuevo proyecto, muy interesante llamado Svelte. Svelte no es un framework ni una librería. Se proclama así mismo como un compilador que no es importante pero sí una gran diferencia.

Se supone que Svelte en verdad sí trabaja el modelo o patrón de Reactividad que en resumen implica que una entidad debe reaccionar, de manera automática, a los cambios que sufra en diferentes partes de la aplicación. Puedes leer más al respecto en la página web RxJS.

Al final, opté por Svelte y me di a la labor de hacer la aplicación para hacer vídeo llamadas desde un navegador web.

Svelteando

Usar Svelte fue muy entretenido. Una forma diferente e incluso más sencilla que la forma de programación que nos trae React, Angular o Vue. Una ola de aire fresco. En todo caso tuvo sus propios problemas.

Primero que nada, dio complique para configurar el proyecto usando una herramienta llamada Rollup al momento de querer configurar las herramientas de linting.

Otra cosa que sucedió, más que nada por la novedad del proyecto, fue montarla un Now.sh. Al final lo logré pero no sin sufrir un rato.

Algo que me gusto mucho de Svelte es que viene con su propia tienda la cual te ayuda a tener estado global en la aplicación. Cosa diferente pasa en React que te tocaría usar el Context(con sus limitaciones) o Redux(que al parecer su caso de uso no es nada claro).

Otra característica buena de Svelte es que los estilos son de ámbito local al componente. O sea que no es necesario usar cosas como CSS Modules, o librerías de CSS-in-JS.

En general, me gustó escribir código en Svelte aunque lastimosamente es un producto nuevo, con una popularidad apenas creciente lo que significa que cualquier librería que salga para apoyar cosas en Svelte sería una seria dependencia para mí proyecto.

Finalmente, logré crear la aplicación en su versión más básica. Hacía lo necesario para establecer una vídeo llamada usando el navegador web aunque carecía mucho de experiencia de usuario.

Puedes ver esta versión de Intrati en este enlace.

Si iba bien, ¿por qué migrar?

Cuando empezamos el aislamiento preventivo por el COVID-19, decidí que era el momento de echar adelante Intrati(nombre del proyecto) aprovechando que podía trabajar desde casa y tener un poco más de tiempo libre por no estar transportándome al trabajo.

Decidí tomar un servicio existente como guía para proseguir siguiendo su ejemplo, un servicio para tomar como benchmark. Elegí Whereby(antes Appear.in). Su interfaz me parece muy bonita y el flujo para crear una sala es muy bueno también.

Siendo así, bosquejé el flujo que quería para la aplicación y vaya sorpresa que me doy cuando veo que cambiarían muchas cosas y que tal vez Svelte no sería capaz de permitirme hacerlas.

Nuevo flujo para Intrati

¿Qué tenía que hacer? Buscar un enrutador (router) para Svelte. Encontré pero no funcionaron con la versión de Svelte que usaba junto con la configuración con Webpack.

Estos fueron los routers que encontré:

Hubo varias situaciones con los que encontré.

El de Daniel Sharkov, tuvo sus últimas actualizaciones en 2019. También abrí un issue porque obtuve este error

ERROR in ./node_modules/@danielsharkov/svelte-router/src/RouterViewport.svelte 1:1
Module parse failed: Unexpected character '#' (1:1)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> {#if componentNotChanged}
| 	<div
| 	in:transition={{ duration, easing, delay }}
 @ ./node_modules/@danielsharkov/svelte-router/src/index.js 3:0-67 3:0-67
 @ ./src/App.svelte
 @ ./src/main.js
 @ multi ./src/main.js

El router de Wmzy dice que es un fork del de Vue y eso no me dio buena espina. Con el router de Jorge Gorka también enfrente el mismo problema que con el de Daniel Sharkov.

Desesperanzado, le pregunté a un colega sobre una librería que me pudiera ayudar a tener enrutamiento y alto nivel de productividad como React PERO no quería usar React.

Los motivos por los cuales no quise React son para otro artículo.

Me recomendó Ember y explícitamente la versión Octane. El 31 de Marzo empecé la migración y el día 15 de Abril la completé con el flujo y las mismas características.

Embereando

Primer commit

Empecé con mucha expectativa de lo que encontraría y esperando no tener que pasar luego a otro framework. Si hubiese tenido que hacerlo, habría abandonado el proyecto. Afortunadamente, no fue así.

Vale aclarar que Ember Octane viene a ser un nuevo cambio en cómo funciona el framework. Como soy nuevo no tengo ningún tipo de sesgo. Soy un chico nuevo en una nueva versión del framework. No problemo, brother.

En todo caso, no todo fue flores. Tuve una situación que me dejó bien preocupado una noche y aunque le encontré su solución vaya susto me llevé.

Lo primero antes de crear el primer componente fue tener muy claro el flujo de todo lo que había hecho en la versión en Svelte. En Svelte, en un mismo componente gestionaba todo con respecto a crear y conectarse a una sala de llamada. Usando Ember y con el nuevo flujo tenía que saber que era necesario puntualmente para poder mover el código.

Resalto que viniendo de Ruby on Rails, usar Ember fue una experiencia muy agradable ya que hay muchas cosas listas para usarse y no tener que pensar en buscar, configurar, hacer:

  • Estructura de carpetas
  • Rutas
  • Servicios para estado global
  • Lenguaje de código embebido, Handlebars
  • Una interfaz de comandos para generar archivos, Ember CLI

Una maravilla.

Manos a la Obra

Para aprender el framework no recurrí a un curso o vídeo tutorial sino que leí la introducción y el tutorial que se encuentran en las guías de Ember. No contaba con mucho tiempo y lo mejor era ir a la fuente.

Si bien por momentos algunos conceptos o puntos me quedaron poco claros, a medida que fui haciendo la aplicación todo iba conectando. Por esa razón también me armé un documento con la conclusiones a partir de los apuntes que hacía en Trello y así aterrizar mejor los conocimientos recién adquiridos.

En Ember, un componente generalmente empezará por una definición en el archivo router.js, acompañado de un componente y una clase en app/components. Veamos un ejemplo.

Definición en router.js

import EmberRouter from '@ember/routing/router';
import config from './config/environment';

export default class Router extends EmberRouter {
  location = config.locationType;
  rootURL = config.rootURL;
}

Router.map(function() {
  this.route('room-form', { path: '/' })
});

Componente y clase Glimmer.

// app/components/room-form.hbs 
<form {{on "submit" this.submit}}>
  <input {{on "input" this.updateRoomName}} placeholder="Room name" />
  <button>Create Room</button>
</form>

// app/components/room-form.js
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';

export default class RoomFormComponent extends Component {
  @tracked roomName;

  @service router;
  @service('room-name') roomNameService;

  @action
  updateRoomName(event) {
    this.roomName = event.target.value;
  }

  @action
  submit(event) {
    event.preventDefault();

    if (this.roomName) {
      this.roomNameService.setName(this.roomName);
      this.router.transitionTo('create-room', this.roomName);
    }
  }
}

En la clase Glimmer podemos ver el uso del decorador @tracked y @service. Con @tracked se define una propiedad que va a ser observada cuando cambie y así poder repintar el componente y con @service con se indica una clase global a la aplicación. Una forma de tener estado global.

Así, poco a poco, fui logrando la migración. Con la ayuda de algunos sitios y repositorios. Leyendo al detalle para tener pistas de cosas que no tenía ni idea de cómo eran.

Otro tema confuso pero con paciencia, lecturas y pruebas, entendí cómo funciona y es el ciclo de vida de los componentes. Cuando se usa Ember Octane la situación cambia.

En Ember Classic, el ciclo de vida se maneja desde la clase JavaScript. Ahora, en Octane, se maneja distinto. Pero mejor veamos algo de código.

En Ember Classic

// app/components/component.hbs
<canvas id="my-canvas"></canvas>

// app/components/component.js
import Component from '@ember/component';

export default Component.extend({
    didInsertElement() {
        // query for the canvas by id and create a graph
    }
});

En Octane se usan los Element Modifiers mediante un paquete aparte. La idea es que se defina el ciclo y la función en la clase, solo se defina la función en la clase y en el componente se indique el modificador a usar. Así:

// app/components/component.hbs
<canvas id="my-canvas" {{did-insert this.createGraph}}></canvas>

// app/components/component.js
import Component from '@glimmer/component';
import { action } from '@ember/object';

export default class SomeComponent extends Component {
  @action
  createGraph(element) {
    // you already have the canvas element,
    // now make the graph!
  }
}

Me pareció un poco raro pero luego se me hizo cómodo ya que la clase solo tiene funciones relacionadas con su funcionalidad y nada más. En el proyecto Ember Render Modifiers explican un poco y en las guías también podemos ver un ejemplo de cómo usarlos.

El Susto

Es claro que estoy usando en el proyecto la API de Twilio Video. En el proyecto Svelte usé el paquete twilio-video y me funcionó sin problemas. Sin embargo, en Ember me encontré con este error:

TypeError: 'get peerIdentity' called on an object that does not implement interface RTCPeerConnection.

¡Ocurría cuando importaba la librería en cualquier componente!

Fue un momento preocupante porque ¿de qué otra forma podía usar la librería? ¿tendría que hacer mi implementación propia? Hacer algo propio estaba fuera del mapa así que a buscar se dijo.

Encontré dos issues (1) (2) que mencionaban el caso. Si bien en uno de ellos la conversación indicaba que se había resuelto, en mí caso no fue así. No importaba que versión del paquete usara en Ember no funcionaba. En cambio en la versión hecha en Svelte sí.

Muy para fortuna mía, el paquete también lo publican en un CDN y con ese aunque sigue presentando el error, no me da problemas con los componentes. Incluso la aplicación funciona como si nada, audio y vídeo.

Hice la pregunta sobre este error en DEV pero hasta el momento nadie ha respondido (ignorado xD) y no he encontrado un caso concreto como el mío.

Conclusión

Pasar de Svelte a EmberJS fue una gran experiencia. Yo no soy desarrollador frontend pero haber usado Svelte fue muy bacano y usar EmberJS también lo es.

En mí poca experiencia puedo recomendar ambos proyectos pero toca leer bien la documentación de ambos, hacer pruebas con ambos y tomar una decisión concienzuda según los requerimientos que se tengan.

Recursos Valiosos

Enlaces que me ayudaron a encontrar respuestas a mis dudas cuando la documentación no fue suficiente y parecía no tener esperanza en internet.

Autor: cesc1989

Ingeniero de Sistemas que le gusta escribir y compartir sobre recursos que considera útiles, además que le gusta leer manga y ver anime.

2 comentarios en “Migré de Svelte a EmberJS y Fue Para Bien”

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios .