This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Si es la primera vez que vienes a esta clase, que sepas que hay un repositorio en GitHub donde están todas las clases y está el código de cada una de las clases.
Si ya, por supuesto, no es la primera vez que estás y estoy seguro que muchos de vosotros habéis estado aquí clase tras clase, ya sabéis que este repositorio existe y no os lo voy a volver a comentar.
Pero bueno, que sepáis que aquí lo tenéis y de hecho en cada clase empezamos a partir de la última clase, de la anterior.
En este caso es la 6. Así que vamos a tomar esta clase, que es la 6, desde esta rama.
¿Qué vamos a hacer en la clase de hoy? En la clase de hoy vamos a hacer tres cositas.
Son dos principales y una que me apetece hacer, pero son tres cosas.
La primera, me di cuenta que, bueno, me di cuenta no, alguien puso una ISU justamente en el repositorio de GitHub donde tenemos todo el código de las clases
que nos estaba recargando en tiempo real el tema de los tweets o los debits, que nosotros le llamamos debits a los tweets del clon de Twitter que hemos hecho
y nos estaban actualizando en tiempo real. Y es cierto. Y esto lo vamos a solucionar porque creo que es bastante fácil
y vamos a ver qué tenemos que tener en cuenta para hacerlo bien, para que no nos pete de ninguna forma ni haya errores ni nada.
Es sencillo, pero bueno, hay que tener una cosita en cuenta y lo vamos a ver.
Porque esto es una de las gracias de utilizar Firebase y Firestore, ¿vale?
Así que vamos a arreglar eso. Vamos a hacer que sea de tiempo real y que si alguien añade un débit o un tweet,
pues lo que vamos a ver es que se actualiza en tiempo real. Eso por otro lado.
Segundo, vamos a ver qué es la mejora progresiva o en inglés Progressive Enancement.
Ahora no me sale la pronunciación, pero bueno, la mejora progresiva. ¿Por qué?
Porque lo he comentado en algunas clases y hay gente que tiene muchas dudas de cómo hacerlo.
O sea, yo le digo, sí, esto se hace así, y me dicen, ya, pero no sé cómo hacerlo.
Vamos a ver un ejemplo rápido de cómo lo podemos hacer justamente con lo que hicimos del Time A Go.
Porque alguien, además fue una ISU también diciendo, esto no funciona en tal sitio y por lo tanto no funciona la app.
Esto lo queremos evitar y vamos a ver cómo lo podemos lograr.
Que nuestra app siga funcionando, pero los usuarios que tienen soporte para esto le funcione todavía mejor.
Y lo tercero es que vamos a ver el soporte de NextDS con los archivos .env para tener variables de entorno en nuestra aplicación.
Y vamos a ver sus particularidades, cómo podemos aprovecharnos y cómo podemos hacer que estas variables de entorno
estén disponibles de forma pública, también en el código del cliente, porque normalmente no deberían estar ahí.
Pero las vamos a querer tener ahí, obviamente.
Así que eso es la clase de hoy y vamos a pasar a empezar desde la clase anterior, ¿no?
Utilizando el código que dejamos aquí en esta rama, la 06 Dynamic Routine Data Fetching, que esa fue la clase anterior.
Así que vamos a ver, vamos a ir por aquí.
Aquí tengo el proyecto y lo que voy a hacer es un git checkout y vamos a ir al 06 este,
que es la rama que habíamos dejado anteriormente.
Entonces aquí ya se ha descargado todo el código que teníamos.
Lo primero que voy a hacer es levantar el entorno de desarrollo para que tengamos la aplicación funcionando.
Voy a poner esto justo, ¿vale?
Y ya vamos al puerto 3000.
Vale, a ver si carga y al menos vemos que todo funciona correctamente.
A ver si lo dejo todo.
Vale, hay una cosa que me ha hecho mucha ilusión y es que algunos de vosotros habéis empezado a utilizar la aplicación,
os habéis descargado el código y habéis empezado a escribir por aquí, prueba, ¿será que todos ven esto?
Sí, no vemos tu nombre, no sé por qué no vemos tu nombre, pero sí, todos ven eso, ¿vale?
Así que, bueno, es verdad que esto es una cosa que vamos a hablar hoy, ¿no?
El cómo podemos hacer, porque ahora mismo solo tenemos la, digamos, la base de datos de producción y no tenemos ninguna otra, ¿no?
O sea, que esto es un problema que podemos tener mientras desarrollamos que esto, pues de alguna forma,
contamine la base de datos de producción.
Luego lo veremos con las variables de entorno.
Lo primero que vamos a hacer, y os voy a enseñar un poco la ISU que tenemos por aquí,
Eric Martínez Roqueñi, que es la persona que nos ha dejado estas ISUs.
Ay, quería ver su perfil para ver de dónde... Bueno, no importa, Eric, quería ver tu perfil, pero no me deja esto.
A ver ahora. Vale, Eric, ahora te voy a ver.
Aquí tenemos a Eric Martínez Roqueñi, ha dejado tres ISUs en nuestro repositorio.
Y ya sabéis que eso es interesante, ¿no? Que nos dejen ISUs, a ver qué problemas tiene y tal.
Bueno, pues estas tres ISUs, una es el timeline de la home que no se actualiza en tiempo real.
Esta es la que vamos a arreglar.
Dos, no funciona Intel, que es de internacionalización, ¿vale?
En navegadores del teléfono.
Aquí he echado de menos, y esto es un feedback que os doy en general para todos.
Cuando dejamos una ISU, lo mejor es intentar dar la máxima información posible.
Por ejemplo, no existe en los navegadores de los teléfonos.
Claro, pero yo mi teléfono sí que lo tengo.
Pero aquí lo interesante hubiera sido saber justamente el modelo en el que no le funciona
para ver exactamente a ver si lo podríamos simular, ¿vale?
Entiendo el problema, pero cuanto más contexto damos en un problema, mucho mejor.
Igualmente, esto también lo vamos a solucionar.
Y el tercero, que este no lo vamos a solucionar porque, como digo, es un poco vago y no entiendo muy bien.
Dice, los estilos de home no funcionan cuando visitas la app desde un navegador de un teléfono.
No sé si es que se ve mal, a lo mejor un screenshot nos hubiera ayudado.
Bueno, al menos vamos a hacer dos de tres, cosa que no está mal.
Espero que a nuestro amigo Eric le sirva.
Y si hace falta, la semana que viene, pues seguimos arreglando cositas, ¿vale?
Además, está interesante para lo del timeline.
Así que mira, aquí tenemos a Eric, que justamente nos había dejado esta prueba.
Así que va por ti, Eric.
Vale, vamos a empezar por lo de hacer que el timeline se actualice de forma automática, ¿vale?
En real time.
¿Qué significa esto?
Si yo ahora abro otra pestaña de nuestro proyecto y yo aquí, pues, escribo un debit y digo, ¿qué está pasando?
Digo, vamos a probar el real time, ¿no?
Y le digo a debitear.
Aquí ha funcionado correctamente y ahí vemos nuestro nuevo tuit, que además hace cero segundos.
Es un poco raro.
Ah, mira, pusimos esto de que cada cinco segundos se actualizase.
Qué gracioso.
Vale, pues, el tema es que tenemos esto bien.
Aquí ha salido bien.
Pero si vamos a la otra pestaña, aquí no lo tenemos.
Esto lo podemos solucionar con Firebase.
Y es lo interesante, ¿no?
Que si alguien, esto es porque lo he hecho yo mismo,
pero otra persona ahora mismo podría enviar un tuit y lo interesante sería que automáticamente, ¿no?
En tiempo real, viésemos esa actualización.
Y ya vemos que no la tenemos.
Tenemos que actualizar para verla.
Así que vamos a emular, como lo que queríamos hacer, a emular justamente el Twitter.
Necesitamos esta funcionalidad.
Es bastante más sencillo de lo que parece porque al final Firebase está más que preparado para hacer esto.
Así que lo que vamos a hacer es ir aquí, a nuestro Firebase Client.
Aquí ya teníamos todas nuestras llamadas, todo lo que hacíamos.
Una de ellas es esta, ¿no?
La de fetch latest debits.
Esto yo lo hice al principio porque solo queríamos recuperar los resultados, ¿no?
Lo que tenemos que hacer es bastante similar, pero un poco diferente.
Cambian una cosita.
En lugar de decirle que queremos hacer un punto get y que esto nos devuelve una promesa
donde tenemos ya los resultados,
lo que queremos es escuchar cada vez que tengamos resultados.
Cada vez que ocurra algo, ya sea que se añaden, se eliminan, o lo que sea,
queremos saber qué ha ocurrido y actualizar la página con esa información.
Entonces, esto lo voy a dejar tal cual.
Lo que sí que voy a hacer es separar este...
Tenemos ya un método que es map user from Firebase,
que básicamente lo que hace es recuperar algo de Firebase y lo mapea a un objeto.
Pues eso mismo, en esta función lo estamos haciendo aquí.
Si os fijáis, lo tenemos aquí, ¿no?
Estamos mapeando algo.
Entonces, voy a hacer aquí una constante, una función,
que va a ser map debit from...
Debit es tweet, ¿vale? Es como un tweet.
Firebase, Firebase...
From Firebase to debit object, por ejemplo.
Y aquí lo que le pasamos es el documento que recibimos de Firebase.
Porque en Firebase no nos devuelve el documento tal cual nosotros lo queremos,
sino que tenemos que hacerle alguna transformación.
Aquí tenemos el documento y lo que tenemos que hacer, básicamente,
que es la transformación que hacíamos antes,
lo que hacíamos aquí, pues lo vamos a pegar aquí, simplemente, ¿vale?
Y ya está.
Así que este map debit from Firebase, bla, bla, bla,
lo que podemos hacer es ejecutarlo aquí.
Podríamos hacer un return de esto.
Y esto debería funcionar exactamente igual.
O sea, lo que hacíamos antes, pues ahí en todas estas líneas,
ahora lo hacemos una función, lo hemos extraído y ya está.
Parece que todo funciona bien.
Bueno, como siempre os digo, las funciones en JavaScript son de primera clase,
o sea, son ciudadanos de primera clase, ¿no?
Bueno, esto quiere decir que las funciones pueden funcionar como parámetros.
Así que si nos fijamos aquí en la firma de esta función, ¿no?
Que recibe un parámetro doc y es una función que ejecuta una función que recibe doc,
esto al final lo que podemos hacer para simplificarlo sería hacer esto, ¿vale?
Pasarle al map justamente la función que recibe ese doc y ya lo tendríamos.
Y esto funcionaría exactamente igual.
Esto ya tenemos el map, ya lo hemos separado.
Ahora lo que tenemos es que crear este nuevo método que os digo,
que es ligeramente diferente al que teníamos del fetch.
Le vamos a llamar listen latest debits.
Bueno, ya te fijas que he puesto listen, no fetch, porque fetch es como una vez, ¿no?
Listen es como que vamos a escuchar lo que ocurra, ¿no?
Así que eso es lo que justamente queremos.
Vamos a hacer por ahora un return muy parecido a lo que estábamos haciendo antes.
Tenemos el collection, que es el de debits, que más o menos son las mismas líneas.
¿Cómo lo ordenamos?
Pues lo vamos a ordenar de forma descendiente por la fecha para que los más nuevos estén arriba.
Y ahora, y aquí está lo interesante, lo que queremos no es hacer un punto get,
que nos va a devolver justamente el resultado de ese momento,
sino lo que queremos es que on snapshot, cada vez que ocurra algo,
cada vez que pase algo en esa colección, ¿vale?
Vamos a ver esos documentos.
Este on snapshot nos devuelve un snapshot, ¿no?
Nos dice, bueno, tenemos un snapshot de lo que ha ocurrido.
Directamente lo que podemos, bueno, vamos a poner snapshot directamente,
pero igual que aquí teníamos, aquí estamos extrayendo ya los docs,
si ponemos snapshot, y esto es una cosa muy chula que tiene la librería de Firebase,
si ponemos snapshot punto, como está todo tipado, pues ya podemos ver todo lo que nos ofrece.
Y una cosa que tiene es el punto docs, que justamente son todos los documentos, ¿no?
Así que hacemos un punto docs y ya tendríamos aquí los documentos de ese snapshot.
Así que lo que vamos a hacer para simplificar esto es como lo habíamos hecho antes,
extraer directamente el docs de aquí y así no tenemos que hacer esto.
Ahora, con estos docs lo único que tenemos que hacer es este mapeo, ¿no?
O sea, es muy similar a lo que ya teníamos.
Realmente, o sea, sería exactamente lo mismo, ¿no?
Devolverlos y ya está.
Pero claro, los queremos devolver.
Lo que queremos hacer con esto es devolverlos, porque no podemos devolverlos.
Si lo que queremos es ejecutar algo cada vez que ocurra esto, ¿cómo lo hacemos?
¿Cómo hacemos que algo se ejecute cada vez que ocurre este snapshot?
No podemos hacer un retun y ya está.
Esto no es tan sencillo como hacer esto.
No, sino que lo que tenemos que hacer es utilizar el concepto de callback.
Así que le podemos llamar callback o le podemos llamar...
Le voy a llamar callback por ahora.
Básicamente, el parámetro que va a recibir este método es una función que se va a ejecutar
cada vez que tenemos un nuevo snapshot, ¿vale?
Cada vez que ocurra algo con esto, ya sea que se añaden o que se eliminan,
pero si se eliminan lo que nos llegará en los documentos, ya no existirá ese documento
porque se ha eliminado, ¿vale?
Así que en esos nuevos documentos vamos a ejecutar esta función pasándole esos nuevos documentos, ¿no?
Sería pasando...
Vamos a ponerlo así, que quedará más claro.
Vamos a poner new debits, que los tenemos aquí con el docs.map.
Docs, que son todos los documentos.
Los mapeamos utilizando esta función que hemos hecho antes
y llamamos al callback y le pasamos justamente estos new debits, ¿vale?
Le pasamos una función de forma que esa función se ejecute
cada vez que se ejecute este on snapshot con esos documentos.
Y lo que hacemos con ese callback es pasarle todos estos nuevos debits que queremos
y ya mapeados justamente como los queremos utilizar.
No sé si hasta aquí se ha visto claro.
Igual callback, a ver, callback es que es como se llaman normalmente este tipo de cosas, ¿eh?
Le podríamos poner algo más semántico, como handle new debits, no sé.
Pero ahora lo vamos a ver más claro cuando pasemos a utilizar esta función, ¿vale?
Si no os gusta callback, lo podéis cambiar.
Por ahora vamos a guardar los cambios y por ahora funcionaría todo igual
porque no estamos utilizando esta función.
Pero ahora os voy a leer un poquito, ¿vale?
Y utilizamos, nada, esta función en un momentito.
Vamos a ver qué me contáis y vamos.
Andrés Sánchez, eres muy grande.
Me tengo que ir, pero lo veré luego.
Mil gracias por tus clases, por tus clases.
Muchas gracias a ti.
Tus cursos valen oro, dice Andrés Campuzano Garcón.
Muchas gracias.
Junior García, supongo que está contestando a alguien.
Ah, sí, a Alfonso Luis.
Entonces, efectivamente, yo utilizo OneDark Pro.
Es mi tema favorito, Visual Studio Code.
Me gusta con el estilo vivid y con vivid es porque los colores están como más vivos.
Y con negritas y cursivas, ¿vale?
Por si veis que tiene muchas negritas y alguna cursiva, es porque lo tengo activado.
Esto se puede activar en Visual Studio Code.
Tengo pendiente de hacer un vídeo de esto, que me lo pedís un montón, ¿vale?
¿Qué más?
Matías me dice, ¿usaste el Incremental Static Generation de Next?
Entonces, no lo usé, no sé si lo usamos la última vez.
No lo usamos, no lo usamos.
No lo hemos usado, pero lo comentamos en la anterior clase, en la de hace dos semanas.
Y la idea es que lo veamos.
Quiero añadir la posibilidad de editar los debits y entonces necesitaremos el Incremental Static Generation.
Y creo que así lo podremos ver, que será muy interesante.
Víctor Vejas, con razón, dice, ¿de dónde le llega esa función callback o está predefinida?
No te preocupes, le llega por parámetro, ¿no?
Es una función que le llega por parámetro otra función.
Y ahora veremos de dónde le llega esa función.
Cuando la usemos, quedará bastante más claro, ¿vale?
A ver, antes de que se me van añadiendo los chats, ¿qué más, qué más?
A ver, alguien dice, gracias a él aprendí webpack.
Muchas gracias, hombre.
¿Para cuándo la segunda puerta de webpack?
Pues me la apunto, porque la verdad es que tengo muchas ganas y hace tiempo que no lo hago.
DreamCode dice que se llegó tarde.
Nunca llegas tarde, siempre se llega a tiempo.
Ana Paula dice, genial, te pasaste.
Creo que esto iba por lo del tema de YouTube, que he puesto la lista de reproducción.
Me alegro que te guste.
Me hace mucha ilusión, porque ahí está un ratito.
Vale.
Andrés Arai dice, hola, mira, que cuando hago el committee no se suben los archivos de una carpeta,
pero sí de la otra.
Ya revisé mi gitignore y no puedo.
Habría que verlo con más detalle, Andrés.
Entonces, si tienes por ahí el repositorio, pues pásalo y a ver si le podemos echar un vistazo.
Vale, vale.
¿Qué más?
¿Qué más por aquí?
A ver, lo estoy viendo un poco en diagonal.
Pablo Rodríguez, notado en superchat.
¡Qué bonito!
¿Qué tiene?
¿Es un hámster dándole al teclado?
¡Qué bonito!
Me encanta.
Midu, siempre crack, un pequeño aporte.
Espero ayude, siempre ayuda.
Ayuda, solo que estés aquí, ayuda.
Y tu aporte ya es, vamos, descomunal.
Pablo, un abrazo a ti y a ese hámstercito que me ha robado el corazón.
Que es súper bonito.
Andrés está por aquí.
¿Qué más?
¿Dónde le llega?
Midu, un poco fuera de tema.
Para hacer las rutas protegidas, ¿usarías High Order Components o de qué otra forma?
Creo, no lo íbamos a ver, pero High Order Component puede ser una forma bastante interesante.
Creo que High Order Component podría ser.
Soy nuevo.
¿Qué anden haciendo?
Mr. Banano, estamos haciendo un clon de Twitter.
Esta no es la primera clase.
Creo que es la sexta.
Pero creo que es interesante.
Hoy estamos haciendo que funcione en tiempo real los resultados.
Y, hombre, es un efecto guau que está bastante guay.
¿Qué más?
Pablo me decía que tenía una consulta fuera de la clase.
¿Qué patrón o librería para manejar usuarios, roles y permisos?
¡Buah!
¡Buah!
Pablo, esto me da para una clase entera.
La verdad es que no sabría decirte ahora mismo qué patrón o librería.
No se me ocurre que haya una librería sencilla así para manejar usuarios, roles y permisos.
Es que normalmente casi siempre esto lo he visto hecho más a mano que otra cosa.
Y no se me ocurre qué patrón o qué...
No se me ocurre.
Me has pillado ahí fuera de ti esto.
No sé.
Pensaré sobre ello.
A ver si se me ocurre algo.
Santiago.
Lo de las funciones como objeto de primera clase y ahorrarse código.
¿No le quita legibilidad?
Pues, Santiago, yo creo que todo lo contrario.
De hecho, vamos a verlo.
A ver.
Sobre la legibilidad.
Tenéis...
Hay dos opciones, ¿no?
A mí me parece interesante esta legibilidad.
A ver, ¿a qué es subjetivo aquí cada uno?
Una sería esta, ¿no?
Y la otra sería docs.map, que el doc sea mapdebitdoc.
Esta sería.
Entonces, si realmente entiendes el concepto, ¿no?
De utilizar la referencia de la función directamente porque tiene la misma firma que necesitas,
a mí me gusta bastante esta.
Porque, hombre, está...
Dices, vale, voy a mapear docs.map, directamente le paso el doc a esta función y ya está.
A mí me gusta más.
Pero, bueno, si veis más claro esta, aunque sea innecesario porque está creando una función para llamar a una función que le está pasando el mismo parámetro,
lo bueno, lo que sí que te diría que tiene de ventaja esta, la de la línea 73,
es que si el día de mañana necesita hacer algo más, pues, hombre, es más fácil de añadirlo.
Es subjetivo, ¿no?
Porque también la otra solo puedes añadir y al final no es gratis.
Pero sí, aquí podrías hacer alguna cosa.
O un if.
Eso le ve una ventaja.
O sea, que no te voy a decir que no, no, son todos ventajas la otra.
Creo que es subjetivo, pero, bueno, ahí lo...
A mí legible me parece, ¿eh?
Y además queda súper cortito, no tienes que crear una función anónima ahí en medio.
Creo que si se hace en una sola línea y no se abusa, obviamente, creo que puede quedar bastante bien.
¿Qué silla abusas?
Tengo un vídeo donde hablo de todo mi setup y hablo de la silla.
Desde Ecuador, gracias por su enseñanza.
Gracias a ti, Rolando Cachipuendo.
Gracias a ti.
¿Salto de React.js a Next.js es mucho?
No es mucho.
Tiene sus cosas, pero si te ves el curso que hemos preparado, vamos.
¿Se acabaron las vacaciones?
Ay, sí, Jefferson, se acabaron las vacaciones.
Lagrimita.
Midu, ¿cómo haces un High Order Component con Get Server Site Props?
Saludos, crack.
Pues no puedes hacer como tal un High Order Component, pero sí que puedes hacer una composición de Get Server Site Props.
O sea, puedes tener una función que llames desde fuera.
O puedes hacer el High Order Component y que dentro llame al Get Server Site Props que tienes desde fuera también.
A ver, no sé si lo vamos a ver, pero se puede hacer.
Es una cosa que no es imposible.
No sé, claro, el Get Server Site Props tiene un export.
Ahí tengo dudas si sería tan sencillo.
Con el Getting Site Props era más fácil porque mutaba el objeto.
Pero bueno, lo miraré.
A ver, ¿qué más?
Madre mía, cuántas preguntas.
Habéis venido con ganas, ¿eh?
¿Qué más?
Dice Adrián, al Snapshot se le puede colocar un límite de resultados o que cada que detente cambios traerá todos los documentos de Firebase.
¿No consumirá mucho ese proceso al haber ya muchos debits?
Efectivamente, tienes toda la razón.
De hecho, creo que podemos utilizar limit y ponerle 20.
No había pensado en ello porque como tenemos tan pocos.
Pero sí, podemos limitarlos.
Creo que poniendo punto limit 20 y luego un Snapshot ya debería funcionar.
Creo que esto debería...
A ver, si esto...
Sí.
Vamos a probarlo.
Ahora lo probamos.
Si le pongo un 1, si te parece, lo voy a comentar y luego lo probamos.
Así, ¿vale?
Creo que más o menos por aquí.
Luego continuamos, ¿vale?
Por ahora ya tenemos este y vamos a ver que...
Vamos a ver cómo seguimos.
Venga.
Que si no, vamos a utilizar este ListenLatestDevits.
Para eso lo estamos utilizando en la página Home.
Así que vamos aquí al UseEffect y aquí estamos utilizando este FetchLatestDevits.
Y aquí ya se ve el problema, ¿no?
Porque esto se ejecutaba solo una vez y esto no es exactamente lo que queremos.
Así que vamos a hacer que esto pete comentando este método que ya no vamos a usar más, ¿vale?
Entonces esto peta porque dice, oye, no puedes importar esto.
Y lo que vamos a hacer es importar el Listen que hemos creado, que ya nos dice que no lo estamos usando.
Vale.
Lo que vamos a hacer por ahora.
Vamos a comentar también esto.
Vamos a comentar esto, ¿vale?
Guardamos los cambios.
Y ahora, funcionar funciona un poco raro, ¿eh?
Porque no debería salir nada.
Ahora, vale, vale.
Ya digo, ¿cómo va a salir algo?
Vale.
Entonces vamos a empezar a escribir.
Si tenemos un usuario, ¿qué tenemos que hacer?
Pues lo que tenemos que hacer es ejecutar este ListenLatestDevits, ¿vale?
Y este ListenLatestDevits, ¿qué hemos dicho que le tenemos que pasar como parámetro?
Un callback.
¿Y qué es un callback?
Una función.
Así que le vamos a pasar una función, ¿vale?
Vamos a poner aquí por ahora un console.log.
Y vamos a poner aquí ListenLat, ¿vale?
Como que lo hemos escuchado.
Vamos a abrir las herramientas de desarrollo.
Vale.
Aquí pone que se ha escuchado dos veces.
Si refresco eso, que se ha escuchado dos veces.
A ver.
Vale.
Una, una.
Lo que pasa es que con el hot module replacement, bueno, react fast refresh, puede ocurrir esto,
¿no?
Que parece que la escuchamos de una vez.
Solo la ha escuchado una.
¿Por qué?
Porque la primera vez ya debería tener resultados.
Así que este callback que le estamos pasando por aquí, ¿qué le está llegando como parámetro?
Justamente los debits, ¿no?
Así que lo que tenemos que hacer aquí es tener, tendríamos, no sé si llamarle new debits, ¿vale?
New debits.
Así que ahora ListenIt, With, y vamos a ver estos new debits.
Vamos a guardar los cambios.
Vale.
Y aquí podemos ver un poco lo que tenemos, lo que hemos escuchado, ¿no?
Tenemos estos 14 documentos que justamente son estos debits o tweets que tenemos que mostrar.
Así que ahora lo único que deberíamos hacer es actualizar el estado con esta información.
Así que este SetTimeline utilizamos justamente estos new debits.
Guardamos los cambios.
Y a ver, ahora funciona.
Bueno, funciona correctamente.
Sí, funcionar funciona, ¿vale?
Ahora está bien.
Funciona bien.
Pero hay alguna cosita aquí que no está del todo bien, aunque luego lo veremos.
Por ahora vamos a quitar estos comentarios.
Vamos a ver lo del limit que le he prometido a nuestro amigo que lo íbamos a hacer.
A ver si esto funciona como debería.
Voy a refrescar por aquí.
Y efectivamente, aquí podéis limitar los resultados.
Le ponéis un punto limit y el número de resultados que queráis y ya está.
Vamos a poner 20, ¿vale?
Para que no se nos vaya.
Pero 20 yo creo que ya está bien.
Tampoco tenemos más de 20 ahora mismo.
Pero por si poco a poco vamos añadiendo más.
Vale, hasta aquí esto funciona exactamente igual de como estaba funcionando antes.
Así que hasta aquí no hay ninguna diferencia.
El tema es que ahora lo que se está haciendo aquí realmente es que estamos escuchando cuando ocurre eso, ¿vale?
No estamos recuperando los datos y ya está.
Lo que le estamos diciendo a Firebase es cada vez que ocurra esto voy a ejecutar este callback, ¿no?
Esto que teníamos aquí.
Esto que teníamos aquí.
De hecho, y aquí tenéis otro ejemplo de cómo utilizar las funciones como parámetros.
Si te fijas aquí claramente, este parámetro es justamente el mismo que le pasamos al setTimeline.
Así que lo que podríamos hacer, y a mí me parece un poquito más legible, pero ya os digo que esto es subjetivo.
Si os gusta más el otro, no pasa nada.
Podríamos hacer esto, ¿no?
Directamente el parámetro que son los new debits, pues se lo pasamos directamente al setTimeline.
Esto funciona porque el parámetro es exactamente el mismo, ¿vale?
Esto es importante que os sepáis.
Si aquí tuviésemos otra cosa, esto no funciona, ¿no?
Esto se vuelve otra cosa.
Y aquí new debits como la segunda posición de los parámetros, entonces esto no funcionaría, ¿vale?
Esto ya no hace magia.
Sí que necesitaríais esta forma, ¿vale?
Solo funciona porque es exactamente igual la firma, el contrato que tienen las dos funciones.
La anónima recibe el new debits como parámetro y justamente el setTimeline también como primer parámetro recibe el new debits.
Por lo tanto, podéis hacer esto, ¿ok?
Si no, no funciona.
A ver si luego vais a hacer cosas muy raras por ahí.
Entonces, ya tenemos esto.
Vamos, si os parece, la gracia que habíamos hecho esto era crear un debit, ¿no?
Así que voy a abrir una nueva pestaña y a esta nueva pestaña voy a escribir un nuevo debit para ver si en la pestaña inicial se refleja este nuevo cambio.
Vamos a ver si funciona la actualización en tiempo real.
Y vamos a poner aquí un emoji.
Emoji.
Aquí ha funcionado bien y aquí también ha aparecido.
De forma automática ha recuperado ese nuevo dato, ¿vale?
Y se ha actualizado todo sin ningún tipo de problema.
Pero hay un pequeño problema, me parece a mí.
O es raro que no, es raro que haya funcionado todo bien, ¿vale?
Y ahora te explico por qué.
De hecho, aquí está el problema, ¿vale?
Aquí está el error.
Ya decía yo, digo, pensaba que iba a petar, ¿eh?
Directamente, no te voy a engañar.
O sea, me alegro, es que React a lo mejor dice, oye, esto no funciona bien, pero pensaba que a lo mejor al intentar actualizar el estado de un componente que se haya desmontado a lo mejor ahí no le iba a gustar.
Pero mira, solo deja un warning y pensaba que a lo mejor veíamos una página en blanco.
Vale, ¿qué ha ocurrido aquí?
Te voy a explicar qué ha ocurrido, ¿vale?
Cuando yo estaba en la página, vamos a abrir otra pestaña para que se vea claramente.
Cuando estamos en esta página, que esta es la página home, estamos actualizando este useEffect, ¿no?
Y este useEffect, lo que tenemos aquí es una suscripción.
Esto es típico, ¿vale?
Esto es un caso típico, fruto de miles de millones de problemas en React.
Así que esto lo tienes que tener cristalino.
Vale, aquí tenemos un efecto.
Que se suscribe algo.
¿Qué está pasando con esto?
Que el efecto, que se suscribe algo, se ejecuta cada vez que se renderiza la home.
¿Qué problema podemos tener aquí?
Varios problemas.
Uno, que nos estamos suscribiendo más de una vez.
Por ejemplo, si cambia el user, pues volverá a suscribirse y por lo tanto que tendremos dos suscripciones que estarán activas.
Eso es un problema.
Segundo problema.
Lo que estamos haciendo en este efecto, no estamos limpiando la suscripción.
De forma que cuando el homepage, la página de homepage, se desmonte, esta suscripción seguirá funcionando.
Y es justo lo que ha pasado.
¿Por qué?
Porque nosotros hemos ido aquí a crear un tuit, ¿no?
Ahora en crear un tuit estamos en otra página.
Por lo tanto, la página home se ha desmontado.
Si yo creo el tuit, ¿qué va a ocurrir?
Pues que vamos a añadirlo en Firebase.
Firebase nos va a informar y la suscripción que habíamos hecho aquí se va a ejecutar.
Y va a ejecutar el set timeline y este estado se va a intentar actualizar.
Pero ¿qué pasa?
Que este estado es de la página home.
Estamos en la página crear un tuit, ¿no?
Aquí estamos en la página crear un tuit.
Entonces, ¿qué pasa?
Que va a intentar actualizar el estado de un componente que está desmontado.
Y esto es algo que tenemos que evitar.
Esto es un problema muy típico también con, por ejemplo, un fetch.
Aquí a veces ponemos un fetch, punto den, ¿no?
Algo así, ¿no?
Y cuando tengo los resultados, pues hacemos aquí un set response de...
Algo así.
Pero claro, ¿qué pasa?
¿Qué ocurre si en el tiempo, como esto es asíncrono,
qué ocurre en el tiempo en el que esto está contestando y el usuario navega a otro sitio?
Pues que cuando ejecuta este set response ya la página no existe.
Entonces intentas setear el estado, actualizar el estado de un componente que se ha desmontado.
Esto es un problema.
También cualquier suscripción, por ejemplo, un set interval y no limpiarlo.
Cosas así.
Y en este caso nos está ocurriendo.
El error que vemos aquí es porque ha intentado actualizar la página homepage cuando estaba totalmente desmontada.
Pero bueno, no nos preocupemos.
Todo este tocho es para algo.
Todo lo que os he comentado, todo este tocho, es porque lo vamos a arreglar.
¿Cómo lo podemos arreglar?
A ver, voy a guardar los cambios.
Y ahora vamos a ver cómo lo arreglamos.
Lo que tenemos que hacer primero, esto, aquí he puesto un return, ¿vale?
Y este return que he puesto aquí, aparte de porque normalmente vamos a querer saber si ha ocurrido o no ha ocurrido en el caso del listen, en el otro que habíamos visto, bueno, que lo he borrado, ¿eh?
Pero normalmente lo que te devuelven muchas operaciones de Firebase, lo que te devuelve en realidad es una promesa, ¿no?
Porque estás esperando un valor futuro.
Entonces tienes una promesa para que cuando se resuelva tengas ese valor.
Pero en este caso que estamos escuchando algo, no te devuelve el valor, ¿no?
Como he dicho antes, no queríamos hacer dentro un return.
No tenía tanto sentido hacer un return.
Por lo tanto, esto no nos devuelve una promesa, sino que nos devuelve un objeto, que es un objeto no, una función para poder desuscribirnos de esta suscripción.
Como para decirle, oye, deja de escuchar esto, ¿vale?
Esto lo que nos va a devolver es un método que podemos llamar para eliminar la suscripción que teníamos.
¿Cómo lo podemos utilizar?
Pues este listen, que ya estamos, este return, ya lo tenemos aquí.
O sea, que esto está devolviendo justamente este método para desuscribirnos.
Lo que tenemos que hacer aquí, en este listen, es desuscribirnos.
Así que lo que podríamos hacer aquí es tener un subscribe.
Lo voy a dejar fuera porque tengo, bueno, vamos a dejarlo así.
Un subscribe.
Lo vamos a guardar aquí.
Y ahora, ¿qué tenemos que hacer con esto?
Pues básicamente lo que deberíamos hacer es devolver en el efecto cómo tenemos que limpiar los efectos.
Y el efecto que queremos limpiar justamente es que si tenemos un método en subscribe, lo ejecutemos, ¿vale?
¿Por qué lo estoy haciendo así?
Porque tengo dudas.
Lo más correcto sería hacer esto, ¿no?
Un subscribe.
O lo más correcto.
Lo más correcto no sabemos si sería más correcto.
Pero más fácil sería hacer esto.
Pero ahora tengo la duda de si realmente lo que hacemos dentro de un efecto,
a la hora de limpiarlo, de limpiar los efectos, puede ser condicional.
Porque hay algunas reglas, por ejemplo, no podemos hacer esto, ¿vale?
Un hook no lo podemos tener aquí así.
Yo creo que dentro no debería haber ningún problema en hacer un condicional.
Lo podemos probar.
Lo podemos dejar así.
Y luego, si vemos en algún momento que peta, pues lo que podemos hacer es eso.
Tener un subscribe, que seguramente puede ser una buena práctica porque de esta forma siempre está devolviendo una función.
Y lo único que hará es que si está en un subscribe, pues que se desuscriba y ya está.
Y de esta forma lo dejaríamos así.
¡Pam!
Lo dejaríamos así.
Tenemos esta variable aquí fuera.
Si hay un usuario, pues entonces ejecutamos la suscripción,
recuperamos el método este para desuscribirnos
y para limpiar el efecto, lo que hacemos es mirar si tenemos esta suscripción
y entonces nos desuscribimos y la ejecutamos.
Con esto, a ver si lo he hecho bien, que de esto yo soy hablando,
lo que deberíamos hacer, ahora tenemos tres pestañas, ¿vale?
Así que lo que voy a hacer en esta tercera es añadir este...
Voy a refrescar por si acaso.
Tenemos esto, tenemos esto.
Y aquí voy a abrir las herramientas de desarrollo para ver si nos vuelve a ocurrir ese warning.
Así que probando que estamos limpiando bien la casa de suscripciones activas.
Le ponemos aquí un guiño lengua.
Vale, ahora ha funcionado bien y no tenemos ningún tipo de warning.
Y podemos ver que se ha actualizado en todos los sitios.
Se está actualizando automáticamente.
Ese salto que has visto es porque Firebase es lo suficientemente listo para decir,
vale, cuando recupero el foco en la página, entonces voy a actualizarlo.
Así que con esto ya tendríamos solucionado el problema.
Hay que tener en cuenta que hay que limpiar las suscripciones.
Este ejemplo sé que es muy básico y puede parecer una tontería,
pero hay muchas veces que esto puede ser un verdadero caos en tus aplicaciones
si no lo tienes en cuenta, ¿vale?
Puedes empezar a navegar, por ejemplo, una parrilla de búsqueda,
unos resultados de búsqueda, ¿no?
Y entonces que sea siempre el mismo componente.
Y ese componente de resultados de búsqueda, pues que tenga una suscripción abierta, ¿no?
Entonces tú vas navegando, vas filtrando y siempre utilizas el mismo componente
y entonces de repente la página peta, porque a lo mejor tienes 15 suscripciones, ¿vale?
Y eso al final se va convirtiendo en una cola donde esas suscripciones siguen abiertas
y estás intentando escucharlas.
Cuanto más pequeño es el componente y más lo estés reusando, puede ser más problemático.
Solo que ten en cuenta esto también para los fetch, que también puede ser algo interesante, ¿no?
El fetch, tienes dos formas, una buena y una mala, ¿no?
Bueno, una, no es que sea incorrecta, pero es mala práctica, que es básicamente dejarte un flag, ¿no?
De decir, cuando esto del fetch, aquí tenemos una API.
Además he visto por ahí que alguien lo ha preguntado.
Creo que me lo está preguntando.
Cracks4, ¿vale la pena cancelar todos los fetch que hacemos una app?
Normalmente sí.
Y de hecho, creo que tengo un artículo a medias por ahí de cómo cancelar una llamada fetch a una API.
Porque es relativamente fácil y vale la pena.
Una práctica que se puede hacer sería tener un flag si esto está montado, decimos true,
pero cuando lo desmontamos lo ponemos a false.
De forma que este fetch, cuando tenemos aquí la respuesta res.json.den y aquí tenemos la response
y hacemos setResponseResponse, cuando hacemos esto podemos mirar si está montado.
Y esta variable, esta variable que hemos añadido aquí, bueno, imaginad que esto está dentro de, a ver, voy a comentar esto para que se vea.
Algo así, ¿vale?
HTTP, API.com y tu clase.
Vale.
Pues podéis intentar hacer algo así.
Esto es como un flag para saber si está montado o no está montado el componente.
Esto, algo parecido lo podéis hacer, pero normalmente es mejor a lo mejor utilizar signals.
Una señal y puedas abortar el fetch, porque esto no te evita que la llamada a la API se haga.
Entonces, claro, eso suele ser una mala práctica, porque tú estás dejando que la API, esa llamada se haga,
en lugar de abortar la llamada de la network.
Bueno, eso a lo mejor para otro vídeo del canal, ¿vale?
Que si no, me lío.
Así que voy a ver si tenéis alguna duda o algo.
Dejadlo en el chat, que ahora voy a ver qué me comentáis, ¿vale?
Porque de mientras, vale, voy a ir cerrando todo esto.
Esto ya lo tenemos solucionado.
Ya tenemos con esto las actualizaciones en tiempo real, ¿vale?
Así que nada, voy a ver qué me comentáis.
Leí que para desuscribirse hay gente que usa abortcontroller.
Sería conveniente usarlo acá.
Ahora, el abortcontroller es justamente la señal esa que comentaba para el fetch, ¿vale?
Para el fetch tiene todo el sentido del mundo.
En el fetch es como lo haríamos con el abortcontroller.
Pero en el caso este, la de suscripción de Firebase solo lo haríamos así.
Para el fetch, lo recomendable sería justamente hacer el abortcontroller,
utilizar el signal para evitar que se termine de hacer la llamada cuando no es necesario.
Y eso, yo diría que es la mejor práctica.
Haré un vídeo que me parece súper interesante, ¿vale?
¿Usas Mac o Windows?
Pues utilizo MacOS.
No sé si lo conocéis, pero sí, utilizo MacOS.
Y lo comento en un vídeo de mi setup, que ahí comento todo lo que utilizo y por qué lo uso.
¿Vale?
Miguel Longar.
¿Qué tal Midu? ¿Se puede usar ESI en Next.js?
Pues no sé qué es ESI.
Coméntamelo, Miguel, que no sé qué es ESI.
Naro dice, trabajas con TDD de vez en cuando, pero no para todo.
Por ejemplo, cuando creo componentes y cosas así, pues no utilizo TDD.
Pero hay veces que para métodos con lógica de negocio y tal, pues primero hago el test y luego hago la implementación y lo hago utilizando TDD.
Pero cuando hago componentes de React, no utilizo TDD.
De hecho, tampoco tanto.
Tampoco utilizo tanto TDD.
A veces sí, depende.
No sé, es que depende un poco del momento.
No lo tengo en mi día a día y estoy todo el día con TDD, pero hay veces que sí que me ha resultado útil.
Sobre todo cuando tenía muy claro, tenía muy claro qué es lo que tenía que entrar y lo que tenía que salir y cómo tenía que funcionar por fuera, pero no tenía tan claro por dentro.
Y me ha venido muy bien como para entender mejor lo que tenía que hacer, qué problema me podía encontrar y cosas así.
Vale.
¿Qué theme usas de ZSH?
ZSH.
Oh my, ZSH.
Utilizo Pure.
Pure theme.
Muy bonito el tema este.
A ver si os lo puedo enseñar en un momentito.
Bueno, es que es complicado, ¿no?
Porque utilizo dos cosas.
Uno, el prompt, que sería el de pure, que es este.
Y luego, además, tengo cuál serían los colores que utilizo.
Uno de ellos es el de material design.
Suelo utilizar el de material design.
A veces el de one dark.
En Visual Studio Code, si te soy sincero, no sé cuál es el que estoy utilizando.
No sé.
Porque los colores cambian un poco respecto a mi terminal.
Pero si no es material design, material colors o lo que sea, como se llame, debe ser one dark.
Uno de los dos.
Y utilizo como prompt pure, que es que es muy bonito.
¿Vale?
A ver, ¿qué más?
Juan Quiroz dice, hola, bro.
Hola.
Hola, bro.
Juan.
Para una arquitectura de backend basada en microservicios, ¿qué framework para Node.js es recomendable?
Buah, esto es un mundo.
Esto es un mundo.
A ver, depende.
Uno de los grandes frameworks que ahora están muy de moda es Nest.
Nest con S, no con X.
Nest.
Yes.
Que se parece a Next.
Yes.
Pero es Nest.
Yes.
Y está bastante bien para justamente lo que quieres.
Que sería un backend basado en microservicios.
Echad un vistazo porque además está teniendo mucha popularidad ahora y creo que puede ser...
Mira, sí, vamos a verlo.
Vamos a verlo.
A ver, para que todo el mundo...
Nest.
Yes.
Este sería.
A progressive Node.js framework.
Luego tendrían los típicos, ¿no?
Como Express.
Aunque Express hace tiempo que no se actualiza.
Happy.
Happy creo, ya no sé ni siquiera si está deprecado incluso.
Está Fastify también.
Otra opción sería Fastify.
Que es más parecido a Express.
Entonces no llega a ser tan parecido.
Seguramente para microservicios pues puedes echarle un vistazo más a Nest.
Yes.
Que he escuchado buenas cosas.
No lo he utilizado, ¿eh?
Personalmente tampoco te pondría la mano en el fuego.
Pero me han hablado muy bien de él.
Así que, ¿qué más?
¿Qué más por aquí?
¿Qué beneficios te ofrece Firebase a la hora de loggear con OAuth que no puedas solucionar con un Passport?
En realidad, ninguna milla.
O sea, lo que pasa es que la idea era un poco utilizar Firebase para todo.
Y, a ver, una ventaja sería que al menos solo tienes un servicio en el que te tienes que preocupar y lo tienes todo unificado ahí.
Y la verdad es que Firebase tiene un montón de posibilidades a la hora de trabajar con OAuth.
Súper fácil, sin preocuparte y lo tienes en el mismo SDK.
Yo diría que esa sería.
Pero, al final, si solo tienes eso, pues a lo mejor si solo necesitas el OAuth, a lo mejor mi recomendación sería no vayas a Firebase, que a lo mejor es más grande.
Pero, hombre, si vas a utilizar Firestore, vas a utilizar Storage, vas a utilizar muchas cosas, puede ser interesante mantenerlo todo en un solo sitio y no tener que tener dos servicios.
Además, si pagas Firebase, para qué vas a estar a lo mejor con otro servicio y te lidia con un montón de problemas.
Eso sería un poco, ¿vale?
Es que, bueno, Beto Toro dice, Messi, del código, después de los cursos de Next, ¿seguirás haciendo streaming o le darás a tu proyecto de cursos?
Seguiré haciendo, yo quiero seguir haciendo streaming hasta que os canséis.
Entonces, no sé, espero que no os canseis nunca, ¿no?
Pero, quiero hacer streaming, no sé si será lo mismo, no sé si seguiré haciendo proyectos o haré cosas más pequeñas, no lo sé.
También vuestra opinión cuenta.
Entonces, me decís, oye, pues podrías hacer streamings más de este tema.
Pues, lo tendré en cuenta y pues haré esas cosas.
Así que, pero me gustaría seguir haciendo streamings todos los viernes, aunque no sean de un curso completo, ¿vale?
Pero me gustaría seguir haciendo streamings.
Pues, si os parece, vamos a seguir, porque si no, no avanzamos, no avanzamos.
Pero muchas gracias por vuestras preguntas y cuestiones, que siempre me siento acompañado cuando me decís estas cosas.
Y acordaos de dejar vuestro like.
Vale, entonces, hoy os quería hablar de la mejora progresiva, porque son dos palabras que he dicho muchas veces.
Y justamente con la ISU que nos ha creado nuestro amigo Eric, pues esto, ¿no?
Nos decía que el objeto Intel no existe en los navegadores de los teléfonos.
Me imagino que teléfonos antiguos, que no sean los últimos modelos.
Pero, bueno, yo ya dije, bueno, nosotros vamos a pasar de, vamos a intentar que sea ya todo lo nuevo.
Y, bueno, y entiendo que eso no es el mundo real, ¿no?
Entonces, quería hablarte de la mejora progresiva, porque creo que lo tendrías que tener muy en cuenta.
¿Cómo hacerlo? ¿Cuál sería la estrategia?
Creo que es un ejemplo sencillo, pero creo que le puedes ver un poco la gracia a esto, ¿vale?
Básicamente, la mejora progresiva es como una filosofía que hay dentro del diseño, o debería haber, porque tampoco mucha gente lo sabe, ¿no?
Pero es como una filosofía que hay dentro del diseño web, porque hay que pensar que hay una fragmentación brutal de dispositivos, ¿no?
Cuando hablamos de la web hay una fragmentación brutal, y el problema es que a lo mejor tenemos un montón de clientes que están utilizando la última versión de Chrome, Safari, Firefox,
y claro, esas últimas versiones ofrecen ventajas, ¿no?
De, por ejemplo, lo que hemos visto en las clases anteriores de tener el Time A Go, ¿no?
El Relative Time Format, y esa API es súper interesante, ¿no? De poder utilizarla, pero hay veces que obviamente tenemos nuestros usuarios que tienen Internet Explorer 11,
y les revienta si intentamos utilizar esto, porque ya le quitamos soporte.
Pero a lo mejor solo es un 5% de nuestros usuarios.
Entonces, lo que queremos con la mejora progresiva, que se puede ver de la forma contraria, pero a mí me gusta verlo así, ¿no?
Es que lo que queremos es tener una base de funcionalidad, una base que funcione para todos, ¿no?
Que funcione de la misma manera para todos.
Queremos que la página web funcione en Internet Explorer 11, pero le queremos dar una mejor experiencia de usuario a los que tienen la posibilidad.
No queremos dejar de darle soporte a Internet Explorer 11, pero si tienes Chrome, ¿por qué deberías cargar, por ejemplo, yo qué sé,
pues una librería para hacer Relative Time Format?
Entonces, lo que se trata es que cuanto, si se puede obtener una mejor experiencia para esos usuarios, es dársela.
Y esto, si tienes un navegador más moderno, pues tienes la mejor experiencia posible, pero todos tienen una misma base, ¿vale?
Entonces, normalmente lo que se hace es detectar las características que tiene en tu dispositivo.
Oye, pues puede manejar gráficos, por ejemplo, ¿tienes una buena conexión?
Pues, toma, aquí tienes una imagen todavía mejor o tienes un vídeo.
O sea, estamos mejorando progresivamente la aplicación.
Si tienes una mala conexión, si tu dispositivo tiene una mala CPU, si es un navegador antiguo,
pues lo que vamos a hacer es que, bueno, va a funcionar la app, va a ser como la base más normal y ya está.
Bueno, también esto a veces también se puede ver un poco al revés, ¿vale?
Se puede ver al revés que serían los fallbacks, ¿no?
Como decir, bueno, si esto se ha visto mucho en CSS, si tienes la posibilidad de ver un gradient, pues ves un gradient,
pero si no, ves el fondo más normal y esto sería como un fallback, que también se puede entender así.
Pero la verdad es que pensando en mejora progresiva hay que pensarlo como al revés, ¿no?
Como qué podemos hacer para darle la mejor experiencia a esos usuarios que pueden, ¿no?
Y es una filosofía de desarrollo que tienes que tener en tu día a día con tus compañeros, con UX y todas estas cosas.
Entonces, esto, como he dicho, normalmente se hace detectando estas características, ya sea por JavaScript, por CSS y tal.
Así que lo que vamos a hacer, lo primero, para hacer esta mejora progresiva, digamos, lo que vamos a hacer primero,
teníamos un hook por aquí, que era el de user, este.
Entonces, vamos a cerrar esto.
Lo primero que se suele hacer normalmente es detectar si el navegador es compatible con esa funcionalidad que quieres darle, ¿no?
Por ejemplo, es si el IntelDate is DateTimeFormat, no sé, supported, ¿vale?
Entonces, aquí miraríamos si tenemos el objeto global Intel de internacionalización, ¿vale?
Si es diferente undefined y Intel.DateTimeFormat existe, pues ya sabríamos si el DateTimeFormat está soportado.
Ya con esto lo que podemos hacer es básicamente decir, vale, esto es lo que queremos darle a los usuarios que tienen la posibilidad.
Que al final ya os digo que es muy parecido a un fallback, ¿no?
Pero los que no tienen la posibilidad, pues vamos a hacer otra cosa.
Entonces, vamos a hacer aquí, vamos a quitar todo esto que tenemos aquí, lo vamos a extraer, ¿vale?
En otra función que le vamos a llamar FormatDate.
FormatDate, que a esto le llega el timestamp y ya está.
Bueno, vamos a hacer que también le llegue el language, language, y vamos a hacer que sea el default language,
porque veo aquí que tenemos esta línea y esto ahora ya nos lo podríamos quitar.
Así que todo esto que estamos haciendo aquí lo vamos a poner aquí, FormatDate, ¿vale?
Y vamos a utilizar esto.
Esto es que nos va a ayudar más adelante con el time ago también, ¿vale?
Así que por eso lo voy a sacar todo esto de aquí.
Y vamos aquí, pues utilizamos esta función de FormatDate.
Y aquí lo que tenemos que pasarle a FormatDate, como hemos dicho, aquí es el timestamp, timestamp.
Y le podríamos pasar el language, que ahora mismo es justamente igual que el default language,
que es también el valor que tiene por defecto.
Bueno, esto lo podríamos arreglar, pero es como estaba.
Uy, ¿qué dice? Que no puede resolver console.
¿Qué ha pasado aquí?
Hooks.
Ah, no sé qué ha hecho esto, que me ha importado time.
Ni idea, ¿vale?
Vale.
Por ahora esto debería ser exactamente igual.
Lo que queremos hacer es justamente evitar utilizar esto.
Entonces, ahora que ya tenemos una forma de, si tenemos el datDateTimeFormatSupported,
que, bueno, por si no lo sabes, esto que estamos usando aquí en realidad es para cuando se hace hover aquí.
A ver si sale.
Vale.
Ahí se ve muy chiquitito, ¿eh?
Pero se ve una fecha.
Esa fecha la estamos creando gracias a esto.
Entonces, lo que tenemos que hacer aquí es un if.
Es decir, si no está soportado el datTimeFormat, vamos a evitar utilizarlo.
Y lo que podemos hacer es utilizar otra API que está bastante más soportada,
que tiene el quickday, que esto lo ponemos en short,
el year, que lo ponemos en numeric,
el month, que lo ponemos short también.
Aquí he puesto en igual, aquí la he liado parda.
Y ponemos el date, que puede ser numeric.
Vale.
Estas son las opciones que le vamos a pasar a otra API que está más soportada,
reutilizando este date que tenemos aquí, que es date.toLocalDateString.
Entonces, va a hacer un formateo de la fecha sin utilizar el datetimeFormat,
que es bastante más avanzado.
De esta forma, el usuario ni se va a dar cuenta,
pero al menos le vamos a dar alguna funcionalidad que va a ser similar.
Al toLocalDateString hay que pasarle el language y luego las opciones,
que son justamente estas que hemos creado.
Ahora, si guardo los cambios, claro, mi navegador justamente sí que soporta
el datetimeFormat.
Se ve muy chiquitito, ¿vale?
Pero está ahí, está ahí.
Bueno, lo puedo inspeccionar si no el elemento,
porque creo que lo hemos puesto por aquí.
Mira, yo lo enseño.
Vale, aquí tenemos.
Esto que veis aquí, esto es del datetimeFormat, ¿vale?
Entonces, ¿qué pasa?
¿Cómo puedo comprobar yo si esto que he hecho funciona correctamente?
Aparte de poner un test que a lo mejor sea interesante.
Lo que puedes hacer, ahora que tenemos justamente una constante
que dependiendo de esta constante, pues va a hacer una cosa u otra,
pues le puedes cambiar el supported.
Vamos a poner que sea false.
Vamos a poner que esto es un let.
Y de forma que aquí ponemos ahora false.
Así que ahora nuestro código fácilmente se va a comportar
como si el navegador no soportase justamente el Intel este.
Y, hombre, es bastante potente porque ahora fácilmente,
aquí podemos ver, ¿no?
Que ha hecho bien 11SEP 2020.
Ha cambiado, ¿no?
La funcionalidad y a lo mejor no es exactamente lo mismo.
A lo mejor tampoco es exactamente lo que queríamos hacer
y a lo mejor podemos hacer otra cosa.
Es un ejemplo.
Tampoco es importante lo que estamos...
O sea, que lo que he hecho, en lugar de a lo mejor poner short,
porque esto es como con letras, a lo mejor no es lo que queríamos.
Pero lo importante es que le estamos dando la misma funcionalidad
o muy similar a la que tenía, sin necesidad de soportarla,
aunque sea más moderna.
Esta es la idea, ¿no?
Que le hemos dado una cosa básica, más básica,
para que todo le siga funcionando.
Por supuesto, no le pete la app.
Pero si tiene mejor soporte,
pues lo que vamos a hacer es que utilice lo otro.
Lo mismo pasa un poco con el Time A Go.
Por supuesto, el Time A Go vimos que lo podía utilizar
más del 80% de nuestros usuarios.
Lo que no tiene sentido es, bueno, o incluso más.
Vamos a ver cuánta gente lo soporta.
Pero lo que podemos ver con el Relative Time Format.
Vale, no tiene soporte de Internet Explorer 11.
Y globalmente en 75% de usuarios que lo soportan.
Esto me parece un poco relativo,
porque depende también del país.
Y esto es global y habría que ver, ¿no?
Para tu propio país, eso sería interesante, ¿no?
Por ejemplo, creo que se podía importar...
Vea, os voy a enseñar un truco.
Os voy a enseñar un truco que os va a gustar.
Si soy capaz.
A ver, había una forma de importar...
Aquí.
Ah, sí.
Esto es muy interesante.
En Can I Use podéis importar vuestros datos de Google Analytics.
Si vuestra empresa, vuestro proyecto, tu página web,
utiliza Google Analytics,
puedes importar tus datos de Google Analytics
para que los tantos porcientos que veas
sean de tus usuarios reales,
en lugar de una forma global,
que es un coñazo,
porque también te salen datos de China.
Y, bueno, pues tus usuarios seguramente no sean de China.
Una cosa que puedes hacer es añadir solo, pues eso,
cada país, cada región.
Pero creo que es más interesante esto, ¿no?
El añadir desde Analytics.
Hace tiempo que no lo utilizo.
Espero que funcione.
Pero esto debería ir a mi página de Analytics.
Le deberíamos poder permitir darle acceso.
Ahora nos pregunta, oye, ¿de cuáles son?
De todas las que tienes, ¿de cuáles son?
Pues le voy a decir de mi du dev, que es mi página, ¿no?
Esta, y le puedo decir que los últimos 30 días.
Claro, pues si pilla el histórico,
pues pillará también navegadores anteriores.
Así vamos a ver la data de los últimos 30 días
y vamos a ver los usuarios que han venido
esos 30 últimos días,
qué compatibilidad tienen.
Y vas a ver, o debería, ¿vale?
Estos son todos los navegadores que ha importado.
Vale, perfecto.
Creo que esto ya debería estar.
Así que puedo cerrar.
Creo que sí.
Global, región, todos los datos.
Le voy a poner que va a ser el primario, digamos,
el de todos los datos del sitio web,
que esto podría ser usuarios de midu.dev, ¿vale?
Voy a cerrar aquí.
Y ahora vamos a poner Relative Time Format.
Relative Time Format.
Vale.
Y entonces, lo que estábamos viendo antes,
aquí podemos ver,
va, decidme que esto no es brutal, ¿eh?
Decidme que esto no es brutal.
Esto es un trucazo brutal.
Esto está genial.
Mira, aquí podemos ver que mis usuarios,
este Relative Time Format,
los usuarios que entran a mi página
son un 83% tienen compatibilidad con esta API.
Por lo tanto, sé que solo es un 17.
Claro, si yo hubiese visto el global,
hubiera pensado un 20%.
A ver, que tampoco pasa nada.
Pero es súper importante tener datos reales
de tus usuarios y ver la compatibilidad que tienen, ¿vale?
Así que esto, aquí tienes un midu.trukey, ¿vale?
Y aquí vemos que solo hay un 17% de usuarios,
de mis usuarios,
que no tienen compatibilidad para esto.
Así que todavía es más apremiante, ¿no?
Que realmente haya una mejora progresiva
y que ese 80 y pico por ciento
sí que vean el Relative Time Format.
Bueno, pues esto no se ve en todos los sitios.
Esto no se ve en todos los sitios.
Esto solo lo veis aquí, en midu.dev.
Y si te ha gustado el truco, un like.
Vale.
Pues entonces, ¿por dónde iba?
Me he emocionado tanto.
Me he emocionado tanto.
Es que me encantan estos trucos.
Vale.
Lo mismo que hemos hecho con el Date Time Format,
lo vamos a hacer con el Relative.
Así que algo similar a lo que hemos hecho aquí,
que sé que parece una chorrada, ¿no?
Que es lo típico.
Pero esto es la magia de hacer estas cosas.
Entonces, al final lo que detectamos es
si es compatible, aquí vamos a poner
es Relative Time Format.
Entonces, miramos si tenemos el Relative Time Format.
Y ahora, si este es un poquito más complejo, ¿vale?
Si no es compatible,
aquí lo que vamos a hacer es otra cosa.
Lo que vamos a hacer
es justamente utilizar el Format Date
que hemos visto antes.
Format Date.
¿Vale?
El que hemos creado aquí, esta función.
De esta forma, va a ser muy progresivo
porque va a intentar primero utilizar
el Relative Time Format.
Si no, va a intentar utilizar el Date Time Format.
Y si no, pues al final hará tu Local Date String.
Y si no, incluso podríamos añadir uno más.
Pero al menos vamos a hacer este.
Y aquí le podríamos pasar el Timestamp.
Aquí hacemos un Return.
Y ya está.
Ahora es importante tener en cuenta
que este efecto que estábamos haciendo aquí,
claro, ahora deberíamos hacerlo solo
si sí que es compatible con el Relative Time Format.
Porque si no, esto no tiene sentido
que se vaya actualizando
y vayamos viendo y todo esto.
¿Vale?
Entonces, he guardado estos cambios.
Creo que no se me ha olvidado nada.
De nuevo, ¿cómo lo podemos probar?
Pues nada, le decimos, bueno,
pues ahora le vamos a decir
que no tiene soporte.
Punto.
Le forzamos este false aquí
y vamos a ver qué pasa.
Vale, ha petado porque necesita...
Necesita...
He puesto language.
Vale, no pasa nada.
Aquí este language...
Aquí había puesto que este parámetro era...
Bueno, o sea, que tenía un valor por defecto,
pero he puesto que es obligatorio
pasarle a dos opciones.
Vamos a añadir que tiene valor por defecto
objeto vacío.
Y ese objeto, pues tiene valor por defecto
language, default language.
Guardamos los cambios.
Y vale, pues ya está.
Tendríamos esto.
Esto sería un ejemplo, ¿no?
De decir, bueno, no tienes Relative Time Format,
pero al menos, pues tienes esto.
Puedes ver más información a qué hora ha sido.
Entonces, ¿qué pasa?
Ese 17% de nuestros usuarios,
pues, por decir con míos,
no van a poder ver el Time a Go,
pero a lo mejor no es una funcionalidad
tan importante, ¿no?
Para que tengamos que añadir
una librería de 40K.
A lo mejor podemos hacer esto
y progresivamente nuestros usuarios
van hacia allí.
Es mejor muchas veces el intentar mantener
cosas de la plataforma
o incluso con Polyfills
que no intentar mantener tu código
con librerías de terceros.
Que no quiere decir,
esto es un mensaje importante,
no significa que ahora todos
siempre hagáis esto.
A veces tiene sentido.
Si el Time a Go es una funcionalidad crítica
de tu aplicación,
pues seguramente tiene sentido
meter una dependencia
porque es súper importante.
Pero me encuentro muchas veces
que a lo mejor cuando se abre una modal,
pues, hay ahí un comportamiento
que solo se puede conseguir
en el 80% o tal.
Pues, esto es una explicación,
es una conversación
que tenemos que tener
con nuestro Product Owner
o nuestros diseñadores,
nuestros colegas.
Oye, ¿qué te parece?
Si para simplificar el desarrollo,
porque normalmente es mucho más simple,
¿no?
El desarrollo,
el no tener que depender
de algo externo
o mucho más fácil.
¿Qué te parece?
Eso suele ocurrir también con CSS.
No todos los navegadores
soportan Position Fix.
No, Position Fix no.
Position Sticky, ¿no?
Que es para hacer
que un contenedor sea sticky
y se quede mientras vas bajando.
Que justamente también
lo utilizamos aquí.
Entonces, lo que puedes hacer es,
oye, el 80% utiliza Sticky
en lugar de utilizar JavaScript
para hacer esa funcionalidad.
¿Qué te parece?
Si el 80% lo hacemos en CSS
que tengan esta funcionalidad
y el 20% restante
lo ven como Position Absolute
de forma que, bueno,
cuando hace scroll lo pierde
y ya está.
Pues es una posibilidad.
Bueno, pues...
Ay, me he cambiado de cámara
y os quería leer
a ver qué me comentabais, ¿vale?
Pero bueno,
esto es un poquito la idea, ¿vale?
De la mejora progresiva
y ahora antes de seguir
con las variables de entorno
con Next.js
que, bueno, es bastante fácil,
voy a leeros
que os tengo abandonaicos.
A ver,
pacho en la leche.
Samuel Cusilima,
el CR7 más Messi
del frontend.
O sea,
muchas gracias.
No sé,
no sé si llego a tanto,
no sé si llego a uno de los dos,
no sé si llego a la pierna
de uno de los dos,
no sé si llego al pulgar
de uno de los dos.
Bueno, da igual,
pero muchas gracias, Samuel.
Me parece muy bonito.
Manux Music,
Rip,
Moment.js.
Hombre,
Moment.js ha tenido su momento,
me pareció muy interesante,
pero creo que ahora hay,
bueno,
lo he dicho en todas las clases
y me han caído palos,
pero hay alternativas
mucho más interesantes
y yo lo que os invito
a que exploreis la plataforma
antes de meteros
en alguna dependencia,
si puede ser,
que lo exploreis.
Tome su like,
buen hombre,
gracias por el truco.
De nada,
Diego,
me alegro que te haya gustado.
Me parece,
a mí me encanta este truco.
Así que nada.
Matías Caballero,
Midutip,
o Midutruco,
me dicen Midutruco.
IDQM,
XD,
gatito.
Que alguien me diga
que no es el Messi del frontend,
dice Beto Toro.
No lo sé,
no lo sé si soy el Messi del frontend,
pero gracias,
hombre,
te lo agradezco.
Trucazo,
dice Sergiedo.
Bueno,
veo que os ha gustado.
Trucazo,
Daniel,
guau,
gracias por el truco,
guau.
Gracias,
me alegro que os haya gustado,
yo es que me animo solo,
ya lo habéis visto,
¿qué más?
A ver,
¿puedes hacer una pregunta
en Instagram y las historias,
recopilar dudas
y resolverlas en un live?
Vale,
Diego,
lo haré.
De hecho,
lo tengo pendiente.
Alguna vez he querido,
pregúntame lo que quieras
y hacer un live sobre eso.
Lo vamos a hacer,
Diego,
así que apuntaos al Instagram
que lo haremos pronto.
¿Qué más?
Ezequiel me dice,
pon iconos de carpetas al editor.
Saludos desde Argentina.
Pues no sé,
¿para qué?
Si sale una flechita.
No sé,
bueno,
me lo miraré.
Guido dice,
nunca me animé a usar Firebase
porque no sé si al dejar
las credenciales en el front
alguien puede hackear
la database.
Vale,
eso es interesante.
Lo hemos comentado alguna vez.
No pasa nada,
no es problemático
dejar en el front
esas credenciales.
Piensa que hay muchas APIs,
un montón de APIs
y de servicios
que necesitan
que tengas las credenciales
en el cliente,
¿no?
cuando quieres utilizar
en JavaScript.
En el caso de Firebase
hay dos tipos
de credenciales.
Las que van al cliente
que de alguna forma
están como,
pueden estar como
capadas,
pueden estar capadas
y además tú le puedes poner
unas reglas
que no sé si
no,
pero vamos a hacer
una clase
va a ser solo de reglas
de Firebase,
¿vale?
Y hablaremos solo de esto.
Lo tengo pendiente,
pero es que además
pueden ser un poco complejas,
pueden ser tan complejas
como tú quieras,
pero puedes poner
un montón de reglas
que el usuario esté logado
o si no,
no puede utilizar
la base de datos.
Esa es una.
O puede utilizar
la base de datos
pero solo esta colección.
O puede utilizar
la base de datos
solo si el tiempo
que hace
que ha hecho
esta request
sea,
o sea,
tiene un montón
de mecanismos
en las reglas
para evitarlo.
O sea,
lo importante
no tanto son
esos códigos
que comentas
sino las reglas
que pongas
cuando esa request
llega al servidor
de Firebase.
Es súper seguro
Firebase
que se conozca,
no hay ningún
ningún ataque.
Si te equivocases
y como te decía
hay dos tipos
de códigos,
uno son estos,
estos tokens
que sí que son públicos,
pero si tienes,
utilizas Firebase Admin
que lo utilizamos
en la clase anterior
si no me equivoco,
esas claves
sí que son
de administración
y tienes que tener cuidado
de que no,
de hecho las tengo aquí
pero no las subo
al GitHub
y tal.
De hecho,
si las subes
a GitHub,
Firebase lo detecta
porque vas rastreando
los repositorios
y te envía un correo
y lo sé
porque alguna vez
me ha pasado
y te envía un correo
y te dice
estas claves
se han filtrado
elimínalas inmediatamente
y créate unas nuevas.
Así que
fíjate lo importante
que es para ello
es la seguridad
porque es que
claro,
en eso se basa,
eso es la gracia.
No sé si te ha ayudado
con la pregunta.
Lo único que te diría
de Firebase
para empezar es brutal,
es muy bueno,
muy potente.
Lo malo es cuando creces
mucho
que es caro,
puede ser caro,
te puede salir
por un pico.
Sergio,
¿has usado Formic?
¿Te apuntas a un cursito?
He usado Formic
y en el curso de React
que tenemos en YouTube
utilizamos Formic.
No mucho,
pero sí,
lo he utilizado.
Un cursito
lo podemos mirar.
A ver.
Quaymari Carrasquero,
si necesitas hacer una app
que tenga un instalable
para PC,
¿usarías Electron
o algún otro framework?
Yo utilizaría Electron,
de hecho,
tengo unas cuantas aplicaciones
hechas con Electron
y me ha gustado mucho
siempre la experiencia.
Depende de la app,
¿vale?
O sea,
si la app es,
bueno,
pero Slack,
sin ir más lejos,
está hecho con,
aunque yo recuerdo,
está hecho con Electron,
pero depende de la app.
Pero normalmente,
la verdad es que sí
que se podrían hacer cosas así.
Desde las Chrome Tools
o algún plugin
para degradar
las funcionalidades del browser,
para simular otros browsers
que no soporten ciertas funciones
como la de,
claro,
con las Chrome Tools
no lo puedes hacer,
no puedes,
o que yo sepa,
no se puede hacer fácilmente
más allá de que intentes
hackear el objeto
que quieras
que no esté soportado.
Porque cuando simulas otro browser,
aunque cambie el user agent,
esas funcionalidades
siguen funcionando.
Pero obviamente,
si utilizas cualquier herramienta
como browser stack
que se hace pasar
porque es el navegador virtual,
te va a funcionar.
Gonzalo,
creo que te he contestado.
Veremos,
bueno,
roles y usuarios,
¿cómo filtrar autorización
y autentificación?
No lo sé
si lo vamos a ver en esta
porque roles
es otro más,
son roles,
¿no?
De niveles
y no sé si lo vamos a ver.
¿Cuándo un deploy en App Engine?
Lo que veremos en este curso
es el deploy a Vercell
porque creo que es el que tiene más sentido,
¿vale?
Pero
no lo descarto
en el App Engine algún día.
Prueba en DGS.
DGS está muy bien,
pero de nuevo,
creo que DGS,
por muy bien que esté,
puede no ser necesario.
Si es necesario,
pues utilízalo,
que no pasa nada.
¿Aguantaría un curso
sobre todo estos servicios
de Firebase?
Ya, Beto,
pero la verdad,
o sea,
reconozco que no soy
un,
o sea,
he utilizado bastante Firestore,
he utilizado algo Auth,
he utilizado algo el Storage,
pero
quiero utilizar,
quiero que veamos las lambdas,
las funciones,
Firebase Functions
y las quiero aprender
y enseñaroslo
y tengo la idea
de por qué
la vamos a necesitar,
pero no soy
súper experto
y por eso,
pero bueno,
no lo descarto,
me gustaría,
me gustaría.
Nicolás dice que
él publicó un repo
con las claves
y el mismo Firebase
le alteró,
le alteró,
no,
le alertó,
le alertó del error,
que además lo ha dicho después.
Vale,
pues qué más,
qué más,
si usas
GetStaticProps,
qué límite tiene,
si se modifican datos,
sería mejor usar
GetServerSideProps,
en el vídeo anterior dijiste
que podrías usar GetServer
con un sistema de caché,
¿cuál sería?
Es una pregunta
muy,
muy grande,
pero GetStaticProps,
el límite que tiene,
a ver,
ahora con la nueva funcionalidad
de la regeneración
de los archivos estáticos,
pues a lo mejor
puede ser interesante.
Yo diría que el límite
no es tanto el límite
que tiene por sí mismo,
sino que hay que pensar
cuántas páginas
tiene que soportar
tu servidor
que sean estáticas.
Por ejemplo,
yo seguramente iría
por el GetServerSideProps
si tienen que ser siempre
datos frescos,
por ejemplo,
tienes una inmobiliaria
que le entran al día
50.000 inmuebles
y tienes búsqueda
y filtros
y tal.
Claro,
quieras o no,
el GetStaticProps
va a tener la limitación
que en algún momento
le vas a enseñar
al usuario
la versión estática
que se ha creado anteriormente.
Y aunque tú hagas
que sea cada X tiempo,
lo que sea,
al final tiene un límite,
entonces el GetServerSideProps
es para algo
que necesites
que siempre sea fresco,
que tengas mucho contenido
nuevo constantemente
y que lo tengas que enseñar
y que te dé igual
que vaya a la base de datos
y que tenga ahí
un hit más.
O sea,
que te dé igual
la velocidad
porque quieres
la máxima frescura
y es súper importante
para ti.
Quieres que
cuando un cliente
sube un producto,
cuando va al resultado
el primero,
ya ve ese producto.
¿Por qué?
Porque el estático
vería,
puede ser la versión cacheada
si no ha entrado
alguien antes,
vería la versión cacheada
oye,
porque no está mi inmueble.
A lo mejor refresca
ahora sí que está.
Eso podría ser un ejemplo
de por qué utilizar uno,
¿vale?
¿Qué más?
Si al crecer un proyecto
Firebase
se vuelve costoso,
¿cuál sería la mejor opción
para seguir con proyecto
en vez de Firebase?
Pues las opciones
serían utilizar,
empezar a migrar
parte de tus servicios
a algunos más handmade,
ese sería uno.
También Amazon,
ahora tiene un,
que también lo quiero ver
en el canal,
Amazon tiene un competidor
que ahora no me sale el nombre,
pero tiene un competidor
a Firebase,
voy a buscar,
Firebase Competitor,
es que ahora me sale.
Mira,
Amplify,
mira,
cago en la...
Amplify,
se me olvidaba.
Pues eso,
Amplify.
Dicen que te sale
más barato a la larga.
Amplify también está
muy bien para empezar
y a lo mejor me gustaría
que lo veamos
en los live,
porque lo que era aprender
sinceramente no lo he usado nunca
y me gustaría.
Veremos Cypress,
dice Oscar,
voy a apuntarme
lo de Cypress.
Esteban dice,
Moment Yes,
eso ya hemos dicho
que no lo uséis.
Wilson,
¿conocéis alguna herramienta
para generar reportes
a partir de la información
que está en la colección
de Firestore?
Pues la verdad es que no,
lo reconozco,
no tengo ni idea.
Reportes,
a partir de la información,
ni idea.
Amplify,
dice Gonzalo,
pues eso,
Amplify.
Seguimos,
venga va,
seguimos y le damos
a los env,
las variables de entorno.
A ver,
¿por dónde iba?
Aquí,
sí,
¡pum!
Vale,
sobre el tema
de las variables
de entorno,
¿vale?
¿Qué es esto
de las variables
de entorno?
¿Qué son los archivos env?
Por si no lo sabías
o si no lo sabes.
En este caso,
a ver,
tenemos este admin,
vale,
este admin me puede servir.
Los credenciales
no los voy a poner aquí
porque si no
se verían
y estos son los credenciales
que no se deberían ver,
pero vamos a intentar
tener este database URL
como variable de entorno,
¿no?
Porque un problema
que tenemos
en nuestra aplicación,
que supongo
que te has dado cuenta,
es que solo estamos
utilizando una base
de datos.
Independientemente
si estamos en local,
en desarrollo,
en preproducción,
en producción
o testeando,
ahora mismo
tenemos todas
nuestras keys
que están apuntando
a algún sitio
y eso,
hombre,
no es ideal.
Buchito,
un poquito de whisky,
que además,
mira,
os voy a enseñar
la de full stack,
full stack fest.
Hasta la cosa
esta de ver
es friki.
Vale,
entonces,
solo tenemos
un solo sitio,
una sola base de datos.
Lo que nos gustaría
es que dependiendo
del entorno,
dependiendo de
si estamos desarrollando
el local,
si ya estamos
en producción,
si estamos en modo desarrollo,
dependiendo de eso,
nos gustaría ver
que estamos atacando
a una base de datos
diferente,
que el entorno
cambia.
¿Y eso cómo lo podemos hacer?
Con variables.
Entonces,
se le llaman
variables de entorno.
Son variables
que dependiendo
del entorno
cambia su valor
y de esta forma
podríamos atacar
a diferentes bases
de datos,
tener credenciales
y dependiendo
del entorno
ir a unas credenciales
u otras
y eso lo vamos
a ver ahora.
Pongamos el ejemplo
de este database URL.
Este database URL
que estamos utilizando
aquí puede ser
que dependiendo
donde sea el entorno
queremos que vaya
a un sitio
o a otro.
Lo que podríamos crear
al principio
Next.js
es compatible
con un tipo
de patrón,
digamos,
que es el de
los archivos .env
que tú escribes
aquí un archivo .env
y aquí ya puedes
generar,
bueno,
puedes crear o añadir
variables de entorno.
Por ejemplo,
una variable de entorno
que podríamos crear
aquí para esto,
este database URL
sería
Firebase
database URL
y aquí
podríamos poner
este string
que tenemos aquí.
Entonces,
claro,
ahora si te fijas
lo que he hecho
es escribir
un .env
sin nada más.
Vamos a empezar así.
Este .env
lo que es,
digamos que sería
la variable
de entorno
en general,
las que tendríamos
por defecto
independientemente
de qué entorno
estemos,
si sea producción,
desarrollo,
local,
lo que sea.
Entonces,
ya tenemos este.
Ahora,
¿cómo podemos utilizar
justamente esta variable
de entorno
que tenemos aquí?
Pues lo que deberíamos
hacer es aquí poner
un,
bueno,
no deberíamos poner
un console.log,
pero lo que quería enseñar,
podríamos hacer
process.env
.
y aquí
la variable de entorno
que queremos utilizar,
Firebase,
Database,
URL.
Esto mismo
deberíamos hacerlo
con las credenciales,
por ejemplo.
Lo ideal,
en lugar de tener
un archivo aquí,
sería que tirase
de esta variable de entorno.
Por ahora vamos a hacer esto,
voy a poner un console.log
justamente para ver
si esto funciona para algo.
Así que vamos a poner esto aquí,
guardamos los cambios,
voy a abrir la terminal
y vamos a ver
si esto funciona.
Si yo ahora refresco,
a ver qué ha pasado,
a ver si,
ah,
ah,
porque este archivo
solo lo teníamos
cuando íbamos al tweet.
Vale,
ahora me sale
undefined,
o sea que esto no ha funcionado
como esperábamos.
Pueden ser dos cosas,
una,
voy a cerrar el servidor
y lo voy a volver a abrir
a ver si el problema es ese.
Creo que
hay que
resetear el servidor
porque me imagino
que no funcionará tal cual.
Ahora sí.
Esto que vemos aquí
es el console.log
que he puesto
y aquí podemos ver
que tenemos
el valor que he puesto
en el .env.
Este .env,
como he dicho,
esto sería un poco
para nuestros valores
por defecto,
pero podríamos tener
este valor
para los diferentes entornos.
Podríamos tener
.env.production,
.env.development,
.env.test
y en cada uno de ellos
cambiar esta URL.
¿Vale?
Esto por un lado.
Pero tendríamos,
digamos,
dos tipos
de variables de entorno.
Una,
que sería como para indicar
hacia dónde tiene que ir,
por ejemplo,
a qué API tienes que atacar
si estás aquí en desarrollo,
pues a esta,
a esta y tal,
pero hay otras
que son un poquito
más peligrosas,
que digamos que son
las variables de entorno
de tus credenciales.
Por ejemplo,
el archivo este
que comento aquí,
el archivo este
de credentials
que tenemos aquí,
este archivo
está lleno de keys
que no debería haber nadie.
Por lo tanto,
tenemos como dos tipos
de variables de entorno.
Una,
que pueden ser públicas
porque no es tan importante
que la gente las vea
como pasa con las keys
de Firebase,
y otras
que son las credenciales,
que son passwords
que no queremos
que nadie vea.
Así que,
digamos que tenemos
dos tipos
de variables de entorno.
¿Cómo podemos
diferenciarlas?
Como te puedes imaginar,
hay unas variables de entorno
en las que puede ver
todo el mundo
que esas las podemos publicar
a nuestro repositorio.
Por ejemplo,
esta de database URL,
seguramente
vamos a querer
que nuestros usuarios,
o sea,
la gente que ve
nuestro repositorio
la pueda ver.
que cuando estamos
en .env.production
pues tengamos
nuestra variable de entorno,
por ejemplo esta,
y por ahora
pues podamos poner la misma,
o .env.development
vamos a poner también
que sea la misma.
Así que,
en estos tres entornos,
esta variable de entorno
sería la misma,
es pública,
estos tres archivos
nosotros los publicaríamos
a GitHub
y no debería pasar nada,
porque esto es un variable
de entorno
pública,
que es solo para decir
dónde tiene que ir
y tal.
Esto por un lado,
pero tenemos otras
que no son así,
que son más credenciales,
¿no?
En este caso,
claro,
no puedo enseñaros en vivo
el tema este,
porque si no os enseñaría
todas las credenciales
y no por vosotros,
pero se queda el vídeo
y la gente puede hacer
cosas muy peligrosas.
Entonces,
lo que voy a hacer
para enseñaros
un poquito esto
es tener en cuenta
como si estos de client,
las que tenemos aquí,
como si estas,
en realidad,
fuesen credenciales
que no queremos
que vea nadie,
¿vale?
Son credenciales
que deberían ser privadas
y que no debería haber nadie.
Las vamos a tratar así,
imaginad que este objeto
debería ser privado
y que nadie lo debería haber.
Entonces,
vamos a tratarlos así
y ¿cómo lo podemos hacer?
Para eso,
podemos crear
otro tipo de archivo
que sería
.env.local.
Aquí ten en cuenta
que este .env.local
no significa que estés,
significa que va a funcionar
de forma local,
pero porque no debería ser público.
De hecho,
si te fijas,
ya sale como apagado
apagado
y eso es porque automáticamente
yo creo,
ah, mira,
ya cuando,
seguramente cuando se creó
este gitignore,
no sé,
hace dos meses,
cuando empezamos
con el create next,
ya lo que hace
es evitar
que este archivo
tú lo publiques.
Ya te creó
en el gitignore,
te dijo,
oye, no,
esto no lo tienes que publicar
y por lo tanto
te lo pone en ignore.
Como puedes ver,
puedes tener también
.local para development,
production,
esto también lo puedes tener,
pero estos son archivos
que no,
no tienes que poner
en tu repositorio,
¿vale?
Importante.
En este caso,
tendríamos todo esto,
¿vale?
Tendríamos todos los que,
a ver,
¿dónde está esto?
Esto,
.client.
Imaginemos que tenemos
todo esto,
¿vale?
Estos son muchas variables
de entorno,
esto puede ser un coñazo,
un verdadero coñazo
si tengo que ir una a una
y seguramente notaría dos horas.
Así que voy a,
si me permitís,
voy a hacer un truco
que hay gente que diría
que es mala práctica,
yo discrepo,
la verdad,
pero lo que vamos a hacer
es convertir esto
en un string.
Lo que vamos a hacer
es tener un json.stringify
y aquí le vamos a pasar
justamente todo este objeto
y esto pues sería un string
y esto ya lo podríamos copiar
y tal.
Pero como no quiero
que te vayas
sin otro midu truqui,
¿vale?
Te voy a enseñar
de una forma
que esto es genial.
Normalmente lo que haríamos
es esto, ¿no?
Y al hacer esto,
pues aquí yo seleccionaría esto
y lo copiaría
con comando C
y bueno,
que lo pueda hacer
y lo pegaría
y tal.
Vale.
Pues voy a poner que,
voy a copiarme esto
para que veas
que ahora tengo esto,
¿vale?
Vamos a volver a tener esto.
Igual lo sabe ya,
¿eh?
Puede ser.
A ver,
json.stringify
y vamos a pegar otra vez esto.
Es que lo he perdido de,
bueno,
lo pego,
ahora voy a tener esto pego,
¿vale?
Pero he perdido
lo que habíamos pegado antes.
Una forma súper fácil
que tienes en las herramientas
de desarrollo,
bueno,
voy a hacer esto más grande
para que lo veáis,
que si no luego me decís
que no veis.
Una forma súper fácil
que tienes de copiar algo
de las herramientas de desarrollo,
que si lo sabes,
pues bueno,
no te chives,
no te chives.
Puedes poner copy,
¿vale?
Que es un método especial
que tienes en la consola
y de esta forma
el output
de lo que le estás pasando
se ha debido copiar
en tu portapapeles.
De hecho,
ahora si hago comando V,
ahora tengo otra vez
este string
que hemos creado
hace un momentito.
Así que,
bueno,
no sé si te ha gustado
el truquito,
pero ahí está.
Si haces este copy
de este stringify,
pues aquí
lo tendríamos
como un string.
Y ya está.
O no,
me lo está copiando.
A ver,
a ver,
un momento.
Esto,
el copy,
a ver,
lo me ha hecho,
no, no.
A ver,
aquí me ha dejado
súper mal
porque creo que
no me está copiando
como si fuese un string
o me lo estoy imaginando yo.
A ver,
json.stringify.
A ver si es que estoy copiando.
No,
pero si he copiado bien,
¿no?
A ver,
tenemos esto.
Vale,
y esto,
hacemos el copy.
Pues,
ah,
porque me lo está transformando.
La madre
que lo trajo.
Cuando hago el copy
me lo está transformando
en json.
La madre
que lo trajo.
Bueno,
pues no me ha salido
el nido truqui.
Bueno,
pero ya lo sabéis
que si tenéis que copiar algo
lo podéis hacer así.
Claro,
cuando hago el copy
y lo pego
me lo está copiando
como un json
porque él quiere.
Bueno,
ahí se ha quedado el truco.
Bueno,
el caso es que tengo el string
porque si lo hago a mano
sería un coñazo.
Así que voy a poner
Firebase
y voy a poner aquí,
¿cómo se llamaría esto?
Config,
¿vale?
Firebase Config.
Y aquí le pegamos todo esto
que al final es un string.
Vamos a ver si esto funciona
como debería,
que no lo sé,
pero si funciona bien
y si no,
luego buscaremos el problema.
De nuevo,
piensa que estos son
como las credenciales
que no quieres que nadie vea.
En este caso,
ya sabemos que estas sí
que las podría ver la gente,
pero pensemos que no queremos
que nadie las vea.
Entonces,
voy a comentar todo esto.
Voy a comentarlo.
Y vamos a poner aquí
const Firebase Config
y de la misma forma
que antes hemos hecho
el process.env.
Y aquí
Firebase Config.
¿Vale?
Firebase Config.
Esto,
claro,
nos viene como un string.
Así lo que tenemos que hacer
es un json.parse
de todo esto.
Esto es importante.
Tenemos que transformar
este string que tenemos aquí
a json
porque es el tipo de archivo,
el tipo de estructura de datos
que necesita.
Para ver que esto
está funcionando bien,
vamos a hacer este json.parse,
vamos a hacer esto
y lo vamos a poner en el console.log
y a ver qué pasa.
Porque vamos a ver
que esto no es tan sencillo
como parece
porque hay una cosita.
Entonces,
voy a resetear el servidor
como he hecho antes
que hemos visto
que no funcionaba bien.
Si no reseteamos,
no tomaba ese nuevo valor.
Ahora,
voy a irme a la home
que sé que estamos utilizando
en la home
todo el tema este de Firebase.
Vale.
Y aquí,
pues está petando
porque no está encontrando
este,
dice,
un expected token,
json,
no sé qué,
no sé cuánto.
Vale,
vamos a hacer otra cosa.
Como este veo
que me está petando,
vamos a poner
este process.em.firebase.config
a ver qué hay aquí
porque no le está gustando nada.
Así que vamos a ver
qué hay aquí.
Vale.
Entonces,
aquí
vamos a ver algo raro,
¿no?
A la izquierda
lo que estamos viendo
es que aquí,
que sería el servidor,
¿no?
Cuando estamos en la terminal
de la consola,
de la consola del editor,
esto sería el servidor,
¿no?
Cuando se ejecuta en el servidor,
sí que tengo la información.
Pero cuando estoy
en el cliente,
aquí puedo ver
que me ha salido
que es undefined.
¿Qué está pachando?
¿Qué pacha?
Vale,
yo te digo lo que pasa.
Y es que,
por defecto,
las variables de entorno
que pones en los archivos .env
solo están disponibles
en el servidor.
¿Y en el servidor
qué quiere decir?
Pues quiere decir
en toda tu aplicación
en modo servidor,
por ejemplo,
aquí,
esta línea 14
se ha ejecutado
en el servidor
y sí que la ha encontrado,
pero por ejemplo,
en el getInitialProps,
getServerSideProps,
getStaticPath,
getStaticProps,
en las APIs,
¿no?
Esta API
que teníamos aquí,
aquí también tendríamos
acceso a esa variable
de entorno.
Pero en el cliente
no está disponible.
Súper,
mega,
importante.
Para hacer que esté disponible
hay que hacer,
hay que añadirle algo
de hilante
a la variable de entorno
que es
next-public-firebase-config.
Y de esta forma
lo que le estamos diciendo
es que esta variable
de entorno
tiene que ser pública
también en el cliente.
Que claro,
aquí está el tema.
Si es un .env.local
no debería ser,
no debería ser pública.
Es un contrasentido.
De hecho,
tengo dudas
si esto no va a funcionar
tal cual.
Vamos a verlo.
Vamos a ver si esto
se lo traga con patatas.
Tengo mis dudas
de que se lo trague.
Porque,
claro,
en realidad
sería un contrasentido
hacer que
una variable de entorno
que debería ser
totalmente privada
sí que la puede hacer
pública después.
Porque eso
va a acabar
en tu código.
Lo que,
donde tú ves
este process.ef
bla,
bla,
bla,
esto lo que va a hacer
next es que cuando lo compile
va a saber
lo que es tu variable
de entorno.
Así que sería un poco raro.
Pero igual funciona.
No lo sé.
Como estábamos probando
algo que debería ser totalmente
posible,
ha funcionado.
De hecho,
aquí lo tenemos.
Esto,
aquí tenemos en la consola
justamente lo que necesitábamos.
Y como lo he transformado
con json.parse
a un json,
como aquí,
pues ha funcionado correctamente
y ya nuestra aplicación
vuelve a funcionar.
Pero lo interesante de esto
es que ahora no está tirando
de una configuración
que tenemos aquí a mano.
sino que esto
lo que nos habilita
de alguna forma
es que ahora
dependiendo del entorno
podemos tener
uno u otro.
Por ejemplo,
vamos a ver.
Ahora esto,
ya sabemos que esto
está funcionando correctamente
así que vamos a dejar así.
Hacemos el json.parse
esto del process.enf
tiramos de aquí.
Voy a guardar los cambios.
Ya hemos dicho
que el enf.local
esto no debería ser público.
No lo subas a tu repo.
¿Vale?
Así que no lo vamos a usar ahora
porque no le...
Lo que sí que podemos hacer
a lo mejor
el firebase database url
este sí lo podemos...
Voy a hacer una cosa.
Voy a pegar esto aquí.
Y este firebase database url
este sí que lo vamos a dejar aquí
porque total
esto solo deberíamos verlo
en servidor
y no es importante
lo de next public y tal.
Y en cambio
el next public firebase config
este que es el que básicamente
no es importante.
O sea,
este es correcto
que esté la variable
en entorno general
sino en la local, ¿no?
Porque hemos dicho
que puede ser público.
Y este...
Con este lo que vamos a hacer
es tener...
Vamos a quitar el punto enf
que este es demasiado general
y vamos a tener dos.
Uno que sea development
y otro que sea production.
Y en development
vamos a poner...
Bueno,
en production
vamos a poner el que ya tenía,
¿vale?
El que ya estábamos utilizando
que es el que estábamos utilizando todos.
El que ha utilizado Eric
y hemos podido poner aquí
quien quiera lo que quería.
Y en desarrollo
voy a poner otro
o otra configuración
de forma que vamos a poder ver
la diferencia
porque ahora estamos
en modo desarrollo
y vamos a...
Deberíamos ser capaces
de levantar otra vez
nuestra aplicación
y que tire
de una base de datos
totalmente diferente.
Tengo este
de try new things
que este lo puse
para probar,
no me acuerdo qué.
Y como también tenía
lo de Depter
y alguna vez hecho pruebas,
pues este debería funcionar.
Así que
todo este Firebase config
hacemos lo mismo.
Esta es la configuración
que tenemos
en nuestra variable de entorno, ¿no?
Pues vamos a transformarlo.
Vamos a hacer aquí
el json.stringify
de este objeto, ¿vale?
Qué pena que esto
no ha funcionado antes.
No el copy.
Me ha extrañado, ¿eh?
Pero bueno.
Entonces,
en desarrollo
vamos a tirar
de esta nueva configuración.
Y en producción
vamos a tirar
de la configuración
que estábamos tirando
hasta hace un momento, ¿vale?
O sea, que importante.
Hemos cambiado totalmente.
Ahora,
cuando entremos
en modo desarrollo,
deberíamos ver
unos tweets
totalmente diferentes
porque ahora
no son los mismos.
Pero lo importante
de todo esto
y con lo que te tienes que quedar
es que ahora vamos a tener
dos entornos.
Uno de desarrollo
y otro de producción
de forma que no se mezclan,
de forma que,
total,
esto es público,
pero de esta forma
estamos haciendo un switch, ¿no?
Podemos decir,
bueno,
mientras estoy desarrollando
necesitaré ver,
integrar lo que estoy haciendo,
pero que no sea
en un entorno
donde luego
los usuarios reales
van a ver mis pruebas, ¿no?
Así que
esto es lo que vamos
a intentar conseguir.
Vamos a levantar otra vez
el entorno de desarrollo.
Tenemos NextPublic.
Aquí vemos que está leyendo
las variables de entorno, ¿vale?
Y vamos a ver si esto compila
y deberíamos ver,
aquí tenemos
otros tweets
totalmente diferentes.
Esta es una cuenta
totalmente diferente
donde he estado
haciendo pruebas,
pero como puedes ver
no funciona,
o sea,
no tenemos los tweets
de antes, ¿no?
Porque esos son
de producción.
Así que hemos separado
los entornos.
Ahora tenemos
el entorno de desarrollo
que está en otra base de datos
que además puede tener
unas reglas distintas, ¿no?
En Firebase podemos hacer
que tenga reglas distintas
de forma que, bueno,
cuando está en desarrollo
me da igual
que un usuario
pues intente
crearme un debit,
pues bien por él.
Felicidades.
Pero en producción
voy a ser
con otro entorno,
voy a tener
otras reglas más estrictas
donde voy a asegurarme
que no pueden
hacer ciertas cosas.
Me hubiera gustado
y no sé
si lo haremos
a lo mejor
en otro vídeo
si lo consideráis
que os llama
mucha atención
es que
Firebase
tiene
un sistema
que se puede ejecutar
en local
que creo que se llama
Firebase Emulator
Firebase Emulator
creo que es.
Sé que suena
muy cliché
pero
a ver
Emulator
Firestore
y algunos
de sus servicios
los puedes tener
incluso en local
de forma que
en desarrollo
puede ser incluso
más interesante
ejecutar el emulador.
Tienes Firestore,
tienes Real Time
Database,
tienes Hosting,
tienes las Cloud Functions
pero no tienes
Auth, por ejemplo.
Sé que están trabajando
en ello
pero esto no lo tienen.
O sea que
podríamos tener
el entorno
enteramente no
pero parte de él
en local
utilizando Firebase Emulator
que podría ser interesante.
Igual lo vemos
en uno de los vídeos
pero al menos por ahora
lo hemos separado en dos
que es lo que
justamente queríamos
así que ahora
tenemos esto
que por cierto
dos cosas
antes de que se me olvide
una
vamos a quitar
lo del Relative
no vaya a subir esto así
que no está bien
esto
que haya puesto el False
esto no está bien
ya le preguntaremos a Eric
si ha conseguido que funcione
¿vale?
aquí seguimos con el Timeago
y lo segundo
es que os quería enseñar
una cosita ¿no?
porque antes
hemos comentado
que cuando
y además
también lo compruebo yo
porque a lo mejor
lo hemos hecho así
y está mal
pero así además
en el Try New Things
este es el nuevo entorno
que estamos probando
podríamos ir a Firestore
y deberíamos ser capaces
aquí de borrar un documento
por ejemplo
vamos a ver
este
el
asdasdasdas
adadasdasdas
¿vale?
este
si yo elimino este documento
vamos a ver qué pasa
en la Home
vale
pues se ha eliminado también
¿vale?
justamente lo que queríamos
queremos
este Real Time
¿no?
queremos que si ocurre
cualquier cambio
ya sea que se añade
se modifica
o lo que sea
queremos que
que ese cambio
se refleje
en nuestra página
así que ha funcionado
justamente como esperaba
voy a ver
que me comentáis
ahí en el chat
vamos a ver
wow
oh oh
Eric
ah mira
si tenemos aquí a Eric
Eric
mira un super chat
de 50 pesos mexicanos
muchas gracias Eric
yo estoy diciendo
a ver que Eric
solo porque he visto Eric
y no me acuerdo
del apellido
a ver si es el mismo
¿eres el mismo Eric?
a ver
dime algo
yo creo que sí
es que me sonaba
lo de
si no
si Martínez Roqueñi
Martínez
debe ser el mismo
y le veo la misma cara sonriente
Eric
muchas gracias
muchísimas gracias
y muchas gracias
por las Isus
de verdad
estas cosas ayudan
porque también me ayudan
a ver de lo que hablo
en los streamings
así que bueno
y espero que
aparte de
de esto
que me comentes más
en que
en que dispositivo móvil
no te ha funcionado
la aplicación
el layout
que lo intentaremos arreglar
vale
vale
a ver
que más me comentáis
por aquí
que más me comentáis
por aquí
veo que queréis mucho
Cypress
Cypress 1
2
3
luego
Midudev
¿estará este vídeo
luego en turista de vídeos
pirata del rock?
pues claro
pues claro
¿qué pregunta es esa
pirata del rock?
claro que sí
sí estará en la lista
de hecho ya está
en la lista de reproducción
ya está preparado
ya está preparado
Milan dice que ha llegado tarde
pero justo para
ENV
pues espero que te haya gustado
la explicación
Manuel dice
¿recomiendas utilizar variables
de entorno
.ENV
en proyectos front?
gracias
crack
sí
por supuesto
sí
este es el ejemplo
o sea
por ejemplo
pongamos un proyecto front
que no
no tenemos
en ese proyecto
nada de app
o sea nada de app
no tenemos nada de backend
vale
y solo tenemos el proyecto front
si tú estás desarrollando
en ese proyecto
imaginemos que
que tiras de appis
¿no?
estás tirando de appis
o tienes que crear usuarios
al final
vas a querer evitar
tirar de las appis reales
¿no?
si tienes que crear un usuario
si creas un mensaje
si creas una compra
cualquier cosa de estas
quieres que sean de mentira
o quieres que ocurran
en una base de datos
de que es de
de forma controlada
que no
aunque sea una base de datos
aunque sea más pequeña
que la de producción
pero que no pasen cosas
reales ¿no?
entonces
claro que tiene todo sentido
del mundo
al menos tener dos entornos
seguro ¿no?
uno de producción
porque si no
¿dónde diferencias
de dónde tiran esas appis?
pues los archivos .env
es el mejor sitio
donde puedes hacer
podrías hacer otras cosas
podríamos por ejemplo
que no lo recomiendo
¿vale?
si tenéis que hacer esto
hacerlo como
he comentado aquí
otra cosa que
yo he visto
que la gente hace
que podemos discutir
sobre esto
si está bien o está mal
¿no?
que es mirar
el node.env
si es node.env
pues utilizo uno
si no
o sea
si es node.env
desarrollo
utilizo uno
si no
utilizo el otro
esto lo he hecho yo
también muchas veces
no voy a decir
yo aquí
voy a ir de
no, yo esto nunca lo he hecho
no, alguna vez lo he hecho
y esto a veces
puede estar bien
puede estar bien
en ciertos
entornos
en los que utilice
webpack
¿por qué?
porque webpack
si lo tienes bien configurado
lo que hace
puedes hacer
que el node.env
lo evalúe
de forma estática
¿esto qué quiere decir?
que tú tengas aquí
por ejemplo
tú tengas esto
aquí
firebase config
¿vale?
y aquí pongamos
firebase config
igual
bla bla bla
y aquí
firebase config
si no
pues
tralalala
¿no?
esto es producción
bueno
production
pongamos algo así
para que quede claro
¿no?
entonces
esto no es mi recomendación
eso lo digo
para que lo entendáis
o si veis código
que sepáis
si es webpack
esto lo bueno
es que podría llegar
a hacer una compilación
estática
y utilizando luego
uglify
como este
procesem
esto te lo
dependiendo de tu entorno
te pondría true
y luego
al compilarse
esto
pasaría
a ser
esto
¿vale?
porque
¿qué hace?
que
elimina
las ramas muertas
¿no?
cuando crea tu código
elimina las ramas muertas
y esto
podrías
se hace
y yo lo he hecho
y tal
pero
la buena práctica
yo diría
archivo sen
¿vale?
y ya que Next.js
los tiene soportados
súper fácil
vamos
¿qué más?
¿esas variables
no deben llamarse
react-app-resto-variable?
pues
no tiene por qué
Dairo
sí que sé
que a mucha gente
le encanta
el tema
bueno
naming de variables
y tal
pero
a ver
ya estamos en la react-app
o sea
no sé si es que está
mezclando
con create-react-app
es verdad
en create-react-app
también
tiene
soporte a variables
de entorno
y claro
creo que van por aquí
un poco tus tiros
sí sí sí
claro
en create-react-app
cuando creas un proyecto
también
son compatibles
con las variables
de entorno
de forma similar
a como lo hemos visto
pero
todos tus
variables de entorno
tienen que empezar
con react-app
esto no es lo mismo
con next-js
y no es como funciona
generalmente
los archivos
.env
¿vale?
lo único que tiene
next-js de especial
es que si quieres
que sea público
tienen que empezar
con next-public
en el caso de
create-react-app
tienes que empezar
con react-app
justamente para que funcione
ahora ha entendido
por dónde ha ido
el tema
¿vale?
Diego dice
yo lo que hago
es tener los env
en mi proyecto local
sin subirlo a un repo
y cuando lo quiero subir
para usar esos env
lo que hago es usar
lo que me permite
vercel
que es declarar variables ahí
espero haberme explicado bien
sé que vercel
y muchas plataformas
tienen su apartado
de la redentor
¿no?
efectivamente
el tema de esto
hay que diferenciar
¿no?
y de hecho
me parece muy interesante
lo que has comentado
porque lo quería comentar
y se me ha olvidado
y os quiero enseñar
dónde
claro
porque alguien me diría
vale
entiendo las variables
públicas
¿no?
como estas
esta
que hemos dicho
que es pública
esta entiendo
que puede ir
esta la puede subir
a tu repositorio
¿no?
porque hemos dicho
que esta configuración
puede ser pública
esta es la configuración
que va en el cliente
de Firebase
y ya hemos dicho
que esto es público
así que no hay ningún problema
pero ¿qué pasa con esta?
la que queremos
que sea privada
si no la puedo subir
luego
¿de dónde recupero esto?
¿no?
entonces
depende de dónde
que utilices
nosotros vamos a utilizar
Vercel
y esto
seguramente lo haremos
en un momentito
en un siguiente vídeo
pero
en tu proyecto
esto lo veremos
cuando hagamos el deploy
¿vale?
el siguiente
por ejemplo
midu.dev
que está en mi página
en settings
aquí tendríamos
environment variables
¿vale?
aquí ya tengo una
que es la de YouTube
y está encriptada
esto ya no se ve
hace 82 días
aquí podríamos añadir
esta de Firebase
database url
y aquí ponerle el valor
¿vale?
y le damos a añadir
y ya tenemos
esa variable de entorno
ya la tenemos seteada
para producción
¿vale?
porque aquí tenemos producción
podríamos hacer lo mismo
en preview
o en development
¿vale?
preview sería para
pull request
o development
y aquí lo podemos configurar
otra forma
que se podría configurar
y de hecho
esto es muy interesante
si
esto lo veremos
en funcionamiento
en la siguiente
para que
veamos cómo funciona
¿vale?
pero
con la línea
de comandos
de Vercel
podemos recuperar
las variables
de entorno
que tengamos
que estemos utilizando ya
por ejemplo
vamos a hacer
vercel
env pull
¿vale?
y esto
lo que nos va a crear
ahora no va a funcionar
porque no hemos creado
el link
de este proyecto
con ningún proyecto
de mi cuenta
de Vercel
pero esto
este comando
lo que haría
es descargarse
las variables
de entorno
y generar un archivo
.env
.local
porque claro
yo ya me he logueado
y tal
y entonces se supone
que yo tengo acceso
a eso
y entonces
ya tendría
esta variable de entorno
en mi local
pero no la debería subir
si no aquí
también lo que puedes hacer
es directamente añadir
puedes poner aquí
el nombre
y podríamos poner
Firebase
Database
URL
y directamente
poner el valor
y esto lo que hace
es añadirla
directamente
en el
en el sistema
de deploy de Vercel
¿vale?
y así ya lo tendríamos
tendríamos la variable
de entorno
y también la podemos eliminar
creo que con remove
remove
y le decimos
Firebase
Database
URL
y la eliminas
pues eso sería un poco
creo que además
claro
creo
ahora
claro
como no lo estoy haciendo
tengo dudas
¿vale?
pero creo
que también
le puedes decir
el entorno
aparte del
add
vale
claro
dices el nombre
y luego le dices
el entorno
y seguramente
luego
es que
le das el valor
¿vale?
pero sería así
como añadir
la variable de entorno
le tienes que decir
el entorno
claro
o sea
porque si no
no tiene mucho sentido
si no sería
para múltiples
¿no?
que sería este el caso
le añades
y es para múltiples
y ya está
¿vale?
pues eso sería
utilizando la línea de comandos
o utilizando
pues la UI
que como puedes ver
pues yo ya lo he utilizado
alguna vez
porque si no
no funcionaría
lo importante es que no sea público
que en tu repositorio
esto no exista
pero que tú puedas trabajar
en el local
y también puedas trabajar
Vercell
a la hora de deployarlo
y se quede ahí
¿no?
que se quede totalmente privado
¿vale?
vamos a ver
¿qué más me contáis?
eso quiere decir
que cualquier variable
entorno
si no empieza con
next public
nunca estará accesible
en código cliente
eso es lo que significa
exactamente
si no ponen next public
no se puede ver
en el cliente
¿vale?
si está ignorado
en el gitignore
no está en el código fuente
de lo contrario
si estará
claro
exacto
en el código
en el gitignore
que tenemos aquí
de hecho ya los tenemos añadidos
todos los local
cuando creamos el proyecto
con next
ya nos lo añadió
así que no nos tengo que preocupar
pero
este
env.development
env.production
estos sí que van a estar
¿vale?
importante
y de hecho
otra cosa que se puede hacer
es que
en el punto local
que digamos que son los privados
tú puedes tener
el
uno que sea
privado
pero que no lo puede haber nadie
y dejar en el punto env
un valor por defecto
¿no?
porque de esta forma
pues
podríamos tener este
Firebase database url
que este sería por defecto
pero luego
el que es privado
que por ejemplo
aquí una API
o una IP
que es nuestra
de nuestro servidor
lo podríamos tener aquí
¿vale?
y no lo vería nadie
pero aún así
con el punto env
que sea por defecto
podemos darle otro entorno
donde podría seguir funcionando
la aplicación
¿ok?
eso sería
¿qué más?
¿qué más?
gracias a ti por compartir
no hombre
gracias a ti
muchas gracias Eric
¿se puede acceder directamente
al API o tener los datos
sin estar
no sé si te refieres
a Firebase
o en general
Diego Luna
esto está genial
muchas gracias Diego
las funciones serverless
de Versace
corren en un contenedor
de producción de Docker
no creo que funcione
en un entorno
no se sabe
realmente
debería ser transparente
que es la gracia
de serverless
yo creo que no funciona
en un entorno
de producción
en Docker
de hecho
creo que son directamente
Lambda Functions
o sea claro
es que
las funciones serverless
son Lambdas
y yo creo
que funcionan
en entornos
a AWS
que no creo
que utilicen Docker
porque es que
debe ser incluso
todavía más
tendrá algún sistema
interno
Amazon
bastante más
a bajo nivel
creo yo
no sé
se me escapa
pero son Lambdas
seguro
o sea que
¿se puede limitar
el acceso al público
a un solo campo
de una colección?
a un solo campo
de una colección
yo creo que sí
si quieres
me lo apunto
y lo miraremos
pero yo creo
que sí
¿vale?
de lo que has comentado
a ver
Milán
después de lo que has comentado
entiendo que cosas
súper privadas
en front
usar el enf.local
y luego añadirle prefijo
para lo que pille
next view
es una mala práctica
¿qué recomiendas?
a ver
no es una recomendación
pero básicamente es
si es privado
tiene que ir
en un enf.local
y no le puedes poner
next public
porque si es next public
y luego lo utilizas
en tu código
eso va a quedar
ahí en línea
ya está
si es privado
tiene que ir
en enf.local
o enf.production.local
porque además
enf.local
digamos que es
para todos los entornos
pero tú luego
puedes poner
esos privados
esas variables privadas
por cada uno
de los entornos
entonces
ahí lo tenías
¿por parte de backend
qué trabajo tienes pensado
hacer para nuestro
clon de Twitter?
de parte de backend
la idea justamente
era que Firebase
no lo diese todo
pero a lo mejor
sí que vemos con Node
vamos a ver el tema
de las cloud functions
de Firebase
y eso es Node
y yo considero
que es backend
así que
espérate al rock
ya te he dicho
que queda en la lista
de producción
que no te preocupes
hombre
sigue adelante
con tu vídeo
dice DeadCode
bueno
pues yo creo que
ya lo podemos dejar aquí
que hemos estado
dos horas
pensaba que hoy
íbamos a estar menos
pero al final
hemos estado un buen rato
hemos estado charlando
y tal
muchísimas gracias
a todos y a todas
los que habéis estado
hoy aquí
ha sido un verdadero placer
como siempre
compartir con ustedes
antes de irte
dale al like
¿vale?
que no se te olvide
dale al like
tus likes
me ayudan
me ayudan muchísimo
para seguir animándome
a todas las semanas
a hacer esto
hasta en mi do classes
y bueno
que tus likes
me dan calor
¿no?
me siento acompañado
y pues nada
me siento desde que
te gustan los vídeos
y me anima a hacer más
así que
si te gusta
mi contenido
pues ya sabes
dale like
compártelo
si no estás suscrito
aquí
aquí abajo
te puedes
te puedes suscribir
le das a la campanita
para que te sube
te avise
¿vale?
cuando suba un vídeo
y
¿qué puedo decir?
que de corazón
muchísimas gracias
por estar aquí
muchas gracias
una semana más
esto es brutal
Sergio
gracias una semana más
dice Sergio
Daniel Pérez
saludo a mi duele
desde Puebla
México
Puebla
mira tengo un
tengo un cuñao
en Puebla
que gracioso
gracias Messi
dice Beto
me he quedado en el Barça
que no se diga
mira con mi estrellita
de Gijap
con mi estrellita
de Gijap
me he quedado en el Barça
al final
tengo un
¿cómo es esto?
anda
mira
Adrián González
Ars
100 Ars
muchas gracias
muchas gracias
Adrián
no gracias a ti
dice saludo gracias
no gracias a ti
Sebastián
Mesidev
muchas gracias
de corazón
vamos like
like a tope
like
compartir en vuestras redes sociales
hacer retuit
cuando pongo algo y tal
que siempre me ayuda
os lo agradezco de corazón
que me ayuda a crecer
y a ver si puedo seguir dándole
contenido y cariño al canal
que siempre está bien
y yo me lo paso pipa
así que yo creo que es un win-win
para todos
pues nada
espero que os cuidéis muchísimo
tengáis mucho cuidado
en estos tiempos
y sobre todo
por supuesto
sin ningún tipo de duda
que seguáis dándole al frontend
¿vale?
que os acompaño ahí
Crack
gracias por compartir
dice Milán
gracias Midu
Ricardo
muchas gracias Diego
Pirata del Rock
dice que estaba en Colombia
muchas gracias
muchas gracias Julio
ánimo
me gusta mucho esto
me siento como un desarrollador profesional
siguiendo estos lives
muchas gracias
te lo agradezco un montón
Julio Barajas
te mando un abrazo enorme
y muchísimas gracias por
por aportar
os lo agradezco de corazón
por acompañarme
nos vemos
¿qué nos queda por hacer?
dice Julio
nos queda el deploy
en la siguiente clase
que no os lo he dicho
vamos a ver el deploy ¿vale?
siguiente clase
deployamos a Vercell
eso seguro
y
y no sé si nos dará tiempo
a Cloud Functions
pero me lo voy a mirar
a ver si nos da tiempo
y a ver si lo podemos hacer
así que nos queda eso
gracias Mariano
chao Nicolás
un abrazo
saludos de la fraternidad Mariano
como siempre
buen viernes
y que tengáis un buen fin de semana
nos vemos en el siguiente
en los próximos vídeos
aquí
en Midudev
así que ya sabéis
no paréis de darle
al frontend
hasta luego
cuidaos mucho
un abrazo enorme
chao
un abrazo enorme
un abrazo enorme
un abrazo enorme
un abrazo enorme
un abrazo enorme
un abrazo enorme