Introducción

Antes de nada, sería pertinente comenzar por el por qué del grupo. Recientemente nos planteamos la certificación de Symfony para los desarrolladores de nuestra empresa, y en la documentación de los pasos a seguir, vimos que desde la página de academia de Sensiolabs tenían con frecuencia cursos y talleres de preparación, en Francia, Londres y Alemania. Cuando les preguntamos sobre la posibilidad de realizar la formación aquí en España al igual que en otros países, la respuesta que obtuvimos es que no hay tanta gente que lo solicite, por lo que no se lo plantean.

Queremos conseguir que todos los desarrolladores de Symfony que lo deseemos tengamos la posibilidad de tener un espacio en el que discutir inquietudes, apoyarnos y mejorar, sin tener que esperar a grandes eventos anuales como el deSymfony o Codemotion para ello, y por esas razones, creamos el grupo de Symfony.

Un poco de contexto

El pasado jueves tuvimos la suerte de poder organizar nuestro primer meetup, «Los retos de la comunidad Symfony«, y desde aquí quiero agradecerles a todos los asistentes que nos brindaron su tiempo. Desde el principio queríamos desmarcarnos de la clásica master class, que aunque no tiene nada de malo, no se ajustaba tanto a nuestra idea de generar comunidad en torno a Symfony, queríamos romper el hielo entre los participantes (que no oyentes), y queríamos debate.

 

Los retos de la comunidad Symfony

Como adelantaba antes, queríamos que el meetup fuera algo más comunicativo, que todos los presentes aportasen su visión, mostrasen sus inquietudes y pudieran ser ayudados. Pensamos usar Lean Coffee como método para obtener, priorizar y tratar temas de conversación que todos deseáramos discutir.

Para el que desconozca cómo funciona lean coffee, está dividido en tres grandes bloques de los que hicimos uso de la siguiente manera:

  • Obtención de temas: el primer paso era saber los temas sobre los que querían hablar los participantes. Para ello, planteamos las preguntas «¿Qué quiero aprender?», «¿Qué puedo aportar?», «Dudas existenciales». Repartimos una serie de post-its sobre los que escribir los temas que quisieran tratar y que posteriormente se colocaron bajo cada pregunta en un muro. Para tener mejor visibilidad de todo, dedicamos unos instantes en agrupar los temas similares o los que directamente eran iguales.
  • Priorización: una vez teníamos todos los temas, los priorizamos para hablar sobre los que pudiéramos dentro del tiempo que teníamos disponible, repartimos entre cada uno 5 puntos que usarían para votar los temas que les resultaran más interesantes, y de esa manera, ordenarlos y detectar los prioritarios.
  • Discusión: establecimos un timebox de 5 minutos para hablar por tema, llegando a la posibilidad de prorrogarlos con una votación hasta que todos pensásemos que el tema no daba más de sí.

Temas tratados

Tras realizar los primeros dos pasos del Lean Coffee, se nos quedó el siguiente muro con los temas que trataríamos en la siguiente hora:

Muro de temas a tratar sacados en el Lean Coffee

Muro del Lean Coffee

Como podéis ver, uno de las grandes preocupaciones que asaltaban a los participantes es la gestión de los assets del frontal de nuestras aplicaciones, cómo hacemos uso de Gulp y/o Webpack Encore. Este tema se llevo gran parte del tiempo asignado del meetup.

Otro tema que tratamos fueron sobre la forma en la que cada uno realizaba la subida a producción de los assets, el debate estaba en generarlos en local y copiarlos arriba, o generarlos directamente arriba. Cada uno defendió sus ventajas e inconvenientes dependiendo de lo que acostumbra a hacer.

Siguiendo con los frontales de nuestras aplicación, surgió la visión de cómo Symfony estaba alejándose de la alimentación del frontal para centrarse en el lado back de las aplicaciones, dando paso así a los clientes desarrollados con frameworks javascripts como React, Angular o Vue. Dedicamos un rato a discutir nuestras experiencias con cada uno, cómo realizamos las comunicaciones entre cada parte, y el manejo de datos sensibles de usuarios.

El último tema que nos dio tiempo a tratar fue el de la gestión de formularios en Symfony, la validación, creación de Constrains. Cada uno expusimos cómo trabajamos con los formularios.

Se quedaron fuera temas interesantes como Certificación, los cambios que se acercan con Symfony 4 o testing, uso de servicios para la lógica de la aplicación frente a custom events.

Cierre

Una vez más, me gustaría desde aquí mandar un saludo a todas las personas que quisieron y pudieron venir, esperamos que les resultase una experiencia enriquecedora y quieran repetir en el próximo. Por otro lado, a todos los que os interese apuntaros al grupo y estar al tanto de los próximos eventos que organicemos, dejo el enlace al registro en el grupo de Meetup.

Esta es la narración de una historia de amor. Breve, intensa y que terminó de forma brusca, contra un muro.

Todo empezó con un encuentro tan casual como inevitable.

Por un lado un estudio digital buscando una herramienta que hiciese el desarrollo de aplicaciones web más eficaz, fiable y escalabale, y que abriese la puerta a exportar ese conocimiento para generar aplicaciones móviles.

Por otro, con uno de tantos frameworks de JavaScript ofreciéndose cual sandía abierta en la red de redes (saludos a los señores periodistas digitales de los mass media).

 

Qué inocente parece, tan sencillo, pulcro y fácil de instalar.

Dentro de las opciones disponibles, estaban los nombres habituales: Angular, React, Ember, Backbone

Pero uno llevaba desde hacía un tiempo llamando poderosamente la atención de todo aquel que se adentraba en este mundo: Vue.

Sus virtudes eran obvias: ligereza, rapidez, versatilidad y sobre todo una curva de aprendizaje de lo más agradable, en la que con un conocimiento previo de HTML/CSS/JavaScript podías obtener resultados muy vistosos de forma casi inmediata.

Para un estudio modesto, en el que la inversión en I+D no puede competir con la de grandes corporaciones al estilo Weyland-Yutani, era una verdadera tentación, imposible de resistir.

El tiempo es dinero, y si un 89% de los desarrolladores decían en 2016 estar tan satisfechos con él como para volver a usarlo, no había más que pensar.

Así, la relación nació llena de ilusión, con un primer acercamiento a la reescritura del Rand-o-matic muy rápida y vistosa.

Versión 0.1 del Rand-o-matic Vueizado. Jusqu’ici tout va bien.

El Tocstrap, como buen amigo, echó una mano en ello, y todo parecía ir sobre ruedas, pero ya sabemos que al principio la pasión lo tapa todo.

El problema vino, como tantas otras veces, con una tercera persona.

Llegó la hora del cambio, de dar el siguiente paso y comprometerse a ser capaces de hacer aplicaciones móviles.

Deberíamos haber empezado a sospechar cuando la elección del framework que debía ayudarnos a conseguirlo no se mostraba con claridad ¿Weex? ¿Cordova? ¿Phonegap? ¿Quasar? ¿Framework7? ¿Ionic? Cada uno tenías sus ventajas e inconvenientes, algunos ya los conocíamos y no nos convencían, otros estaban en un estado de desarrollo demasiado temprano, otros no estaban pensados para funcionar con Vue sino con Angular, otros eran de Adobe…

Con las dudas propias de quien da un like en Tinder a alguien que solo tiene una foto, optamos por Weex. Parecía la opción menos mala dentro de las posibles.

Weex.

Recordad ese nombre. Anotadlo junto al de Summer.

Los problemas empezaron a manifestarse desde el principio, una vez metido entre medias de la relación.

El hecho de tratar de hacerlo funcionar en un entorno Windows no hizo sino agravarlos ¿Pero qué clase de futuro podía esperarnos si no era capaz de resistir una prueba tan dura? Variables de entorno, actualización de Node, instalación de Android Studio, JDK y drivers del dispositivo, añadido de la plataforma de Android… todo lo que en el ecosistema Web App había sido fluidez y avance, aquí se volvía barricadas, retrocesos y desesperación.

Cuando creíamos haber logrado por fin deshacer el nudo, se volvía a enmarañar y había que volver a empezar.

Y para colmo, al ser un proyecto de Alibaba y estar poco extendido aún, gran parte de las dudas había que resolverlas en chino ¿Os imagináis Stack Overflow en chino en vuestro día a día? Intentadlo.

Gracias chicos, pruebo lo que decís y os cuento

El golpe definitivo vino cuando tuvimos que añadir estilos: instalación de paquetes de node (style-loader, css-loader), intentos de importación de ficheros externos, como si de un componente se tratase, intentos de carga asociados a <style>, intentos de carga de todo nuestro Tocstrap incrustado inline. Nada, que no había forma de que aquello cogiese los estilos. Estábamos intentando forzar algo que había nacido fracasado.

Y la culpa fue nuestra, por fiarnos. Por no leer la documentación y ver esto:

The CSS standard may support a lot of selectors, but now weex only support single-class selector.

The CSS standard can support many types of length units, but now weex only support pixel, and the px unit could be ignored, you can write number directly.

The styles of Weex cannot be inherited to children elements, this is different to the CSS standard, such as color and font-size.

The CSS standard contains a lot of styles, but weex only sopport few styles which include layouts such as box model, flexbox, positions.

¿En serio?

¿Y nos dices ahora que estás casado y tienes hijos?

¿De verdad no crees que es algo que deberías poner en tu página home para que, si empiezo algo contigo, sepa a que atenerme?

No sé, algo así como en letras mayúsculas, a tamaño 70 y en #f00. Está bien, no podíamos echarle la culpar, la información estaba ahí, algo escondida, pero estaba. Y nuestra obligación era habernos informado antes de tirarnos a la piscina del I+D.

No era momento de buscar culpables, sino soluciones.

Bien, bien… lo que se dice bien… ahora mismo no me caes mucho

Así que hicimos lo que hemos aprendido en tantas películas: cortar.

Asumir que aquello no iba a ningún lado, que no estábamos hechos el uno para el otro. Ta vez en dos años hubiese tenido más sentido, pero no ahora, nos habíamos equivocado con el momento.

Hicimos limpieza, nos quedamos con la parte de Vue que aún podía salvarse para hacer Web Apps de forma rápida y ligera, y nos pusimos a buscar otra pareja con la que seguir recorriendo al camino.

¿Cuál fue nuestra elección? Solo adelantaremos que, como decía Hitchcock, «en caso de duda lo mejor es refugiarse en lo conocido«.

 

 

 

 

 

Uno de los grandes “problemas” que nos encontramos en Elemento115 a la hora de hacer despliegues rápidos en un corto lapso de tiempo es, precisamente, cómo mostrar estos cambios al usuario final. Me explico.

Nuestro flujo de trabajo nos permite hacer cambios rápidos de diseño y funcionalidad en la parte cliente, por lo que podemos llegar a desplegar una aplicación bastantes veces al día. ¿Nuestra némesis? La caché. Ese elemento que ayuda tanto a que nuestros desarrollos carguen a una velocidad óptima también provoca que el usuario no vea los cambios de manera inmediata.

Para solucionarlo tenemos varias opciones, como dejar los archivos servidos expiren en tiempos relativamente cortos (en nuestro caso debería ser de horas) o forzar el de nuevo la bajada haciendo que expire manualmente. Ninguna de estas opciones nos convence. Hasta Symfony 2.8 utilizábamos Assetic para la gestión de assets. Este componente estaba integrado en Symfony, era fácil de utilizar y además nos solucionaba este problema con un sistema simple, el versionado de archivos. Pero, y siempre hay un pero, Assetic pasó a estar deprecado en Symfony 2.8.

 

Gulp al rescate.

¿Cómo afrontamos esto? Fácil, nos subimos al barco de Gulp. La integración con Symfony fue sencilla y además ganamos tiempo a la hora de hacer los despliegues gracias a que Gulp resultaba ser más rápido que Assetic a la hora de procesar los assets. Pero (otra vez) perdimos la facilidad con la que versionabamos los archivos, ya que con Assetic solo era necesario cambiar el número de versión en un archivo de configuración.

No íbamos a hacer de esto un drama, así que nos pusimos manos a la obra para solucionar el tema del versionado de archivos de la manera más limpia y automatizada posible. Queríamos que, cada vez que un archivo, ya sea CSS o JS, fuera modificado, se actualizase la versión de este para servir el nuevo contenido a los usuarios de manera inmediata. Para ello integramos gulp-rev, un paquete de Gulp que se encarga de añadir un hash a los archivos que necesitamos versionar. Un ejemplo práctico con archivos Sass/Css:


gulp.task('public-clean-assets', function() {
    return gulp.src(['web/public/css/*.css', 'web/public/**/*.js'], {read: false})
        .pipe(clean({force: true}));
});

gulp.task('public-sass', function() {
    return gulp.src('app/Resources/front/public/scss/*.scss')
        .pipe(sass({includePaths: ['app/Resources/front/public/scss/modules']}))
        .pipe(gulp.dest('app/Resources/front/public/css'))
        .pipe(notify({message: 'PUBLIC SASS OK', onLast: true}));
});
gulp.task('public-styles', ['public-clean-assets', 'public-sass'], function() {
    return gulp.src('app/Resources/front/public/css/**/*.css')
        .pipe(cleancss())
        .pipe(rename({suffix: '.min'}))
	.pipe(rev())
        .pipe(gulp.dest('web/public/css'))
	.pipe(rev.manifest('web/rev-manifest.json', {
            merge: true
        }))
	.pipe(gulp.dest('.'))
        .pipe(notify({message: 'PUBLIC CSS OK', onLast: true}));
});

Aquí actúan básicamente tres tareas de Gulp.

  • Con public-clean-assets limpiamos las carpetas de assets públicos, así no acumulamos un gran numero de archivos sin utilizar.
  • public-sass se encarga de procesar todos los archivos Sass de la aplicación.
  • public-styles se encarga de:
    • “Minificar” el archivo resultante de procesar los archivos Sass.
    • Añadir el sufijo “.min” una vez minificado.
    • Añadir el hash de versión.
    • Mover el archivo resultante a la carpeta pública desde donde se sirve.
    • Añadir una entrada en el rev-manifest.json con el nombre del archivo original y el resultante.

Vale, ya tenemos los archivos listos para servir, ¿como sabe Symfony qué archivos servir?

 

Servir la versión correcta con TwigExtensions.

Vamos a aprovechar el archivo rev-manifest.json para servir los assets correctos. En el archivo rev-manifest.json tenemos, por ejemplo, el siguiente contenido:


{
  "jquery-3-2-1.min.js": "jquery-3-2-1-c9f5aeeca3.min.js",
  "jquery-ui.min.js": "jquery-ui-fdf4d9013c.min.js",
  "main.min.css": "main-6ca53126cb.min.css",
  "main.min.js": "main-32fc16b6cd.min.js"
}

Aquí tenemos la relación entre el archivo que queremos utilizar (main.min.css por ejemplo) y el nombre versionado del archivo (main-32fc16b6cd.min.js). Para hacerlo de manera automática vamos a crear una extensión de Twig que realice este proceso por nosotros:



namespace AppBundle\Twig; 

/** 
 * AssetVersionExtension 
 */ 
class AssetVersionExtension extends \Twig_Extension 
{ 
    private $rootDir; 

    /** 
     * Constructor 
     * 
     * @param string $rootDir
     * @param string $cssDir
     * @param string $jsDir 
     * @param string $pluginsDir 
     */ 
    public function __construct($rootDir, $cssDir, $jsDir, $pluginsDir)
    { 
        $this->rootDir = $rootDir;
        $this->css = $cssDir;
        $this->js = $jsDir;
        $this->plugins = $pluginsDir;
    }

    /**
     * @return array
     */
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('assetVersion', [$this, 'getAssetVersion']),
        );
    }

    /**
     * Retrives the hashed version of the file
     *
     * @param string $filename
     * @param string $fileType  Should match js or css property
     * @param string $subfolder If the file is in a subdirectory it must by especified
     *
     * @return string
     */
    public function getAssetVersion($filename, $fileType, $subfolder = '')
    {
        $manifestPath = $this->rootDir . '/../web/rev-manifest.json';
        if (!file_exists($manifestPath)) {
            throw new \Exception(sprintf('Cannot find manifest file: "%s"', $manifestPath));
        }

        $paths = json_decode(file_get_contents($manifestPath), true);

        if (!isset($paths[$filename])) {
            throw new \Exception(sprintf('There is no file "%s" in the version manifest!', $filename));
        }

        return $this->{$fileType} . $subfolder .  $paths[$filename];
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'asset_version_extension';
    }
}

Declaración del servicio en services.yml:


...
app.twig.assets.version.extension:
    class: AppBundle\Twig\AssetVersionExtension
    arguments: ['%kernel.root_dir%', 'public/css/', 'public/js/', 'public/js/vendor/']
    tags:
        - { name: twig.extension }
...

¿Como funciona la extensión? Básicamente se le pasa como parámetros el nombre original del archivo y el tipo de archivo. Con esto, se encarga de leer desde el rev-manifest.json cual es el archivo correcto a utilizar.

Un ejemplo de uso:


...
< link rel="stylesheet" href="{{ asset('main.min.css'|assetVersion('css')) }}" />
...

Con esto, ya tenemos automatizado el versionado de los assets, además de servir siempre el archivo correspondiente sin necesidad de cambiar ningún tipo de configuración en los despliegues.

Un apunte sobre Gulp y la «sincronicidad».

Gulp, al ser una herramienta escrita puramente en JavaScript, ejecuta las tareas de manera completamente asíncrona. Debido a este comportamiento, es posible que intente hacer un versionado de archivos que aún no existen, por ejemplo cuando aún no se ha terminado de procesar los ficheros Sass.

Esto es fácil de corregir, podemos «forzar» a que Gulp actúe de manera síncrona. Tan solo es necesario pasar como segundo parámetro a la función gulp.task que lo requiera un array de tareas a las que debe esperar antes de ejecutarse. En el caso de la tarea public-styles, esta no se ejecuta hasta que public-clean-assets y public-sass han terminado.

La semana pasada, durante la fase de test de un proyecto que estamos desarrollando, un cliente nos dijo que estaba teniendo problemas para introducir contenidos porque estaba fallando el editor WYSIWYG que estábamos usando, el CKEDITOR integrado en Symfony. Como siempre, los desarrolladores dijimos que «a nosotros nos funcionaba«, y es que era cierto… hasta que dejó de serlo. De forma aparentemente aleatoria, a veces se permitía la introducción de contenidos con normalidad y otras el proceso no se llegaba a realizar por completo: desaparecía el TEXTAREA asociado pero el editor no llegaba a aparecer en su lugar.

El ordenador del desarrollador como centro del universo

En este punto hay que decir que nuestras necesidades iban un poco más allá de las de por defecto, ya que teníamos que limitar la cantidad de encabezados que podía introducir el usuario y al código HTML al que equivalían unas vez renderizados. Además, en la carga inicial de Symfony no conseguíamos que apareciese la configuración deseada (botones de la barra de herramientas y skin), así que terminamos llegando a este código:


var WYSIWYG = {
	init : function() {
		CKEDITOR.config.format_tags = 'p;h1;h2;h3';
		CKEDITOR.config.format_h1 = { element: 'h3' };
		CKEDITOR.config.format_h2 = { element: 'h4' };
		CKEDITOR.config.format_h3 = { element: 'h5' };
		editors = CKEDITOR.instances;
		if (editors) {
			for (var editor in editors) {
				config = editors[editor].config;
				editors[editor].destroy(true);
				if ($('#' + editor).length > 0) {
					CKEDITOR.inline(editor, config);
				}
			}
		}
	}
};

En donde lo que hacíamos era:

  • Modificábamos los parámetros de la configuración general del CKEDITOR que necesitábamos (format_tags, format_h1, format_h2 y format_h3).
  • Recogíamos todas las instancias del CKEDITOR
  • Para cada una de ellas, almacenábamos su configuración, destruíamos la instancia y la volvíamos a generar, esta vez invocando nosotros al constructor inline.

Este método, según vimos en las sagradas escrituras de Stackoverflow, es muy común cuando se quiere modificar de forma dinámica la configuración del CKEDITOR. Provocaba un efecto de parpadeo algo extraño, ya que primero se invocaba desde el Symfony, y una vez creado se volvía a hacer lo mismo desde el JavaScript, por lo que había unos breves instantes en que el el TEXTAREA se quedaba sin CKEDITOR asociado, pero nos pareció una consecuencia aceptable si lográbamos hacerlo funcionar como queríamos.

Pero entonces ocurrió que esos breves instantes se convirtieron en eternidades, y por más que esperásemos, había veces en que esa segunda creación del CKEDITOR nunca llegaba, y resultaba imposible por tanto introducir contenidos en ese campo. Intuíamos que, al carecer de patrón de aparición aparente, se debía a desajustes en los procesos de carga del JavaScript de Symfony y el nuestro, así que nos pusimos a indagar hasta que finalmente dimos con la solución:

Al añadir el campo en el formulario de Symfony, hacerlo añadiendo un auto_inline a false:


->add('text', CKEditorType::class,
    array(
        'required' => false,
        'auto_inline' => false,
        'inline' => true,
    )
)

Y en el config.yml, cargar la configuración que antes metíamos por JavaScript


page_manual:
            entities: false
            allowedContent: true
            format_tags: "p;h1;h2;h3"
            format_h1: { element: 'h3' }
            format_h2: { element: 'h4' }
            format_h3: { element: 'h5' }
            toolbar: [ ['WidgetTemplateMenu', 'BootstrapTabs'],['Bold', 'Italic', 'Underline', 'Strike'],['Format'],['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],['NumberedList', 'BulletedList'],['Link', 'Unlink', 'Anchor'],['Image', 'PageBreak'],['PasteText', 'PasteFromWord', '-', 'Undo', 'Redo'],['Find', 'Replace', '-', 'SelectAll'],['ShowBlocks'] ]
            uiColor: "#ffffff"

El resultado es que ahora la configuración correcta se carga inicialmente desde el componente de Symfony, y el JavaScript se utiliza… para nada, ya no nos hace falta: un código más simple, eficaz y fiable.

Esperamos que esta solución le pueda servir a alguien y le ahorre un rato del camino que tuvimos que recorrer hasta llegar a esta concusión 🙂

He aquí la gran pregunta.

Respuesta corta: porque tenemos un Transtorno Obsesivo Compulsivo. De ahí el nombre del framework. Tocstrap. Ríete tú de Sterling Cooper.

Respuesta larga: porque nos hacía falta una herramienta front con la que afrontar nuestros proyectos, que nos hiciese más rápidos, autónomos y eficaces, y evitase malgastar tiempo en tareas repetitivas de un proyecto a otro. Y todo ello sin generar dependencias de terceras partes, o las mínimas posibles, manteniendo el máximo control sobre el código.

Es decir, un TOC de manual.

Home de Tocstrap

Sí, sí, van en serio, le hemos puesto ese nombre

Así que, con las suficientes referencias a nuestras espaldas que dan el ya maduro recorrido de Elemento115, y que nos permiten saber qué necesitamos como equipo y qué nos haría mejores, nos decidimos a comenzar nuestro propio framework de CSS y JavaScript.

La forma de abordarlo es sencilla: siguiendo las ideas del Atomic Design hemos creado una conjunto de componentes aislados entre sí que nos permiten afrontar de forma automática la creación de cualquier elemento que nos podamos encontrar en un proyecto, así como dotarle de comportamiento. Y todo ello documentado en unas guías de estilo dinámicas, accesibles a través de una URL propia, y que cargan los mismos ficheros que el resto del proyecto. De esta forma nos aseguramos de la autoactualización de la guía de estilo, ya que al modificar el componente del proyecto se modifica automáticamente su homólogo en la guía de estilo.

A todo ello hay que añadir un sistema de grid, basado en el de Bootstrap, que permite a los desarrolladores una buena dosis de autonomía al crear plantillas, sin tener que depender del departamento de Front-end. No nos hemos atrevido aún con el CSS Grid, pero sí con Flexbox, y en lugar de las 12 columnas habituales nos hemos ido hasta las 20, que da más margen para afinar y da divisiones enteras del 100%, y no números periódicos puros en los que uno no puede confiar. Otra vez el TOC.

Columnas del sistema de grid de Tocstrap

Nuestro grid en todo su esplendor

También hemos aportado las ventajas que da usar SASS y Gulp. Tenemos un fichero de settings que configuramos al inicio del proyecto y que nos permite establecer de forma cómoda y rápìda aspectos tan dispares como:

  • Colores corporativos
  • Anchos de los contenedores principales
  • Espacio de los gutters del grid
  • Tamaños y tipografías de los textos
  • Puntos de corte de las media queries
  • Velocidad de las transiciones CSS

De este fichero beben todos los componentes del framework, así que si a mitad del proyecto el cliente quiere cambiar un rojo por un verde, tardamos unos 10″ en hacerlo (y 9″ son de abrir el fichero y arrancar el Gulp).

Aspecto del fichero de settings de SASS

Todas estas cosas podemos modificar fácilemente

El resto de elementos CSS del framework se reparten en módulos de SASS que agrupan aspectos similares, tales como layout, texts, forms… Desde la hoja de estilos principal cargamos dichos módulos, que junto al reset CSS y a los mixins de SASS, nos dejan en una posición de inicio estupenda para arrancar el proyecto con mucho tyrabajo ya hecho.

En cuanto al JavaScript, reunidas todas las funcionalidades en un único fichero y encapsuladas en objetos aislados entre sí, nos permite una inicialización muy sencilla basada en unas convenciones de sintaxis HTML para cada componente y una llamada al método init() correspondiente. No hay, por tanto, que preocuparse por el comportamiento: el framework hace el trabajo por ti.

Aspecto del fichero principal de JavaScript

El init() es nuestro amigo

Esto que hemos hecho no es más que el arranque del camino. Nos queda muchísimo por recorrer, muchas cosas que añadir, unas cuantas que modificar y más de una que eliminar. Tal vez cambiemos Gulp por Webpack o usemos ambos, puede que dejemos de lado jQuery por ES6, incorporaremos Grid CSS en cuanto podamos, y una lista interminable de cambios que ahora ni podemos intuir. Pero la idea básica, el esqueleto sobre el que construir, seguirá siendo el mismo: un único framework para gestionarlos a todos.

jQuery vs JavaScript

Planteadas en nuestro artículo anterior las ventajas e inconvenientes de utilizar jQuery, llega la hora de decidir qué hacemos con él. Y para ello el primer paso es responderse a una pregunta:

¿Qué necesidades de JavaScript tengo como desarrollador?

Es difícil encontrar una respuesta que no requiera una explicación de miles de píxeles de longitud, así que vamos a tomar el caso de un estudio como Elemento115, y pensar en los proyectos más recientes que tengamos. Eso nos permitirá limitar los casos de estudio.

Para empezar debemos distinguir entre proyectos de webs puramente comerciales, como microsites o páginas clásicas de empresa tipo «quiénes somos-productos-servicios-contacto«, y web apps, que son algo más complejas, en funcionalidad, evolución y tecnología. La definición del tipo de proyectos que encontramos en internet es bastante más poliédrica que está simple categorización, pero como primer acercamiento nos puede servir.

Pueden servir como ejemplo, en nuestro caso, Titanio Estudio y Zio Rød Brand Consultants.

En el primer caso nos encontramos con unas necesidades de JavaScript muy básicas: mostrar/ocultar elementos, plegar/desplegar secciones, añadir algún efecto visual, validar formularios… en general acciones que tienen mucho que ver con el filtrado y manipulación de elementos del DOM, y la aplicación de animaciones sobre ellos.

Moviendo elementos en el DOM

¿Y lo bien que lo pasamos moviendo cosas por el DOM?

En el segundo, a lo anterior se le unen peticiones AJAX, preparación, envío, recepción y procesado de datos (que pueden llegar a ser bastante grandes y complejos), almacenamiento local de información, gestión dinámica del contenido, exportación del código a Mobile App… en definitiva, un conjunto de funcionalidades que requieren de una buena estructura del código que permita que sea robusto, escalable y testeable.

Código de un fichero JSON

El JSON. ese gran amigo

Definidas las necesidades, hay que pensar cuál es la mejor opción para satisfacerlas.

¿Es jQuery la alternativa que más me conviene?

Esta es la pregunta del millón, y el motivo de estos dos artículos. Y la respuesta es… depende.

Para proyectos muy sencillos, las ventajas de jQuery se ven potenciadas pues nos permiten alcanzar resultados muy óptimos en muy poco tiempo, y por la propia naturaleza del proyecto será raro que nos encontremos algunos de sus inconvenientes, o al menos no de forma que nos afecte demasiado. Por estos mismos motivos podemos llegar a plantearnos usarlo si es que seguimos una metodología en la existe una entrega rápida de prototipos funcionales de forma recurrente.

En el caso de web apps, podemos empezar a dudar, y con motivo. Si bien es cierto que muchos de ellos serían abordables y correctamente resolubles con una buena arquitectura basada en jQuery, puede que no sea lo más óptimo, pues nos obligará a hacer un trabajo extra para llevar la librería a los límites que queremos al no estar diseñada para ello, cuando usando Vanilla JS podríamos obtener los mismos resultados de forma más natural y con un código más fácil de testear y exportar.

Si a esto se le unen otros factores como el equipo de desarrollo con el que cuentes, el tiempo del que dispongaslos navegadores a los que tengas que dar soporte, la deuda técnica que seas capaz de asumir… hay tantos factores con tantas posibles alternativas que resulta imposible elaborar una respuesta absoluta. Para cada caso habrá que tener en cuenta las conclusiones anteriores y analizar, según los factores externos, qué es lo mejor.

¿Entonces?

Como hemos visto, el escenario que se nos presenta no es sencillo: multitud de situaciones iniciales distintas, y variedad de ventajas e inconvenientes de cada decisión, lo que nos lleva a la imposibilidad de encontrar una respuesta clara a la pregunta que nos hacíamos al inicio: ¿qué hacemos con jQuery?

Existiendo alternativas a muchas de las cosas para las que veníamos usándolo, quizá la mejor opción sea la de casi siempre: no tomar ninguna decisión radical, empezar a probar desde ya mismo a hacer proyectos sin jQuery y evaluar el proceso. Y poco a poco, sin abandonarlo del todo, ir añadiendo a nuestro repertorio técnico el Vanilla JS de la misma forma que en su momento hemos hecho con otras tecnologías, hasta llegar al punto de disponer de un elemento más con el que decidir cómo abordamos los proyectos.

Porque, que no se nos olvide en medio de esta vorágine tecnófila, lo importante en nuestra profesión es resolver problemas de la mejor forma posible. La herramienta que utilicemos para ello no importa.

¿Quién no ha utilizado alguna vez en su vida jQuery? La librería por excelencia de JavaScript, nacida ya hace más de 10 años, en pleno fragor de la lucha por conseguir unos estándares aceptados en la web, se ha convertido con el tiempo en un estándar de facto en el desarrollo front-end, tan ampliamente aceptado que a veces es fácil olvidar que se trata de un elemento externo al navegador y que la verdadera sintaxis de JavaScript no empieza con «$».

Según las estadísticas, en enero de 2017 era utilizado por el 68.4% de los 10.000 sitios con más tráfico o en el 74.2% del top 100.000. Unas cifras verdaderamente asombrosas ¿De dónde viene este enorme triunfo, que convierte a jQuery en uno de los proyectos más exitosos de la historia de internet?

Como decíamos antes, nació en un momento complicado (uno de tantos) en el que JavaScript empezaba a utilizarse para algo más que para mover elementos por la página, pero los navegadores iban a rebufo de las necesidades de los desarrolladores, por lo que había que llenar nuestro código de comprobaciones para conseguir que fuese cross-browser. Entonces apareció jQuery y, a través de la normalización interna que hacía, consiguió que escribiendo una sola vez pudiésemos olvidarnos del navegador que estaba utilizando el usuario y nos centrásemos en desarrollar.

Otra de sus virtudes, en un mundo en el que aparecen nuevos frameworks de JavaScript con más frecuencia que el Cercanías de Renfe, es la estabilidad. Hay muy pocos casos en los que un proyecto de este tipo se haya asentado de tal forma que una década después siga estando tan vigente. Es cierto que sus mejores días ya pasaron, pero aún goza de una buenísima salud, y uno puede añadirlo a su lista de habilidades sin ningún miedo a que en breve deje de tener de soporte o incluso desaparezca.

Todo ese tiempo que lleva funcionando, unido a una comunidad de desarrolladores enorme que no para de contribuir, ha conseguido que la librería esté tremendamente evolucionada, depurada y optimizada, con un API y una documentación ejemplares, y una cantidad de plugins disponibles tal que es difícil tener una necesidad y que alguien no la haya solucionado previamente y puesto a disposición de los demás.

Por último, su curva de aprendizaje es muy agradable y satisfactoria, de forma que lleva muy poco tiempo empezar a manipular el DOM, añadir widgets o conseguir unos resultados espectaculares en relación al esfuerzo y tiempo invetidos.

code-jquery-vs-javascript

Diferencia de código entre jQuery y JavaScript para hacer un simple «Toggle class»

 

¿Acaso jQuery es como Rafa Nadal?

Pues no, Nadal sólo hay uno y jQuery tiene una buena lista de defectos que hacen desaconsejable su uso. En primer lugar conviene recordar que no es un elemento incluído por defecto en el navegador, es decir, tendremos que cargarla antes de poder utilizarla. Y hacerlo antes que ningún otro de nuestros ficheros JavaScript en los que queramos sacar provecho de ella, condicionado así las dependencias. Y aunque su tamaño esté extremadamente ajustado para todo lo que ofrece (la versión 3.1.1 se queda en 85Kb una vez minificada), no dejan de ser unas decenas de kilobytes que obligamos a descargar al usuario, y que por tanto ralentizan la disponibilidad de la página cuando el propio navegador incluye JavaScript nativo con el que posiblemente podríamos realizar las mismas funciones.

Precisamente en su propio origen reside uno de los motivos de su declive: igual que nació con la idea de normalizar y hacer más limpio el código que la Segunda guerra de los navegadores nos estaban obligando a generar, el final de la lucha o al menos la paz relativa que ha supuesto la adopción general de unos estándares tanto en CSS como en JavaScript, ha propiciado que ya no haga falta recurrir a jQuery para alcanzar esa limpieza. Una buena muestra de ello se puede encontrar en la estupenda web «You might not need jQuery«, donde se pueden encontrar, hechos con Vanilla JS, ejemplos alternativos de muchas de las funcionalidades que solemos demandarle a la librería.

timeline-of-web-browsers

Evolución temporal de la guerra de navegadores desde el ascenso al poder del káiser Guillermo II hasta nuestros días. Si queréis verlo en detalle sin perder los ojos, mejor pinchad en la imagen.

Otra consecuencia negativa viene motivada por su propio éxito: su aceptación y difusión ha sido tal que muchos desarrolladores han olvidado cómo escribir simple JavaScript, o incluso, al incorporarse al mundo laboral más tarde del 2006, ni siquiera han tenido la oportunidad, necesidad, tiempo o energía de realizar ningún proyecto sin el apoyo que ofrece jQuery. Y eso, por muy fiable y sólido que sea, no deja de ser un inconveniente pues nos hace más dependientes al tener como que pasar por un puente para llegar a una de las tres áreas básicas del Front-end. Tan simple como que, si no se carga jQuery, no podemos añadir comportamiento a nuestras webs. Demasiado importante como para poner todos los huevos en una cesta si no es a cambio de unas ventajas que lo compensen.

En la lista de aspectos más puramente técnicos que conviene tener en cuenta están la mayor facilidad para realizar TDD con Vanilla JS que con jQuery, la dificultad para exportar nuestro código jQuery a frameworks de JavaScript o patrones MVC, su poca adecuación para realizar web apps al estar más orientado a la manipulación del DOM, o su incompatibilidad para realizar mobile apps usando frameworks carentes de DOM, tales como React Native o NativeScript. Para ampliar información de estos aspectos, resulta muy interesante leer este diálogo a 6 que hace unos meses tuvo un grupo de desarrolladores y que en parte han motivado este post.

Pues sigo sin saber qué hacer

Hemos repasado las ventajas y desventajas de jQuery. En la segunda parte exploraremos qué necesidades más habituales puede encontrarse un desarrollador de un estudio semejante al nuestro, si existen alternativas para afrontarlas sin necesidad de jQuery y si sale rentable abordarlas, y por último trataremos de emitir un veredicto sobre la conveniencia o no de abandonar jQuery en nuestros proyectos y que pase a formar parte de la historia junto al hack para evitar el doble margen de elementos flotados.

Sin caer en el spoiler, os adelantamos que, como casi siempre que hay una discusión, ninguno de los dos bandos va a quedar satisfecho. Os esperamos en breve 🙂

Carlos Espada
Técnico de deflectores
cespada@elemento115.es