React, Browserify y Babel en Plugins de WordPress (II): Ahora con Gulp

Este post es la continuación de React, Browserify y Babel en Plugins de WordPress (I). Si has llegado aquí, te recomiendo que leas la primera parte para conocer los conceptos básicos de Browserify.

Qué es Gulp

Gulp es una herramienta basada en nodeJS para automatizar labores repetitivas durante el desarrollo de software. Por ejemplo, podríamos escribir JavaScript modularizado en distintos archivos y luego Gulp los une y los comprime en uno sólo. También para procesar hojas de estilo en SASS. Es muy, muy útil, nos ahorra mucho tiempo, errores y dolores de cabeza.

¿Podríamos usar Grunt? Sí pero para lo que queremos hacer Grunt se antoja lento. Gulp hace uso del sistema de streams de Node dando lugar a una ejecución muy rápida a la hora de tratar con archivos de gran peso.

Para qué vamos a usar Gulp

  • Para ejecutar Browserify directamente desde Gulp en lugar de ejecutar el script de npm que creamos en el post anterior. Esto tal cual no tiene ninguna ventaja, es lo que viene a continuación lo que nos beneficia.
  • Comprimir JavaScript para que ocupe menos espacio en disco y sea más rápido al cargar.
  • Crear un watcher para que cuando modifiquemos algún archivo JS, Browserify se ejecute automáticamente sin tener nosotros que ejecutarlo de nuevo desde la consola.

Nuevos paquetes para npm

Necesitamos nuevas dependencias en nuestro plugin que descargaremos desde npm. Para ello podemos ejecutar:

npm install --save-dev gulp gulp-rename gulp-uglify vinyl-source-stream watchify vinyl-buffer
  • gulp obviamente, sin él no podemos hacer nada
  • gulp-rename nos servirá para renombrar archivos más adelante
  • gulp-uglify es el compresor de JavaScript
  • vinyl-source-stream: Vinyl no es más que la representación de un archivo en un objeto. Un archivo tiene dos propiedades importantes: La ruta y el contenido. Representar un archivo en Vinyl nos permitirá recibir de Browserify todo el JS procesado y tratarlo luego para renombrarlo, comprimirlo o lo que queramos. Es un paquete altamente utilizado en Gulp que por filosofía, éste último, se mantiene simple.
  • watchify: Para crear nuestro watcher de archivos.

El archivo gulpfile.js

Bien, es hora de crear nuestro archivo, gulpfile.js donde indicaremos a Gulp cuáles son las tareas que queremos hacer. Para ello, creamos el archivo en la carpeta raíz de nuestro plugin y generamos la tarea por defecto o tarea default:

Dentro del archivo escribimos lo siguiente:


var gulp = require('gulp');

gulp.task( 'default', function() {
    console.log("Hola Gulp");
});

Antes de ejecutar Gulp, vamos a crear un nuevo script dentro de package.json, sustituyendo el script build que generamos en el post anterior:

...
"main": "index.js",
"scripts": {
   "build": "gulp default"
},
"keywords": [],
...

Ahora sólo tenemos que ejecutar

npm run build

y nos tendría que salir algo así:

Ejecución básica de Gulp

Como vemos, a Gulp sólo hay que indicarle las tareas con un callback. Para ejecutar una tarea en concreto sólo hay que ejecutar gulp nombre-de-la-tarea.

Vamos a complicar un poco la cosa y vamos a hacer que Browserify se ejecute cada vez que ejecutamos npm build.

Por pasos:

  • Generamos un bundle  a partir de Browserify (que ya instalamos en el post anterior y nos sirve también para Gulp, así como Babel). Le indicamos que el fichero de entrada se encuentra en src/index.jsLa opción debug tendrá en cuenta los Source Maps.
  • Le indicamos a Browserify que use Babel con los presets ES2015 y React. En el post anterior dicha configuración iba en el archivo .babelrc así que podemos borrar dicho archivo.
  • Ejecutamos dicho Bundle y mediante el sistema de streaming vía funciones pipe (¿Os suena de UNIX?), lo recogemos con vynil-source-stream, le cambiamos el nombre a app.js y lo mandamos a la carpeta build.

Si volvemos a ejecutar npm build, veremos que al cabo de unos segundos se vuelve a generar el archivo build/app.js.

[17:37:45] Starting 'default'...

[17:38:11] Finished 'default' after 26 s

Un momento, ¡¿26 segundos?! ¿No decíamos que Gulp era rápido? Y lo es, pero la primera ejecución es lenta. Cuando tengamos listo el watcher veremos que la tarea se ejecuta en muy pocos segundos.

Creación del watcher

Si no queremos estar ejecutando el script cada vez que hacemos un cambio lo más inteligente es crearnos un watcher.  Para eso vamos a usar una nueva tarea llamada watch.

Es parecido a la anterior tarea sólo que ahora usamos watchify para convertir el bundle en algo observable. Cada vez que se actualice un archivo, nos saldrá por pantalla el nombre del archivo y se volverá a ejecutar el bundle, esta vez en muy poco tiempo

Además agregamos un nuevo script en package.json:

...
"main": "index.js",
"scripts": {
  "build": "gulp default",
  "watch": "gulp watch"
},
"keywords": [],
...

Ejecutamos npm run watch et voilà, Gulp ejecuta primero todo el bundle pero luego queda a la espera de cambios en cualquier archivo dentro de cualquier archivo que estemos importando desde src/index.js, recursivamente.

Compresión de JavaScript

Para realizar la compresión nos ayudamos del módulo uglifysólo lo vamos a usar en la tarea default porque es posible que no queramos el código comprimido durante el desarrollo. También vamos  refactorizar un poco agrupando código repetido. Aquí lo tenemos todo y comentado:

Hemos hecho algunas cosas aquí: Hemos creado una nueva tarea, bundle, que únicamente ejecuta el bundle y que no utilizaremos directamente. Luego hemos modificado la tarea default para que primero ejecute bundle y luego recoja el archivo resultante y lo comprima. Si no lo hiciéramos así puede que Gulp lanzara primero la ejecución del bundle y a la vez intentara comprimirlo, como el bundle tarda mucho más en componerse, se ejecutaría primero la compresión y luego se sobreescribiría con la ejecución del bundle. Esto es lo bueno y lo malo de los streams en Node, que son asíncronos.

Para demostrar ese problema podemos sustituir default por esto otro:

gulp.task( 'default',  function() {
    var bundle = getBundle();
    executeBundle(bundle);

    // Recogemos el fichero del bundle creado y lo comprimimos
    return gulp.src(['./build/app.js'])
        .pipe(uglify()) // Comprimimos
        .pipe(gulp.dest('./build'));
});

Aparentemente la lógica es buena: Primero el bundle, luego la compresión. Pero como hemos dicho, Gulp no funciona así. En este caso lanzaría la ejecución del bundle y paralelamente lo comprimiría. El bundle acaba más tarde por lo que veremos en el archivo resultante un código sin comprimir.
Sólo falta ejecutar npm run watch  para desarrollar y npm run build cuando queramos sacar el código a producción. Con la segunda ejecución vemos que el fichero build/app.js está comprimido

En el próximo episodio

Reescribiremos TODO para trabajar con Webpack. El repositorio del código visto en este post se encuentra en https://github.com/igmoweb/react-plugin

React, Browserify y Babel en Plugins de WordPress (I)

Al grano. Vamos crear un plugin muy sencillo que utilice React en un menú del wp-admin. El plugin generará una página de administración y cargaremos React ahí mismo. Obviamente lo podríamos usar para crear una interfaz en el front y no sólo en el admin.

Para los más impacientes hay un repositorio donde voy poniendo el código: https://github.com/igmoweb/react-plugin/. Para ver este post en concreto hay que elegir la rama step-1.

Qué necesitamos

  • ReactEs una famosísima librería para generar interfaces de usuario. No es un todo en uno como Angular, React sólo sirve para crear la interfaz, no contiene nada para modelar datos y demás. No profundizaré mucho en React porque no es el objetivo de este post.
  • BrowserifyNos ayudará a generar un único archivo JavaScript que contiene todos los módulos necesarios. A este archivo final se le llama en inglés bundle. Browserify nos permite importar paquetes o módulos desde distintos archivos (véase React entre otros) para luego juntarlos todos en uno sólo, que es el archivo que usaremos en nuestro menú wp-admin.
  • BabelEs un transcompilador de ES6 (ECMAScript 6). Convierte código JavaScript ES6 en código ES5, que es el que entienden todos los navegadores hoy en día. Trabajar en ES6 es más fácil que en ES5, y más divertido.

¿Por qué no Webpack? Te estarás preguntando, amigo informático “listillo”. Pues porque Webpack es complicado, un monstruo, una bestia que hace DE TODO, un Browserify supervitaminado. Antes de meternos en Webpack podemos usar herramientas más sencillas como Browserify porque luego Webpack se entiende mejor.

Aquí un dibujo de cómo funciona más o menos todo a la vez:

Diagrama de React, Browserify y Babel

Requisitos previos

Tenemos que instalar Node.js en nuestro ordenador. Node incluye un gestor de paquetes llamado npm que nos servirá para gestionar las dependencias de nuestro proyecto. Como nuestro plugin utiliza React y Browserify, éstos se convierten en dependencias del plugin.

El plugin

El plugin que vamos a crear es muy sencillo: Crea un menú de administración en WordPress desde donde cargará el archivo JS que sacará por pantalla el HTML necesario gracias a React. Para esto creamos una nueva carpeta en wp-content/plugins, por ejemplo react-plugin. Ahora creamos el archivo principal del plugin (no va a haber más): react-plugin.php, y empezamos a picar código:

Es un plugin bastante tonto: Genera un menú (cuyo ID generado lo guarda como atributo de la clase React_Plugin, ahora veremos porqué) y nada más. El contenido del menú (React Plugin), es un simple div#app. Dentro de este div, React generará el código HTML.

Estado de las carpetas:

-wp-content/plugins/react-plugin
  * react-plugin.php

Instalación de dependencias

Gracias a npm, vamos a empezar a instalar todas las dependencias para nuestro proyecto. En el terminal, nos situamos en la carpeta de nuestro plugin y escribimos:

npm init -y

Esto nos genera un archivo package.json, un documento que npm necesita para saber qué instalar y qué características tiene el proyecto. Lo vamos a dejar tal cual porque no quiero meterme mucho en él, es todo un mundo.

Instalamos las dependencias:

npm install --save react react-dom

npm install --save-dev browserify babelify babel-preset-react babel-preset-es2015

Con esto, veremos que se ha creado una carpeta nueva, node_modules, donde se habrán descargado las siguientes dependencias:

  • React y ReactDOM. Éste último sirve para renderizar los componentes de React.
  • Browserify
  • Babelify: Un plugin de Browserify para transcompilar el código ES6 a ES5. Al final es Babel adaptado a Browserify, nada más
  • Babel Preset React y Babel Preset ES2015: Son paquetes de Babel que contienen la configuración necesaria para transcompilar de ES6 (la versión de Junio de 2015) a ES5. Podríamos usar otro paquete como ES2016 o ES2017 si quisiéramos una versión de ES6 más avanzada. El ES2015 es más que suficiente. El Preset de React ayuda a transcompilar el código de React a ES5 también.

Una vez todo instalado, el fichero package.json debería quedar más o menos así:

{
  "name": "react-plugin",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^15.3.2",
    "react-dom": "^15.3.2"
  },
  "devDependencies": {
    "babel-preset-es2015": "^6.16.0",
    "babel-preset-react": "^6.16.0",
    "babelify": "^7.3.0",
    "browserify": "^13.1.0"
  }
}

Estado de las carpetas:

-wp-content/plugins/react-plugin
  - node_modules
  * package.json
  * react-plugin.php

Estructura de carpetas

Dentro de la carpeta del plugin vamos a crear dos carpetas adicionales:

  • src: Aquí vamos a meter todos los archivos JS escritos en ES6 así como los componentes de React.
  • build: Con ayuda de Browserify, a partir de todo lo que hay en src + React (que está en node_modules/react), se generará un archivo app.js dentro de este directorio. Dicho archivo será el que cargaremos en nuestro menú de WordPress.

Estado de las carpetas:

-wp-content/plugins/react-plugin
  - build
  - node_modules
  - src
  * package.json
  * react-plugin.php

Componentes de React

Vamos a crear el componente principal de nuestro proyecto. Va a ser un simple Hello WordPress

src/App.js

src/index.js

Es algo bastante simple: App.js es el elemento principal de la interfaz. Es un simple div con un Hello WordPress dentro. Para crear un componente en React, extendemos simepre de la clase React.Component (en ES5 sería más feo y engorroso). export default significa que cuando queramos importar (con import from) dicho archivo desde otro fichero JS, es la clase App la que se exporta.

index.js  es el archivo principal de la aplicación. Lo que hace es importar el componente App (ya sabemos, con import from) y renderizarlo en el elemento HTML div#app. También importa React y ReactDOM para pintar en la página. Recordad que este elemento ya lo tenemos en nuestro menú de administración.

-wp-content/plugins/react-plugin
  - build
  - node_modules
  - src
     * App.js
     * index.js
  * package.json
  * react-plugin.php

Configuración de Babel

Si pusiéramos a trabajar ahora mismo a Browserify, podríamos generar el archivo build/app.js pero todo saldría en ES6, cosa que los navegadores todavía no entienden bien. Tenemos que decirle a Browserify que utilice Babel y que éste use los presets que nosotros le digamos. Para ello creamos un nuevo fichero:

.babelrc

{
  "presets": ["es2015", "react"]
}

Con esto le estamos diciendo a Babel que use los presets (que ya tenemos instalados en node_modules) ES2015 y React.

-wp-content/plugins/react-plugin
  - build
  - node_modules
  - src
    * App.js
    * index.js
  * .babelrc
  * package.json
  * react-plugin.php

Ejecución de Browserify

Emoción, vamos a generar por primera vez nuestro fichero build/app.js con su React, sus componentes y todo traducido a ES5 por un módico precio de cero maravedíes. A su vez, nuestros componentes estarán separados en sus respectivas carpetas para una mejor organización del código. Es un win-win en toda regla.

Para ello ejecutamos la siguiente sentencia en nuestro terminal:

./node_modules/.bin/browserify -t [ babelify ] src/index.js -o build/app.js

Con esto le decimos a Browserify: “Usando el plugin babelify, transforma el archivo src/index.js y todo lo que importa éste, en build/app.js. Si lo ejecutáis deberíais ver un archivo súper tocho en build/app.js.

Para no tener que ejecutar un comando tan largo, package.json tiene un apartado para crear scripts propios. Añadimos lo siguiente:

{
  "name": "react-plugin",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "browserify src/index.js -t [ babelify ] -o build/app.js"
  },
...

Ahora simplemente ejecutamos

npm run build

Y Browserify se ejecutará tal y como hemos hecho antes.

Estado de las carpetas:

-wp-content/plugins/react-plugin
  - build
    * app.js
  - node_modules
  - src
    * App.js
    * index.js
  * .babelrc
  * package.json
  * react-plugin.php

De vuelta al plugin

Vale, ya tenemos generado nuestro build/app.js pero no lo estamos usando en el plugin de ninguna manera. Hay que hacer uso de hooks y funciones de WordPress para ello. Aquí está la versión definitiva del mini plugin que hemos hecho:

Si nos fijamos, utilizando el hook admin_enqueue_scripts, añadimos nuestro build/app.js sólo en la página de nuestro plugin gracias a la comparación $this->page_id === $hook. De esta forma no agregamos nuestro JS en todas las páginas. Sólo una nota más: El script debe ir en el footer, de otra forma no funcionará, ya que en el header todavía no existe nuestro div#app.

Próximamente…

En el siguiente post vamos a adentrarnos en cómo automatizar todo esto. Es un poco fastidioso ejecutar npm build cada vez que queremos cambiar algo. Para echo, usaremos un watcher que detecte los cambios en los ficheros JS y que rehaga el build en build/app.js.

Cómo cargar módulos de Jetpack sin activarlo

En CampusPress nos dimos cuenta hace tiempo de que algunos módulos de Jetpack vienen muy bien para todos los usuarios pero no todos ellos van a activar el plugin al completo. Para no tener que sacar los módulos del código de Jetpack y utilizarlos como plugins individuales hemos dado con una fórmula para cargar sólo aquellos que nos interesan (los llamamos módulos obligatoriosmandatory en inglés) incluso si Jetpack está desactivado. El siguiente código es parecido al que utilizamos y lo que intenta es:

  • Carga el código base de Jetpack
  • Carga los módulos de Visibilidad de Widgets, Shortcodes Personalización de CSS  y los activa automáticamente.
  • Obvia el resto de los módulos. Jetpack no sabrá ni que existen.
  • Esconde Jetpack de la lista de plugins, por si alguien pretende activarlo
  • Desactiva Jetpack en caso de que estuviera activado.
  • Activa el modo developer en Jetpack

El código tiene dos problemas:

  • Los módulos que requieran conexión a WordPress.com no funcionarían. En este caso no hace falta.
  • No permite activar Jetpack por lo que el usuario no tendrá control sobre ciertas cosas que podrían serle útiles

Este código funciona en instalaciones que tengamos muy controladas. Si el usuario pretende instalar Jetpack, no va a poder hacerlo.

Jetpack_Mandatory_Modules Redux

¿Se puede mejorar? ¡Claro!

La siguiente clase deja a los usuarios activar/desactivar Jetpack pero oculta los módulos que queremos siempre tener instalados para que no toquetee por ahí:

Muy útil porque el usuario puede ahora activar y desactivar Jetpack, así como conectarse a cualquier servicio de WordPress.com pero los módulos obligatorios siempre estarán cargados.

Si siempre cargáis los mismos módulos de Jetpack para todos los clientes, este código puede ser de mucha ayuda para ahorrarnos algo de tiempo cuando creemos una nueva instalación.

WordCamp Europa 2016: Impresiones

En el año 1 después del #wpdrama (eso es 2016 en el calendario gregoriano) se celebra una vez más WordCamp Europa. Y van cuatro: Leiden, Sofía, Sevilla y ahora Viena. WCEU se hace más grande y el nivel de las charlas mejora. Se nota que la comunidad de WordPress es ya madura, el torbellino de tecnologías que se muestran es cada vez mayor y aporta una mayor riqueza a todo el ecosistema. Nuevos personajes aparecen en escena otrora ajenos a WordPress y sea por necesidad o por abrirse a otros mercados llegan con nuevas ideas que refrescan la temática de las charlas.

Pero esto de crecer tiene sus desventajas, el número de visitantes se ha duplicado respecto a Sevilla, el calor no, sólo faltaba. Hablaré de todo esto más adelante.

¿De qué se ha hablado en WCEU?

Foto de Tammie Lister (@karmatosed)
Foto de Tammie Lister (@karmatosed)

De muchísimas cosas pero sólo asistí a un pequeño porcentaje de ellas, sobre todo las dedicadas a desarrollo que para eso es lo mío. Aquí van mis highlights:

Short Talks: WordPress Hardening – Ten tips in ten minutes, What’s New in PHP7 and what to expect in PHP7.1

Son dos charlas de 10 minutos cada una. La primera de ellas trata algo que normalmente se pasa por alto: Seguridad. Algo que suele pasar con proyectos para clientes es no definir un buen acabado en materias de seguridad para prevenir ciertos problemas que terminan por surgir. Durante la charla (a velocidad del rayo) nos proponen ciertas prácticas que podemos incluir en nuestro workflow de manera casi natural y que prácticamente no afectará al tiempo de desarrollo del proyecto. Entre ellos mantener WordPress actualizado, probar nuestras copias de respaldo, permisos para usuarios y permisos de ejecución y escritura en carpetas.

La segunda charla se nos repitió a todos aquellos que asistimos a la WCEU en Sevilla el año anterior pero con algunos matices que merecen la pena. PHP7 ha llegado fuerte: Es mucho más rápido y consistente en la declaración de tipos.

 

Thinking outside the box(model) – An introduction to Flexbox

Una charla imprescindible para aprender el nuevo sistema de layout de CSS. Uno se pregunta por qué Flexbox no había llegado antes. ¿Sabéis eso de centrar verticalmente con CSS? ¿Que un div adapte dinámicamente su anchura cuando sobra espacio? ¿Qué tal si las columnas se dividan con igual anchura automáticamente cuando añadimos o quitamos alguna? Todas estas dificultades son cosas del paleolítico gracias a Flexbox y prácticamente compatible con todos los navegadores modernos.

 

Seven Times Faster : A Study in frontend Optimization

Una de mis charlas favoritas, aunque me hubiera gustado que durara más. Peter Wilson empieza mostrando una serie de estadísticas sobre el proceso de carga y renderizado en un navegador cómo desatender esto puede llevar a un descenso dramático del porcentaje de conversión. Luego puso en evidencia lo anticuado que WordPress tiene el sistema para agregar scripts o estilos y expuso algunas opciones como el precargado de CSS o cargar scripts asíncronamente. Mucha información en poquísimo tiempo, me dejó con ganas de más. Me traería a Peter un fin de semana a Madrid para que lo explicara, la verdad.

The Ultimate REST API talk

Básicamente TODO lo que necesitas saber para empezar con la REST API de WordPress. Si no sabes lo que es ya deberías estar empezando a aprender.

 

Using Composer to create manageable WordPress websites

Buena chicha aquí, y muchísima información en poco tiempo. Composer es un gestor de dependencias para PHP. Desafortunadamente no lo puedo usar mucho porque WordPress y Composer no se llevan bien a la hora de crear plugins generalistas pero es muy interesante ver cómo puede servir a la hora de abordar un proyecto para un cliente. Por otra parte la charla me redescubrió Roots.io, una completa suite de desarrollo para WordPress que tiene muy buena pinta.

 

Modernizing WordPress Search with Elasticsearch

Otra joya. Elasticsearch puede ayudar a resolver los múltiples problemas que MySQL tiene a la hora de ejecutar consultas complejas. Taylor Lovett nos explica cómo se utiliza, para qué y si es fácil utilizarlo una vez tienes tu base de datos en funcionamiento (pista: es extremadamente sencillo). Ideal para sitios grandes, nos gustaría usarlo en CampusPress o Edublogs.

 

Como ya he dicho previamente, las charlas de este año han mejorado en calidad y parece que hay más hueco para los desarrolladores un poco más experimentados. El track 2 (el segundo en tamaño) albergó una gran parte de dichas charlas con un aforo más que considerable.

 

My friend the Impostor Syndrome

Normalmente las charlas sobre comunidad, aunque necesarias, me parecen flojas porque terminan repitiendo lo que ya sabemos. De entre todas ellas me quedo con ésta. Sonja Leix habla sobre cómo nos subestimamos a la hora de contribuir dentro de una comunidad porque nos arrolla un miedo a parecer idiotas. Nos recuerda muy bien que preguntar nunca es idiota y que colaborar de la forma que sea es siempre bueno y bien aceptado. El miedo es infundado y estanca nuestro crecimiento profesional y personal. Algo que intento explicar en el Meetup de Madrid. Quizás coja algunas ideas de la charla.

Todas las charlas están disponibles aquí: https://2016.europe.wordcamp.org/schedule/track-1-livestream/

Los Polyglots en el Contributor Day de WCEU Viena 2016

Polygloting

Contributor Day

Sinceramente, este año llegué tarde al Contributor Day y sin embargo tuve tiempo para sentarme con un grupo de españoles y revisar cómo se están haciendo las cosas en el grupo de Polyglots de Español. Liderados por Luis Rull pasamos un rato buenísimo durante el cual discutimos nuestras impresiones sobre la comunidad de WordPress en España y sobre cómo mejorarla.

Un momento, que no todo es oro

Como ya he dicho, WCEU ha crecido muchísimo de un año para otro. Sorprendentemente a nivel organizativo no se ha visto afectado. Las charlas han comenzado a su hora siempre y la atención de los voluntarios ha sido ejemplar. No hay otra comunidad como la de WordPress y es en estos eventos donde se demuestra la dedicación de los voluntarios y ponentes que sin cobrar un duro pueden llegar a repartir tantísima calidad en el evento, y a precios de saldo, oiga.

Pero hay cosas que han fallado y a mi parecer algo grave. Si las charlas son interesantes, lo que pasa fuera de ellas lo es muchísimo más. Cuando terminas de ver una charla que te ha gustado lo primero que quieres hacer es probar lo que has aprendido en tu ordenador lo antes posible. Una mesa y una silla y a teclear. Al rato pasa alguien que se interesa por lo que estás haciendo, te pregunta, le preguntas, y quién sabe si acabáis haciendo un proyecto juntos. Es debido a estas cosas por las cuales tengo el trabajo que tengo y sé lo que sé. Socializar durante una WordCamp es, a mi entender, lo más importante y en Viena ha fallado estrepitosamente ¿Por qué? Simple, no había casi espacio para pararse en una mesa con tu ordenador. En este aspecto, Sofía se lleva el primer premio (sobraba muchísimo espacio) y Sevilla era acogedor y fresco. Puede que la organización pensara que podríamos sacar nuestros bártulos al patio pero hacía muchísimo calor y humedad y el aire acondicionado en el interior no era un modelo de los que nos gastamos en España. Conclusión: se conoce a poca gente.

Aplauso y medio para WCEU 2016.

wceu1