This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Estamos construyendo un sistema de mensaje que se utiliza por todos los mercados.
He trabajado en esto desde que he subido a Shipstead, casi 8 meses atrás,
y se ha rotado.
Y fue un poco de un rato.
Voy a ser honesto con usted.
Básicamente, el sistema de mensaje tiene dos principales componentes.
El primero es el final, que es construido en Java, con Spring Boot,
y se utiliza Cassandra, como datastore.
Y funciona completamente en AWS, una empresa cloud-only.
Y luego tenemos tres frontends, que son Android, SDK, iOS,
y un widget javascript.
Yo trabajo en javascript.
Soy ingeniero de javascript, y voy a ir al proceso
de construir un widget javascript, que es básicamente lo que queremos,
es crear un div, instantiar el objeto,
especificar la idea del div, y luego obtener un widget que es responsable,
y trabaja con el tiempo real, y es customizable.
Y, bueno, tiene todo lo que deberías esperar de una plataforma mensajera,
una plataforma mensajera moderna.
Y básicamente, ¿qué fue el camino ahí?
Cuando yo subí, yo tenía el on-boarding,
y le dije, básicamente, necesitas construir este widget,
y se salió.
Y, primero, ¿cuándo empezaste?
Tendrías que saber a tu cliente.
¿Quiere usar este widget?
¿Por qué?
¿Qué necesidades hay?
Y, para mí, la primera pregunta fue, ¿cuándo es mi cliente?
Porque no es tan fácil.
Inicialmente, dices que tienes los usuarios.
Los usuarios son siempre tus clientes,
son los últimos clientes.
Ellos usan el producto, crean el dinero.
Y, para el widget que estuve construyendo,
mis usuarios vivieron en diferentes geografes,
de la Europa de la Oeste, de Asia, de Latinoamérica.
Ellos usan los browsers exóticos.
Por ejemplo, tenemos usuarios en Belarus,
que usan el Yandex.
El Yandex browser,
casi 20% de la tarjeta es en el Yandex browser.
Browser, que si vive aquí, en Barcelona,
o no, ni instalaciones.
Ellos tienen diferentes speed de conexión,
que es muy importante.
Y, también, tienen diferentes expectaciones,
según cómo el web ve en su geografía.
Ellos expectan más o menos features.
Por ejemplo, a veces,
si la conexión de internet lo permite,
si quieren un tiempo real,
a veces ellos son felices con tiempo de responso.
También tenemos usuarios profesionales.
Imagina el agente realista en Fotocasa.
Ellos quieren usar e-mail.
Ellos no quieren tener un chat, como WhatsApp.
Ellos quieren poder e-mail a varios usuarios.
Luego, tienes el usuario privado,
que sale algo en Vibo.
Ellos quieren una experiencia de WhatsApp.
Estos eran mis clientes,
y era como una lista longa y diversa.
Pero, también, tengo otro set de clientes,
que son los mercados.
Para mí, para llegar a los usuarios,
necesito los mercados para comprar en,
para instalar el widget en su web.
Y, hay una versión preciosa del widget,
y hemos aprendido algunas cosas de eso.
Esa era la noche que estaba mirando,
se desarrolló en jQuery,
y no trabajaba mucho tiempo,
y no tenía paginación.
Así que, si tuvieras, como, 51,
si tuvieras 50 conversaciones, si tuvieras 51, no te pasas.
Tienes que despegar uno para verlos.
Entonces, lo que hemos aprendido,
los mercados son clientes,
que son construidos en diferentes tecnologías,
ranging de reacción o angular,
como, realmente nueva.
Tienen tecnologías para Smart and PHP,
que no creo que haya any site left
usando Smart and PHP.
Aparentemente, hay.
Ellos quieren poder customizar el widget.
Ok, tenemos nuestro propio branding,
queremos tener nuestro propio look and feel,
y queremos poner eso en el widget,
pero no queremos romper el widget en el proceso.
Queremos que el widget trabaje,
pero la manera que queremos que trabaje,
que es un poco...
Entonces, tienen diferentes sistemas de construcción,
o no.
Algunos usan BrowCertify,
algunos usan webpack,
algunos usan nada,
ellos usan FTP o algo,
todo en lugar.
Algunos tienen equipos dedicados a la frontera.
Entonces, tienen ingenieros de frontera,
con mucho experiencia en JavaScript.
Algunos son muy pequeños mercados,
que solo tienen 3 o 4 ingenieros,
que son Jacko para los altos,
y tienen que tener algo que trabaje para ellos,
como crear un tag de script, importar,
y trabaja.
Y, a veces, tienen que predictar los ciclos,
que crean muchos problemas para nosotros,
porque no siempre tienen que informar las últimas versiones.
A veces, no tienen que informar en general.
Ellos dicen,
bueno, vamos a informar, pero no.
Tenemos algo que hacer más importante ahora.
No estoy negando eso,
pero para nosotros,
esto crea muchos problemas,
porque terminamos de mantener
múltiples versiones del widget,
y también terminamos de mantener
múltiples versiones del API,
porque tuvimos una más grande versión del widget,
que usó una más grande versión del API,
no todo el mundo ha cambiado,
tuvimos que mantener todo el API,
y a algún punto,
tuvimos tres versiones concurrenciales del API,
así que,
esto no está escalando.
Los costos fueron aumentando,
porque necesitaban servidores,
y había un poco de reinvestimiento,
y el problema fue que no volvieron a update.
Entonces,
colocando eso juntos,
tenía mi primer set de necesidades,
este fue,
tal vez, tres meses en mi,
o no,
en tres semanas,
en tres semanas,
en mi trabajo en Shipstead.
Ellos quieren un widget
que es clave,
plátforma y responsable,
customizable,
look and feel,
supports browser
que no existen,
como el yandex browser,
aquí.
Es básicamente construido en Chrome,
pero no es tan raro,
espero.
Ellos quieren hacer eso
sin customizaciones o responsables,
suporta reaccion,
suporta injeción directa
por el tab de script,
y todo en entre.
Entonces,
tiene que trabajar,
no sé qué tecnología tienen,
pero tiene que trabajar con ellos,
tienen que poder platicarlo,
y trabajar.
Entonces,
tenía un requisito
de mi propio producto team,
que era,
tenemos que poder update
los widgets
a nuevas versiones
sin el mercado.
Entonces,
incluso si ellos no quieren
update,
deberíamos poder
poner la nueva versión a ellos,
y ellos no deberían
poder reaccionar.
Podríamos hacer esto automáticamente,
que, de nuevo,
fue una decisión muy política,
y fue mucho,
mucho más fuerte.
Y luego,
también tienes el yandex team,
y el producto,
es como,
ah,
necesitamos el tiempo real,
necesitamos muchas buenas features,
y...
Esto es el primer set de necesidades.
Pero,
por supuesto,
hay más.
Eso habría sido fácil.
Cuando empezó el proyecto,
hay...
tuvimos apretados API,
que estaban aboutados
a ser removidos,
no yet removed,
las nuevas fueron desarrolladas,
entonces,
necesitaba desarrollar,
apoyar un API,
que no yet existía.
Un poco de
un problema chicken and the egg.
Entonces,
el servidor,
al momento,
no apoyaba el tiempo real,
pero quería tener el tiempo real.
Entonces,
necesitaba apoyar el servidor,
y...
pero apoyar el servidor,
cada unos segundos,
crearía un DDoS atacar.
Juste,
atacar su propio servidor,
que se despliegaría.
Entonces,
ah,
nosotros...
soltamos el problema
por solo apoyar
para el tab activo.
Entonces,
si el usuario se mueve,
para un tipo diferente,
yo empiezo a apoyar,
y yo only empiezo
cuando el tab
es activo.
Y,
luego,
te voy a iniciar el tab
para que el
Jennie
Abt
A,
que criminal
una javascript que tienen que ejecutar en su sitio.
Así que,
DREAM Requirements, este fue lo que hice.
Este fue mi primera vez como que voy a casa y...
Pero...
Entonces, me dijeron, ¿cómo hacer esto?
¿Cómo hacer esto?
Porque tengo una renta para pagar.
Entonces, primero, me empezaron a dividir los problemas
en problemas más pequeños, no necesariamente problemas más fáciles,
solo más pequeños, más, como menos cariños, problemas.
Y primero, abastecí el API.
Me quería abastecir, para separar el widget,
el UI,
de los acciones de API.
Entonces, necesitaba desarrollar el widget,
manejar la customización,
y manejar los updates y los tests de AB.
Y me hicieron eso,
que estoy muy orgulloso de.
Así que, primero, empezaron a abastecir el API.
No encontré una imagen de Ajax,
así que el dishwasher lo haceré.
Básicamente, la primera cosa que hice
fue crear un componente llamado El Connector.
Este fue de un punto de vista de widget.
Este fue el libro de la tercera parte.
Incluso si fue desarrollado por el mismo equipo,
el equipo de mí.
Y esto, abastecí todo el acceso al API,
y me instalé en el main widget.
Básicamente, lo que haceríamos,
por ejemplo,
es decir, recibí un evento de update de contras,
desde el API.
A algún punto, tenía que hacer polling.
Ahora y luego, en cada 30 segundos,
voy a hacer un get para un URL específico, cuando el promesio se cumplirá,
voy a emitir un evento de contras.
Luego, cuando tenía el nuevo API y podía abrir un socket,
recibí el data por el socket.
Pero todas estas funcionalidades,
la primera, que fue en el nuevo API,
o el nuevo, en el nuevo API,
eran todos grabados en El Connector.
La parte de widget, la parte de UI,
estaba tan acuerda de cómo la data estaba recibida.
En la parte de widget,
voy a hacer el contras de contras.
Y esta parte fue agnástica de cómo la data fue recibida.
El contras, incluso en el Ajax,
tendrá el tix interno,
con saber cuántos momentos per minuto
para poll, y así.
Y lo mismo sucedió desde los calles de API normal.
Por ejemplo, si quería obtener una conversación,
tendría un syntax como este.
El Connector, el Uscase,
el GetConversationExecute,
y voy a pasar la idea de conversación.
La única idea de la conversación que quería.
Esto tendría un promesio que resolviera
a un objeto, a una entidad,
a un objeto inteligente que tenía, como un objeto proper,
que tenía métodos, que tenía los atributos.
Y, por ejemplo, si quería obtener una conversación como reto,
voy a llamar este método.
Y luego, en el otro lado, en el Connector,
tenía el nuevo API,
y el nuevo y más respiro API.
Pero, esto fue agnóstico de lo que sucedió.
Por ejemplo, si quería marcar la conversación,
por ejemplo, por hacer un post, o un put, o algo,
de la perspectiva del widget,
esto no fue transparente.
El widget no sabía cómo el Connector hacerse su trabajo.
Se decía el Connector,
marqué esta conversación,
que cualquier API que el Connector usara,
o cualquier método HTTP,
era la responsabilidad de los Connectors.
Y, para el Connector, es un libro,
así que solo tengo un test para ello.
Es básicamente que tiene una cobertura de 85%,
que es bastante buena.
No es 100%,
pero no creo que nadie actualmente tiene 100% en el largo ron.
Pero esto me da una buena calidad,
un buen nivel de calidad.
85% cobertura es buena.
Y cómo testo?
Solo hago, como dije, un test con Karma.
Usé Chai for Assertions y sinón para marcar respuestas de JSON.
Imagínate, esto siempre conecta al servidor,
así que necesito marcar respuestas.
Necesito asegurar que, si recibo una cierta JSON,
eso se parse correctamente y todo es controlado.
Así que necesito marcar eso y usé sinón para ello.
Y todos los test son en phantom.js.
No hago ningún browser de cross-browser.
Esto funciona en el browser más simple,
pero, según que el phantom.js esté continuado,
tengo que migrar esto a Chrome.
Y para lanzar, cómo lanzar este libro.
Esto, por lo tanto, es un libro.
Todo el código está en GitHub
y cuando quería tener un proceso automático,
entonces, cada vez que me conecto,
este será un build-on-travel.
Si el build pasa todos los testos,
publicará un package de NPM a nuestro registro local.
Tenemos un registro interno de NPM en el artefacto.
¿Alguna preguntas hasta este punto?
Sí, por favor.
Cuando tienes un montón de taxas, ¿cómo manejas?
Cuando tienes un año de desarrollo, tienes un montón de taxas,
o no lo haces como un montón de relícitos.
No hacemos mucho de relícitos en El Connector.
Y también es el...
El tag, es siempre el número de versión,
que combina el número de versión en NPM.
Así que, en el package de JSON del widget,
puedo decir que quiero esta versión.
Y luego reconozco NPM y me llevaré la versión correcta.
Así que es como cualquier registro de NPM,
solo que es hostido internamente.
¿Alguna otra pregunta?
Ok, vamos adelante.
El widget.
Esta fue la parte principal.
Esta fue probablemente la menos...
La más interesante de desarrollar,
pero también porque es solo una aplicación de vista,
pero también la más visual importante,
porque es lo que el usuario ve.
Esto es lo que el manager del proyecto ve.
Y esta es la actualidad de la UI.
Y para hacer eso, usé la vista.
¿Estás familiar con la vista? ¿Quién?
Es básicamente una versión de React.
Tiene features de ambos React y Angular.
Es, para mí, preferido para React.
También implementa virtual DOM.
Tiene un componente llamado Vuex,
que es un store de estado,
y en una forma similar,
tenemos Redux para React,
tenemos Vuex para Vuex.
También utilizo un router para manejar las routas.
Por ejemplo, las conversaciones necesitan ser estados.
Si estoy hablando de una persona
y compro el URL para un browser diferente,
quiero esa conversación con esa persona específica,
no la en la caña del widget.
Así que necesito un router para eso.
También necesito usar un API de DOM,
que era un poco de un trade-off,
que no era mi opinión más feliz.
Básicamente, la arquitectura del widget.
Si recuerdas,
tengo un header, un list de mensajes.
Cada un list de mensajes tiene un item list de múltiples mensajes.
Lo mismo con la lista de conversaciones y un input chat.
Y también una menú de conversaciones,
que permite a los usuarios
que delete o bloque esa conversación.
Estos son componentes de Vuex,
que significa que se contiene en su propia forma,
y son usados como esto,
en una lengua de XML.
Por cierto, quiero preguntarle,
¿Quién es familiar con Vuex?
¿Quieres ir a más detalles sobre cómo Vuex funciona?
No, voy a ir.
Básicamente, las aplicaciones tienen un estado,
que es una representación de la data
de lo que está dispuesto en la aplicación,
lo que está pasando.
En las aplicaciones modernas,
tengo un estado store,
y los componentes se conectan a ese estado store,
y cambian cuando el estado se cambia.
Por ejemplo, cuando selecciono la conversación,
marco la nueva conversación que se ha seleccionado en el estado.
Y luego, la lista de conversaciones específica
con esa conversación se marcará como activa.
El chat header dispone información para esa conversación, y así.
Y los componentes de la información de este estado,
que es como el comportamiento de la default,
excepto la menú de conversación,
que tiene que ser inyectada de la parenta.
Yo necesito inyectar,
porque tengo una lista de diversas conversaciones,
y cada conversación tiene su propia menú,
y se conecta a esa conversación,
y no se conecta al store.
Y todo lo que termina con el item,
es también un niño de un contenedor,
que significa que tiene el estado, o información que necesita dispañar,
inyectada del contenedor, de la parenta.
Por ejemplo, si tengo una lista de conversaciones,
esto funciona en infinite scrolling.
Yo scroll, y el contenedor detecta cuando ha llegado al fondo,
y coge un nuevo set de conversaciones,
y crea un item listo de conversaciones,
elementos para ello, como aquí.
Esto es el actual código un poco tomado,
pero la conversación del item listo es una lista inyectada,
y luego tiene elementos múltiples como esto.
¿Cómo se desarrolló eso?
Con Babel, usé el ES6,
y construimos con Webpack, NPM,
y miramos a migrar desde NPM a Yarn.
Yarn es suposo ofrecer mejor performance,
también tiene un log file,
así que no tiene eso,
ha tried removing the node modules.
Y...
Bueno, esta es la aplicación de la aplicación de la aplicación de boilerplate.
Si usas la aplicación de CLI,
esta es lo que va a crear para ti.
Pero, a algún punto,
tenía que usar el API DOM directamente,
y esta práctica no es recomendada por la visión,
porque puede tener conflicto.
Si has already handled events
o crea elementos en el DOM,
y si puedes hacer eso
en el avión de la visión,
puede confundirlo.
Puedes añadir eventos,
y luego no remove,
o creas elementos
que la visión de la visión no es consciente
y no les remove.
Pero, infortunadamente, no tengo un tránsito.
Porque esto es, por ejemplo,
una de las cosas que tenía que enviar
durante el desarrollo.
Así que tengo este menú contextual
que permite al usuario
que quiera bloquear la conversación o delitarla,
que tiene que añadir,
como un menú de menú contextual,
cubrirlo, y luego, si clicas en otra parte de la página,
tiene que cerrarlo.
Y a la mayoría de las personas dirán,
o sea, te adecuas un evento,
los escuchadores en el cuerpo,
y cuando se ha clicado,
te cerras el menú,
que funciona, pero no en Safari.
Safari.
Y no en el iPhone,
que los usuarios de iPhone
son muy valiosos,
porque utilizan mucho,
los usuarios de poder,
así que no cortarlos,
y dices, no, no puedes hacer eso.
Entonces,
yo hice algunas investigaciones
en la investigación interna, en la searching de Google.
Así que,
he encontrado la moda de quiz,
¿estás familiarizado con la moda de quiz?
Su site fue construido por un chico duch,
que es probablemente el mejor resorcio
para las botas de JavaScript,
quizás, y más ricos.
Creo que no,
creo que necesita un bebé o algo,
pero estoy contento si no tiene uno,
porque él hace esto.
Y es como,
estas son las cosas que,
si hago ninguna de estas,
funcionará.
Entonces, primero,
el elemento target es un link o un form field.
Obviamente, yo necesito el usuario
para poder hacer clic en cualquier lugar.
Esto no podría funcionar.
El elemento target
o de cualquier de sus ancestros,
también, pero no incluyendo el cuerpo.
Entonces, imagínate,
no sé la estructura de HTML
al lado del widget.
Pueden tener una parenta,
múltiples parentes, no sé.
La única cosa que estoy seguro de que estaba ahí
fue el cuerpo, pero eso no funciona.
Tiene que tener un teléfono específico
para cualquier tipo de eventos de mouse.
Esto puede ser una función de la opción mt.
Entonces, si actualmente pones una función mt
en cualquier de sus parentes,
funciona.
O necesitas poner un punto en todo,
que, de nuevo, no era el xx, no lo sabía.
Entonces, es como,
ok, ¿qué hago?
Entonces, creí un overlay.
Entonces, cuando al abrir la menú,
actually click on the overlay
and closes the menu.
Y porque el overlay,
yo quería, en topo de todo,
necesito ponerlo exactamente
antes del teléfono del cuerpo.
Entonces, al lado del escopo del widget.
Para hacer esto,
no podía hacerla con lo que se produjo.
El framework de la visión solo me permitió
cambiar el HTML aquí,
al lado del widget.
Entonces,
de vuelta a la parte de la visión,
no tenía jQuery o nada más,
entonces, un poco de la escuela,
que me recuerda de la década de 2000.
Y a algún punto,
hice esto con el overlay y funcionó.
Y ahora, los usuarios de iPhone
pueden cerrar la menú sin refletir la página,
que es...
Fue el xx muy feliz.
También tenía otro problema,
porque,
no sé si la página...
El widget debe ser responsable.
No sé lo que tienen en la cabeza,
si tienen los correctos metátax
para asegurar que la responsabilidad
y las clases de media en el trabajo de CSS
están asociadas.
Entonces, lo que hice,
cuando el widget se creó,
me injectaría estos metátaxes en el header,
y cada vez que se destruyera,
me removemería.
Para ingerir esto en el header,
también necesito regresar al API de DOM.
Este es el flaco de la función.
Por default, se han regalado,
pero si utilizan sus metátaxes,
pueden regalarlo en la configuración.
Y eso es todo.
¿Tienes preguntas en esta parte?
Sí.
¿Tenés que entrar en el DOM 3
para el cuerpo?
Sí, el problema con eso es que no sé.
Él puede tener una sección como esta.
O sea, puede tener múltiples cosas en el cuerpo.
No tiene que tener uno niño en el cuerpo.
El cuerpo podría tener...
No sé qué tienen.
¿Tenés que entrar en su elemento?
Sí, pero si tienen un header,
que es al lado de la parent.
Tengo un contacto de contacto directo.
Si clicar en el header, no habrá nada que suceda.
Hacé eso, no te preocupes.
Eso fue la primera cosa que hice.
Y después,
vamos a ingerir todos los niños en el cuerpo
y agregar un MP para ellos.
Y es como, déjame poner un screener.
Y...
De todas formas, ¿tienes otras preguntas en esto?
Sí, por favor.
El contacto es como si fuese en el server.
¿Me siento?
No, no, no.
Es inyectado en esta aplicación.
Es como...
Así que tengo el widget,
que es la aplicación VJS,
que es el UI, lo que veis.
Y luego, para asegurar que ese communico
está correcto con el server,
utilizo el contacto, que es la componente que traigo.
¿Tienes otras preguntas?
Okay, moving forward, customizations.
Estos son...
Algunos de los lados son muy grandes
y han investido mucho dinero en sus branding,
y sus logos, y sus colores.
Y no quieren que me suba con algo que no se acercara.
Porque no.
Así que necesito permitirlos customizarlos.
Básicamente,
solo permitimos customizaciones de CSS,
pero imagínate esto.
Queremos permitirlos customizarlos,
pero no permitirlos que se rompese,
o que no se rompese tan malo.
Así que...
lo que hicimos,
adoptamos BAM,
que es el Modifier Block Element.
Esto es una manera de llamar a las clases de CSS.
Cada elemento tiene una clases específica,
que también es relativa a su parente,
y no usa cascades.
Así que remove el cascading
de cascading-style sheets,
pero se soltan otros problemas.
Es una forma controversial de hacer cosas.
Pero a algún punto,
si miras aquí,
habría el header de mensaje,
y luego, en el header de mensaje,
habría el header de mensaje,
Double Underscore Meta,
Double Underscore Thumb, y así.
Esto es el BAM syntax.
Las clases necesitan ser como esta.
Tenemos un diseño muy opinivo,
un diseño italiano,
que es el BAM.
Es ok, lo hago para él, no es un problema.
Así que...
y porque esto no revela mucho
en cascading-style sheets,
en la parte de cascading-style sheets,
usamos cascades con mezclos
para crear y assemblar las clases.
Así que solo declararía un set de propiedades
una vez,
digamos colores.
Quiero el header y el fútbol
para tener la misma color.
Así que declararía el color
como una mezcla de cascades,
y luego lo importaría en el fútbol
y en el fútbol.
¿Estás familiarizado con las cascades?
Es menos que no se siente.
Así que...
Moving forward...
La manera en la que organizamos las cascades
y las cascades
fueron en dos categorías principales.
Una, lo llamamos el layout.
El layout posicionó los elementos
y aseguró que los elementos
siempre están en su lugar,
tienen el correcto,
con y alto,
actúan responsibly
cuando el usuario
irá a un teléfono
o receta el puro.
Y luego, tenemos el equipo.
Esto mantiene los colores,
el radio bordero,
porque alguien tiene bordes
que son cerrados,
alguien tiene bordes cuadrados.
Y también,
inyectamos los iconos como URL de data.
Así que servimos iconos,
como, por ejemplo,
una pequeña foto
si quieres atacar una imagen
o un clip de papel
si quieres atacar un documento
o este tipo de...
iconos,
inyectamos en los CSS
como URL de data.
Y esto debería ser
recetado por los mercados.
Básicamente,
y servimos todo.
Servimos a un equipo default
y servimos el layout
completamente en uno CSS,
y luego pueden override el equipo.
Sí, por favor.
¿Por qué usas los URL
para evitar colores a Sprite?
¿Por qué usas los URL?
¿Quieres evitar colores a tus servers?
Porque el problema es
que esto debe estar en nuestro control.
Porque, si recuerdas,
queremos updatearlos
sin saberlos.
Así que todo necesita ser
encendido por nuestros servers,
o de S3.
Usamos S3.
Entonces,
queremos tener
los mínimos números de requerencias
para S3.
O no queremos darles
los CSS en ese folder,
pero no.
Es como,
inyectes este script
y hace todo lo mismo.
Todo lo que necesita.
Y luego,
es más fácil
que justificamos un CSS
con todo,
y nos justificamos solo dos files,
uno JS y uno CSS.
¿Alguna otra pregunta?
¿Y por qué no nos permitimos
customizar el layout?
Por ejemplo,
nuestro equipo de UX
ha hecho algunos estudios,
y por ejemplo,
esto está en el móvil.
Cuando el keyboard va,
hay ciertos elementos.
Hacemos requerencias verticales,
porque, si no,
si este tile estaba aquí,
no podríamos ver
ninguna de las mensajes.
Así que hacemos muchas de estas cosas
bajo la escala
para asegurar que el usuario
pueda usarla
sin problemas.
Se puede usarlo todavía.
Entonces, si comienzan
con un layout,
todo esto se despegue.
Así que estamos intentando
despegarse muy fuerte.
No podemos forbidirlos,
porque no seríamos buenos colegas,
pero estemos muy descartados
por justificar un CSS minivo
y no le atreves.
Entonces, la última parte.
Update automáticamente
para los mercados
y test A-B.
Para esto,
desarrollamos algo llamado FAST,
que es la tecnología de servicio.
No es el momento más brillo
cuando llegue a este nombre,
pero
estamos mucho mejor en programar
que no estamos llamando a nuestros componentes.
Así que básicamente,
¿qué hace FAST?
Es un sistema de servicio.
Básicamente, no tienen acceso
al widget.
Solo tienen un pequeño snippet
de CSS
que conecta a un servidor,
recibe el actual código
para el widget,
inyecta en la página
y le atreve.
Entonces,
cómo pasa es que,
digamos,
el usuario X
va al centro de mensaje.
Entonces,
este sitio
tendrá un pequeño snippet
de JavaScript
llamado FAST Client.
El FAST Client
conectará
a su servidor
y le preguntará
para el site X,
este es Le Bonquoire,
este es Photocasa,
este es InfoJob.
¿Cuáles son las versiones
del widget
que este sitio tiene?
El servidor responde
al JSON
que contiene información
y luego crea un script
y conecta a los tags
en la página
que atreve a la TST
y obtenga el actual payload,
obtenga el actual widget.
Entonces,
no tienen el widget
para instalar localmente.
Todo pasa
a través de la Internet
controlada por nosotros.
Y como pueden ver aquí,
las sintaxis
inunda la FAST Client,
el que es una fila minif min 128,
cuando las deje genre
y mas oportunlingue.
Esto paprika
para las componentes
커� cumulative,
no es lo que usando
por Messenger,
es decir,
quiero el widget
mensaje
para la producción
del alfamando
o la preproducción.
El repe kab feast
inder
en Mcanaugábamos
de lo que pasa en esto.
pay honeymoon
gra Block
jeune
Preförotte
Else dephony
la CAN
ری
Y luego, cuando la frontera se cumplirá,
lo que significa que todos los scripts han sido ladrados,
pueden instanciar el...
crear el actual widget.
Y si, a algún punto,
quieren remover todo lo que
hemos injectado en la página,
que es muy útil para aplicaciones de una página,
así que reaccionan,
donde no se refresca,
hay que removerlo desde el dom.
La frontera se cumplirá a una función,
lo que, si es lleno,
remove todo desde el dom.
Y si hay un error,
no widget, no nada.
Entonces, ¿cómo funciona?
Por ejemplo, como dije,
el primer cliente llama el server
y llega una respuesta como esta.
Esta es una respuesta actual.
Dice que el ambiente es preproducción.
El nombre de la recurso es MessagingWidget.
Y luego quiero las siguientes scripts,
desde el CDN,
y usamos CloudFront.
¿Estás familiarizado con AWS?
CDN, SV...
Y...
Dice que quiero este script,
y este estilo,
y estoy en esa versión.
Y esa es la respuesta.
Y...
Por lo tanto, ¿tienes preguntas sobre esta acción?
Todo el mundo lo entendió perfectamente.
Muy bien.
Fast has three main components.
Has first,
what we call the Fast API,
which is built in Java,
uses DynamoDB as a data store,
and runs on EC2.
So, as I said,
everything we do, we do in the cloud.
Then we have a set of CLI tools
that allows us to manage easily
the versions which site is assigned
to which version and so on,
or to publish a new version to the API.
These are written in Python.
And then we have the Fast Client,
which is very vanilla.js.
So, to do the Ajax request,
I manually create an XML HTTP request.
I don't know if you've seen this in the last ten years.
It has 140 lines of code, including comments,
which I'm really proud of.
We tried to sell this approach to the marketplaces.
They said, dude, we don't like it
because we don't control what happens in our site.
And then it's going to be slow
because you need to load the Fast Client first,
and then you need...
So, I had one kilo.
It's like, okay, you have one kilo.
This client needs to fit one kilo,
otherwise we're not injecting it to our site.
So, 140 lines of code,
minified, anaglified, one kilo.
It guarantees the orders of the scripts.
So, if you have multiple scripts here with dependencies,
it injects them in that specific order in the DOM,
provides a cleanup mechanism.
As I said, if you want to remove everything
that was created by the last run,
you call that function and it will remove it.
And you also have CSS before,
and you can specify a CSS selector,
and the styles will be inserted before that element,
and the same for scripts.
And why is that useful?
So, for example, we have our CSS.
If you remember, we serve the layout
and the default theme in one minified file.
And we need them to allow to override this file.
So, what we do, they create their own theme file
where they override the colors and everything.
This is loaded by the normal flow.
So, it's placed in the HTML.
The browser parses the code.
It loads the CSS.
And then, when we call fast,
we specify a CSS selector.
And this will insert the default theme
before that in the DOM.
So, we have the layout in the messaging.min.css.
We have the layout and the default theme.
And the default theme is going to be overridden by their theme.
Questions?
Make sure that they will not override the files.
I'm assuming that they're engineers, not monkeys,
although, not always the case.
But anyway, most of the time.
So, at some point, we're colleagues.
We work in the same company.
We provide them with mechanisms.
And we guarantee that in this fashion,
the widget will work and we will support it.
If they start hacking and they don't follow the documentation,
they're on their own.
And they're going to quickly revert and come back.
So, we also, like, you know,
if you don't want people to do something,
just make it really hard to do it
because people are generally lazy.
You know, if it's hard, I'm not going to do it.
And also, don't document it.
Because at some point, if it's not in the documentation,
as you can do it, they're like, ah, I'm just going to...
And there are, of course, some pros and cons with this approach.
The main con is we have around 50 kilobytes of duplications
because we always send the default team
to be overridden by them,
which is around 10 to 15 kilobytes
depending on the sizes of the icons.
You can maybe add an option to say,
okay, I don't want to go...
No, because if they break it,
we can guarantee to the final customer to the widget,
to the user that the widget will work.
So, even if they break something really,
well, not really bad,
decently bad here,
or they forget something,
the default team will come into place
and display the things correctly.
So, you can still read it.
It will still be accessible to you.
So, it's a set of pros and cons.
And with this approach, it's fast,
given the fact that we can inject things at the end
without them knowing,
we can also do A.B. tests
because without them knowing that an A.B. test takes place.
This is a very controversial topic in the company
because they're like,
dude, you're doing A.B. tests without me knowing.
I know everything.
Just turn it off, guys.
Okay, so, there was another problem with this approach.
It was called React.
A lot of our sites use React.
And if you look back,
everything here relied on, you know,
when I started building the widget,
the first customers were the smarty and PHP guys.
So, they were happy with this.
The guys with React was like, dude, you can't do that.
This doesn't work for us.
This breaks everything.
We have a router.
We have a single-page application.
We have everything modern.
So, okay, we need to support React.
So, a third repository
with a React component,
which we publish in our artifactory as a NPM package.
And this React component wraps around fast,
which wraps around the widget.
And everything is very asynchronous,
which creates a lot of bugs
that are very hard to reproduce.
It's like, it takes, you know,
like 20 times to reproduce a bug.
And it's like, okay,
because they report a bug,
and you're like trying once, twice,
and it's like, dude, doesn't work.
Send you a screenshot,
because for the tester,
it's always like the first try.
And look at the screenshot.
Okay, you're not crazy.
I'm just gonna keep trying.
And at some point, it happens.
And when it happens,
I was already bored,
and I wasn't looking on the logs.
I have to start again.
So, anyway, it was a bit of fighting a high guy,
you know, like firefighting a...
Imagine you have a spoon with water,
and you're trying to put out a forest fire, you know.
So, anyway,
in the end,
we managed to pass this part,
and when it up,
we need to test it and release it.
So, imagine this.
You have fast,
which is a standalone project with an API.
Around it,
you had a React component
that needed a React application
to actually work and be tested.
And then,
everything needed to load the widget somehow
and be tested.
So, it was like this.
So, we had some major pain points.
First of all,
as I said, the entanglement,
React fast widget.
This created a lot of edge cases
and a lot of things that...
You can't really mock it,
because if you were to mock the fast API
and the widgets API,
at some point,
the whole work would be to just keep these APIs in sync
or keep the mocks up to date.
We also use source labs.
Are you familiar with source labs?
No.
It's a device farm.
So, we run a night watch and Selenium tests,
and we run them across multiple browsers.
And source labs provides a browser farm,
and you can say,
you can configure in your Selenium client.
I want to run this test on Windows 7, Chrome,
whatever version.
I wanted to run on Mac, on Safari,
so you can have a list of browsers.
And source labs will just start VMs
with those browsers,
and you can run your tests in them,
which is a third party that we're using.
It's really good.
I actually gave a presentation on it at the Barcelona JS.
But the problem is, sometimes the machines are slow to boot.
So, running the full set of tests could take an hour.
And as a developer,
I don't want an hour till I get any feedback from my test.
I want feedback almost instantly.
Imagine this.
You change three lines, do a commit,
then for one hour you just Facebook,
then, okay, fail.
Then, imagine, after we tested,
and we needed to test with a very high degree of certainty,
because we would automatically deploy to other sites,
and if we break them,
we will never deploy to them again.
So, we needed to...
There's not a lot of room for mistakes.
And then, we also have a manual step,
step that we put in,
where tickets need to receive business validation,
because, and you may be familiar with this scenario,
you go into a meeting room,
you stay there for one hour, you talk,
then you leave, you talk the next day,
and you realize that everybody understood something different,
which is what happens.
I was talking to some of my colleagues,
I'm not saying you're lying,
I'm just saying I remember differently.
So, we need a manual step from business
to validate that what I understood from the requirements
is actually what they required in the requirements.
And we also want to do one or two releases per week
on normal flow.
Normal flow means normal development,
no panic mode.
These were our main pain points, pain points.
So, what we did, we used Night Watch.
Are you familiar with Night Watch?
It's a JavaScript framework
that allows you to write client-side tests.
So, basically, you have a browser object,
and you say, go to this URL,
make sure that this element exists,
click on this button,
make sure that this happens, and so on.
You can write automated tests, like UI tests.
And this is, as I said, source labs.
This is the browser file.
So, we would run this, like, go to that URL,
click on that, make sure that happens,
across, I think, 50-something browsers,
or browser combinations, OS and a browser.
So, we run on Android, we run on iOS,
we run on Linux, we run on Windows,
we run on Mac.
So, what we did, we first split the tests into two.
We had a minimal set of tests.
These will run against a small number of soft browsers,
and will only cover, like, core functionality.
This was to give the developer some quick feedback.
Like, if I broke something that, you know,
like you can't send a message,
that something that people will notice,
you know, or you can't access your inbox.
And it also runs on mocked responses,
which means I will always get some predefined responses
from the API.
And this also accounts for common mistakes.
For example, what happens if you get a message
that's, like, 3000 characters, no spaces,
or if the guy's name is, you know, 20 letters,
or something.
So, we can mock for this kind of edge cases,
and this act is designed to run fast,
around 10 minutes tops,
and acts like an early warning system.
So, if I develop something and I run this set of tests,
should tell me, dude, you broke some, like, core functionality,
you need to go back.
Then we have the full set of tests.
These, they run against all supported browsers,
which sometimes takes more than an hour to do.
They cover most of the functionality.
We can't actually test for everything,
because then it's maintaining those tests
will be another project on its own.
But covers most of the functionality,
and it covers the functionality that's painfully evident,
if it's missing, you know, like.
And this runs on live APIs.
So, this actually runs the test.
They deploy the widgets to a React application,
and then they Nightwatch instructs the browser
to go to that URL,
and do all the things that needs to do.
And to deliver, we had a choice.
Continuous delivery or figured release.
Of course, with this kind of,
you can't do continuous delivery.
It doesn't make even business sense.
We need to inform the marketplaces
that a new set of features
have become available magically overnight.
And we can't send them automatically
like three bug reports per day,
or like somebody updated the documentation.
You know, that's a commit.
Generate a release.
We decided to have trigger the release,
which means a human operator decides to release.
And to do that,
because if you remember,
we have to run multiple sets of tests,
we have a manual step,
and also we wanted to automate this,
because, well, I wanted to automate this
because I don't want to do manual things.
And we use Spinach,
which is an open source delivery platform.
It supports multiple clouds providers.
It supports AWS, the Amazon Web Services.
It supports Google Cloud.
It supports Microsoft Azure.
It acts like a pipeline.
It doesn't do anything.
It just starts different jobs at different times.
So each job can return a status.
I have failed or I have succeeded.
And this can take decisions.
If that job fails, move here.
Or if it succeeded, move to the next step and so on.
And the jobs are handled by Travis,
which is our integration server.
We have a company account for Travis.
And it's also used by Google Netflix.
And the reason we chose this over Jenkins
is, Shifted is a core contributor
of this open source project.
We contribute to a lot of open source projects.
We open source a lot of the things we do.
On this one, we invest a lot in this.
So obviously we're going to eat our own food,
you know what I'm saying.
Yeah, meatballs, Norwegian meatballs.
So how the pipeline looks.
In the normal flow, you have the developer.
See, I have like a...
That's me.
Basically, the developer does some changes.
The changes go to GitHub.
The push to GitHub will trigger Travis Build,
which will run a minimal set of tests in Nightwatch.
And this can happen multiple times per day.
If this fails, I know that my commit was not good
and I can do... I can revert it or fix it.
Pretend that doesn't happen.
And then when I want to release,
as I said, we're using Spinac.
And we start the release process in Spinac,
which tags the master in GitHub.
We have...
Okay, this is what we have at this time.
That will start a Travis job,
which will run a full set of tests with Nightwatch,
but against Mox.
And this will only run against the widget components.
So fast and the React wrapper are left outside.
This will only test the widget and the connector,
but with full set of tests.
If this passes,
then the code for the widget and the default team,
they get minified and they get uploaded to S3.
Then we instruct fast a new version exists.
Then we deploy that to our pre-production,
which is a React application with fast and everything in it.
And there we run a full set of tests with Live API.
So this is as close to production as possible.
And if this passes, it's like, okay,
now it works, let's see if it works
in the way that product actually wanted it to work.
So this here, the pipeline has a manual step,
which is a business validation,
in which we generally have a half an hour meeting
where everybody who added the ticket
or made the request is like, does it match?
Okay, move on.
If it passes business validation,
we upload everybody's pre-production environment,
but we don't ask them, we upload them.
We update them.
And then, if nobody complains,
this is it,
you can't really break their production,
but we're happy to break their pre-production.
We're happy, they're not,
but they're in a different office.
So we will update their pre-production,
which is visible,
if we break their pre-production,
they're gonna come and complain.
You broke our pre-production again.
If that doesn't happen,
okay, in two weeks, we push it to production,
which allows us to keep everything kind of like evergreen.
We don't need to end up with like three versions of the API,
one built like six years ago.
So anyway, this is pretty much,
this was the journey that I did in the last eight months.
This pipeline is still working progress.
We're up to here as of today.
We moved, this morning was here,
and now we actually integrated here.
We actually do the fast thing automatically,
because to upload,
to tell the fast API that a new version was created,
we have some CLI tools written in Python,
and we needed to create a pip package,
put it in an artifactory,
and then install it into the Travis container.
So anyway, cool?