logo

midudev


Transcribed podcasts: 167
Time transcribed: 5d 15h 37m 28s

This graph shows how many times the word ______ has been mentioned throughout the history of the program.

Tienen muchos repositorios y en cada repositorio un paquete y además dependen entre ellos.
Hoy vas a aprender para ver cómo puedes migrar esa estructura a un monorepositorio multipaquete.
¿Y esto qué quiere decir? Pues que en un solo repositorio vas a tener todos esos paquetes
y van a poder estar compartiendo dependencias y te va a facilitar mucho el desarrollo.
Todo esto lo vas a conseguir gracias a los NPM Workspaces, algo que está disponible desde la última versión de NPM.
Los repositorios que vamos a usar son los de backend y frontend que hemos ido desarrollando en las anteriores clases.
Te dejo aquí la lista de vídeos por si quieres repasarlos y que no se te pierda ninguno.
Bueno y ahora te estás preguntando, ¿realmente esto para qué sirve? Pues para un montón de cosas.
Esto hace que sea más mantenible tu código porque está en un solo sitio, mucho más fácil de encontrar y de manejar.
Luego vas a poder compartir dependencias, configuraciones como por ejemplo la del linter que es bastante grande.
La puedes tener en un solo repositorio y además el despliegue es mucho más sencillo
porque ya no tienes que estar deployando, desplegando paquetes de forma separada, sino que lo tienes en un solo sitio.
Y por eso vamos a ver al final de la clase cómo podemos desplegar nuestro monorepo multipaquete con Heroku.
Pero creo que lo mejor es que lo vayamos haciendo. Así que venga, vamos a empezar.
Lo primero que vamos a hacer es crear una nueva carpeta, ¿vale?
Vamos a hacer una nueva carpeta, le vamos a añadir nodes app, ¿vale?
Entramos a nodes app y lo primero que hacemos es inicializar nuestro proyecto de npm como siempre con el menos sí, que significa que sí a todo.
Ahora que ya tenemos esto, lo que deberíamos hacer es recuperar nuestros proyectos, ¿vale?
Teníamos uno que era nodes barra, bueno, guión API. Este era uno y aquí teníamos todos nuestros archivos.
El nodes API lo primero que hago es copiar de forma recursiva.
Voy a copiarme el nodes API y voy a traerlo a la carpeta API, ¿vale?
nodes app, vale, la he liado porque no es un punto, son dos puntos, ¿vale?
Esa es la relativa, no es un punto, son dos.
Ahora sí, debería estar copiando. Espero que esto no haga que reviente absolutamente nada.
Ya me he copiado la API en este nuevo proyecto.
Vamos a hacer lo mismo, pero con la aplicación.
Vamos a buscarla, creo que era app, esta, fullstackbookcamp.
Y esto lo vamos a dejar en la carpeta app.
Pensad que se está copiando todos los nuevos módulos y todo, pero bueno, lo vamos a quitar.
Esto no lo necesitamos como tal, así que ahora lo eliminaremos.
Pero lo más fácil, podrías arrastrar las carpetas, lo podrías hacer como quieras.
Ahora ya vamos a entrar al proyecto donde van a estar conviviendo estos dos proyectos.
Pero fíjate que cada proyecto tiene su propio package.json, tiene sus propias dependencias.
Así que necesitaríamos que cada uno de ellos se instalase en esas dependencias
y que todo siguiese funcionando correctamente.
Así que ahora tenemos como un proyecto, que sería el de la raíz, que tiene su propio package.json,
que se llama nodes app, que puede tener sus propias dependencias, sus propios scripts y tal.
Y tenemos dentro otros dos proyectos que cada uno de ellos tiene su package.json.
Entonces aquí es donde ya tenemos este concepto de monorepo, en el sentido de que es un solo proyecto
y lo vamos a subir a un solo repositorio multipaquete, porque tenemos dos paquetes dentro.
En realidad tres, porque también tenemos este, pero este normalmente se hace que sea privado.
Se utiliza aquí private true y esto lo que significa es que no se va a publicar este paquete a npm ni nada.
Esto es opcional, pero veis, si lo queréis hacer para evitar publicarlo sin querer, pues lo podéis hacer.
Ahora que ya tenemos esto, como ya sabéis, lo que vamos a hacer es intentar unificar ciertas cosas.
Por ejemplo, en la API teníamos estándar para el linter, pero ya no tiene tanto sentido que la API tenga un linter,
que el otro tenga otro linter.
Me gustaría justamente unificarlos, lo que puedo hacer para eso, el linter tiene sentido que esté en la raíz,
en lugar de estar en los dos proyectos de forma separada.
Así que voy a sacar este slint config y me lo voy a llevar a la raíz.
Y además voy a ver por aquí cuáles son las dependencias.
Aquí veo que tengo slint, esta no es necesaria.
Tengo por aquí estándar, esta me la voy a llevar.
Y las voy a quitar del proyecto de API, porque aquí no tiene tanto sentido.
Lo voy a llevar a la raíz y de esta forma lo que voy a hacer es compartirlo con los dos proyectos.
Lo vamos a dejar en DevDependencies.
Vamos a quitar el trailing coma.
Vamos a por lo siguiente.
Ahora vamos a por la app.
En la app vamos a ver cómo tenemos esta configuración del linter.
Por aquí veo que tengo...
El linter normalmente en las aplicaciones de Creative Rack App ya está configurado de forma interna,
pero nosotros añadimos también lo de Cypress.
Esto también nos lo vamos a llevar,
porque vamos a querer también que si tuviésemos más paquetes que utilizan Cypress,
pues que también los entienda.
Así que voy a fusionar estas dos configuraciones.
Esto por aquí.
Este Extents no lo vamos a excitar porque vamos a utilizar el de estándar.
Y este Plugins no lo teníamos, pues lo ponemos aquí.
Así que ahora ya lo hemos fusionado.
Vamos a guardar este, el de la API.
Y por aquí este sería el de la app.
Ya no necesitamos esto de SlimConfig.
Lo quitamos.
Y vamos a ver qué teníamos por aquí.
Aquí teníamos el Slim Plugins Cypress.
Este lo vamos a llevar a la raíz,
porque lo vamos a excitar aquí en Plugins Cypress.
Pues aquí como DevDependency la vamos a poner aquí.
Ya tendríamos como en la raíz todo lo que tiene que ver con el linter.
Y se va a compartir esta información tanto para la API como la app.
Luego veremos qué problemas nos podemos encontrar con esto,
pero ahora mismo parece que tiene sentido lo que estamos haciendo.
Una cosa que podemos incluso arreglar también,
bueno, aquí no tenemos ningún script que tire el linter.
Y aquí en API sí que tenemos este.
Este ya no tiene mucho sentido, así que lo eliminamos.
No se nos ha quedado nada del linter, perfecto.
Vamos a por el siguiente paso.
Antes de hacer nada, importantísimo.
La funcionalidad que vamos a ver está en npm-npm7.
Si vamos a npmgs-docs, vais a ver que la documentación la tenéis versionada.
Buscamos Workspaces.
Aquí tenemos versión 7.
La versión 7 es la última disponible.
La versión 6 seguramente es de las más usadas,
porque la versión 7 ha traído bastantes cambios,
entre ellas cómo se manejan las peer dependencies.
No lo vamos a ver en esta clase,
pero es importante que sepas que ha cambiado cómo funcionan las peer dependencies.
Lo más interesante de la 7 es que viene esta nueva funcionalidad llamada Workspaces
que te permite trabajar justamente con este monorepo multipaquete de forma muy, muy sencilla.
En lugar de ponernos a mirar la documentación,
ya os lo explico yo que va a ser mejor.
Primero, vamos a asegurarnos que tenemos la versión correcta de npm, la 7.9.0.
Si tenéis la 6, necesitáis la 7 para hacer esto,
porque la 6 no tiene esta funcionalidad.
Así que, tenerlo en cuenta, comprobarlo antes de poder utilizar esta funcionalidad.
¿Cómo se utiliza esto de Workspaces?
Pues aquí en el package.json que tenemos en la array,
lo que vamos a hacer es indicarle dónde se encuentran nuestros paquetes.
Así que añadimos Workspaces y esto es un array donde le decimos todos los paquetes que tenemos en nuestra aplicación.
En este caso tenemos, por ejemplo, API y tenemos App.
Lo interesante de esto de Workspaces, porque en este caso justamente no sabemos el nombre,
es que también puedes utilizar patrones.
¿Esto qué quiere decir?
Pues que imagínate que tienes la carpeta Components
y dentro tienes un montón de componentes y cada uno es un paquete publicable
que tiene sus propias dependencias y tal.
Pues puedes hacer asterisco, asterisco, como para indicarle dentro de la carpeta Components
tengo subcarpetas que tienen su package.json.
Lo que va a hacer NPM es detectarlos.
Y va a decir, ah, vale, que aquí tienes un package.json,
pues esto es un paquete más en el Workspace.
Y lo va a detectar sin ningún problema.
Pero en este caso, como tengo muy claro que es API app, ya lo podríamos hacer.
Hay otra gente que utiliza packages y dentro de los packages ya ahí mete toda la información.
Entonces pone asterisco, asterisco y ya está.
Pero a mí en este caso me gusta más tener la API, la API,
y ese día de mañana tenemos otro, pues lo ponemos ahí directamente
en lugar de poner los asteriscos porque creo que queda un poquito más claro.
Pero esto como es totalmente subjetivo, si lo ves de otra forma,
pues lo puedes hacer como tú quieras.
Ahora que tenemos esto, podemos hacer el NPM install.
El NPM install de toda la vida.
Pero verás que el NPM install lo voy a hacer solo una vez y aquí, en la raíz,
en lugar de entrar en todas las carpetas.
Para evitar problemas, porque suele ser muy típico tener problemas
de dependencias cruzadas y tal,
lo que vamos a hacer además es eliminar la carpeta NodeModules de la API.
Vamos a eliminarla y también de la app, porque estas son las dependencias
que ya habíamos instalado previamente cuando estaban separados estos proyectos.
Y entonces puede entrar un poco en conflicto.
Y ya veremos por qué.
Porque ahora cuando haga el NPM install, vamos a hacer el NPM install.
Y esto lo que va a hacer recorrer todos los workspaces
y va a encontrar las dependencias que se deben compartir
entre los dos paquetes que tenemos, entre la app y la app.
Por ejemplo, imaginad que tenemos React, la versión 17, en los dos paquetes.
Pues lo que va a hacer, justamente, lo que va a hacer es compartir
esa dependencia entre los dos paquetes y la va a instalar una sola vez.
Esto lo que significa normalmente, le dicen que es aplanar las dependencias.
Esto siempre lo ha hecho NPM, pero en este caso está llevándolo
a un nivel más extremo, porque lo que está haciendo, aplanando esto,
es compartir dependencias entre paquetes distintos.
¿Vale? O sea, es un nivel mucho mayor.
Vamos a ello.
Ahora que ha hecho el NPM install, si yo entro a la API,
podemos ver que ahora en la API no tengo ningún NodeModules.
Parece como que no me he instalado las dependencias de la API.
Y si voy a la app, tampoco tengo ningún NodeModules.
Y es que lo que ha hecho es dejarlo aquí todo aplanado.
Todo aplanado.
Tienes todos en la raíz.
Y en la raíz es donde tiene todas las dependencias,
la API y la app, para funcionar.
Esto, además, tiene una cosa todavía más interesante.
Y es que si por lo que fuese, tú tuvieses en estos paquetes,
en uno de estos paquetes, API App,
tuvieses un paquete llamado, por ejemplo, Midu.
Pongamos el paquete Midu.
Y tú en la app utilizas el paquete en dependencias.
¿Vale?
Tenemos aquí el paquete Midu, la versión 1.0.0.
Y esta versión y esta dependencia la tienes aquí, justamente.
Imagínate que tenemos aquí esto, Midu.
Y esto tiene un package JSON.
Y el package JSON justo tiene la versión 1.0.0.
NPM lo que haría es que en lugar de descargar de internet
esta dependencia de Midu,
al encontrarla en las workspaces, lo que haría es instalarlo localmente.
Y esto es muy interesante,
porque se va a evitar ir a internet a descargarse esta versión
y, además, va a utilizar la última versión que sí machea,
que es importante, tiene que machear,
que machee, justamente, tu versión.
Va a ser totalmente local.
No va a ir a internet a buscar ninguna cosa.
Esto con catálogos de storybook y cosas así,
cuando estás utilizando componentes uno detrás de otro,
que, además, se publican todos, esto va muy bien.
No lo vamos a ver en este ejemplo, porque, bueno, lo he enseñado más o menos,
pero no vais a ver que no lo vamos a utilizar,
porque en nuestro caso no tiene mucho sentido.
Porque la API no puede ser una dependencia de la API y tal.
Aquí hay una cosa interesante.
¿Veis que me sale aquí, cuando yo al solos control,
me sale API, app y me salen también los cambios?
Esto es porque, cuando me he copiado las carpetas,
lo que se está quedando aquí es que son repositorios de Git.
Para evitarnos estos problemas al copiar, ¿no?
Y que se quede ahí todo el repositorio de Git.
Ahora se cree que tenemos tres repositorios de Git.
Bueno, esto no está bien.
Lo que vamos a hacer es hacer un RF de API y .gip.
Esto lo que va a hacer es eliminar todo el histórico
y toda la información del repositorio que tenía la API.
Así que, si le damos, lo hacemos también con la app.
Esto, si no, luego, más adelante puede ser problemático.
Así que ahora, ahora en nuestro repositorio,
el raíz todavía no está inicializado y ninguno nos aparece.
Esto es correcto, tiene más sentido.
Perfecto.
Ya tenemos instaladas las dependencias.
Lo mejor que podemos hacer es asegurarnos que funciona nuestro proyecto, ¿no?
Que podemos ir a la API y levantarla y que todo funcione y eso.
Antes de que se me olvide, vamos a poner el gitignore con nodeModules y el .env, ¿vale?
Por si lo ponemos, para que no se suban al repositorio.
Vamos a ver si funciona nuestra API.
En la API ya teníamos aquí diferentes scripts,
que sería, pues, para, bueno, el de lintar lo he linado, pues no tiene mucho sentido.
Ya lo he pasado a la raíz.
Luego lo podemos probar a ver si funciona.
Y tendríamos el de modo dev, el de start, start test y todo esto.
Bueno, pues vamos a entrar a la API, vamos a hacer un npm run y voy a hacer el de, no sé, el de dev, por ejemplo.
A ver si todo funciona bien.
Funciona correctamente.
Por eso justamente que te comentaba, porque ha instalado las dependencias de la raíz
y es capaz de resolverlas sin ningún problema.
Ahora en el puerto 3001, pues, tenemos nuestra API levantada y ya está.
Esto mismo lo podríamos hacer, pues, con todos los scripts,
solo para asegurarnos que todo está funcionando bien.
Por ejemplo, el start es bastante importante porque es el de producción, pues, funciona bien.
Bien, podríamos ver si los tests están pasando, si se están ejecutando o no.
Bueno, teníamos aquí el de user, ¿vale?
Pues están pasando y se están ejecutando sin ningún tipo de problema.
Ya sabemos que la app funciona, la API funciona, así que vamos a pasar al siguiente.
Vamos a la app, que la app es bastante importante y un poquito más complicada.
Ya veréis.
Npm run.
Tenemos aquí un montón de scripts.
Vamos a probar primero, por ejemplo, el de los tests, por decir uno, ¿vale?
Npm run test, que dejamos ya algunos tests.
Vale, aquí nos da un error.
Un error bastante, bastante, bastante largo, con un montón de información.
Esto es una cosa que está muy bien.
Y es el hecho de que nos está explicando, ¿no?
Parece que hay un problema en nuestro proyecto y tal.
Bueno, no te preocupes porque lo vamos a solucionar sin ningún tipo de problema, ¿vale?
El tema es que, como te decía, cuando se comparten las dependencias, ¿qué está ocurriendo?
Que al aplanar las dependencias, quizás la API ha instalado una versión de una dependencia
que nuestra aplicación necesita otra diferente.
Y de hecho es lo que nos está comentando.
En este caso, es por cómo funcionan de diferente las peer dependencies.
Y claro, aquí se está haciendo un poco un lío.
Mi opinión es que Create Breakup todavía no funciona muy bien con Npm 7 y los workspaces.
Y seguramente lo arreglarán y tal.
Pero se puede solucionar de forma más o menos sencilla.
Una de ellas, justamente, sería ignorar el problema.
¿Por qué?
Porque la versión que realmente estamos utilizando sí que es compatible.
Lo que nos está diciendo aquí es que puede ser incompatible.
Pero ya te digo que sí que es compatible.
Te da un montón de pasos que puedes intentar para arreglarlo.
Pero uno de ellos es justamente el de hacer un skip de este check.
Porque en este caso no tiene sentido.
Porque sí que sé que es compatible.
Y es lo que vamos a hacer.
Ya nos dice que podemos crear un archivo .env y ponerle este flag.
Pues lo vamos a hacer.
Vamos a nuestra aplicación.
Creamos el .env y vamos a poner este teflag que al final solo es un check.
Seguramente esto, más pronto que tarde, no va a ser necesario.
Vamos a volver a probar a ver si ahora parece ser que sí que funciona.
Y además los tests están pasando correctamente.
Ya tenemos esto totalmente arreglado.
Ahora sabemos que los tests funcionan, pero nuestra aplicación.
Vamos a ver.
Npm start.
Nos está abriendo en el puerto 3000 nuestra aplicación.
Parece que sí que está levantando un entorno de desarrollo.
Y en el puerto 3000, vale, pues ya la tenemos.
No aparecen las notas porque no tenemos levantada la API.
Faltaría para asegurarnos que se puede hacer una build.
Voy a eliminar la build que teníamos aquí.
Y vamos a hacer npm run build.
La build lo que quiere decir es que vamos a compilar toda nuestra aplicación
para que se pueda desplegar a producto.
Vamos a hacer la build a ver si no hay ningún problema.
Es bastante importante que no haya ningún problema porque esto es lo que necesitamos.
Estos son los archivos que necesitamos para poder desplegar en producción.
Perfecto.
Pues parece que todo ha funcionado bien.
Si hago un ls, voy a build.
Pues aquí tengo todos nuestros ficheros.
Muy bien.
Ahora que tengo la carpeta build, ¿qué es lo que voy a hacer?
Vamos a volver a nuestro proyecto donde teníamos todo.
Teníamos la API y la app.
Y en la API, en realidad la API va a hacer un poquito más de API.
Más que de API.
No solo va a hacer de API, sino que va a ir un poquito más allá.
Y es que si vamos en index.js, ya teníamos una forma de servir información estática.
Teníamos imágenes y tal.
Bueno, este de imágenes ya os digo que no lo vamos a necesitar y ahora lo eliminaremos.
Pero también por aquí se nos quedó esto, que esto tampoco lo necesitamos.
Que era para enseñar un Hello World en el caso de que entrásemos a la raíz de la API.
De hecho, lo podemos levantar para que lo veamos.
En pie en randev.
Vamos al puerto 3001, que es donde se queda la API.
Tenemos el Hello World.
Bueno, pues esto no es tan interesante.
No queremos un Hello World, sino lo que vamos a hacer es servir nuestra app desde el servidor.
Y para ello vamos a utilizar justamente la carpeta build que acabamos de crear en la app.
¿Cómo hacemos eso?
Bueno, ya he eliminado Hello World.
Vamos a volver para arriba.
Aquí teníamos imágenes.
Esto lo vamos a quitar.
O lo podemos adaptar más que quitar.
Bueno, lo voy a quitar para hacerlo desde cero para que lo veáis.
¿Vale?
Es un app.use.
Ahora podríamos decirle cuál es el path, pero en lugar de eso lo que vamos a decirle es que queremos que lea los estáticos de la carpeta que está en punto punto barra app.
Todo lo que tenemos en build, que es justamente nuestra aplicación de React, queremos que se sirva de forma estática en nuestra aplicación desde nuestro servidor.
Esto es lo que queremos hacer.
Así que vamos a ver si esto funciona.
Ahora se ha reseteado.
Ahora si refresco aquí.
¡Tachán!
Ya tenemos nuestra aplicación de React, de la que acabamos de hacer una compilación y además está funcionando con la API.
¿Por qué?
Porque tenemos justamente la API también levantada.
Hemos levantado la API, pero justamente leyendo los estáticos que hemos construido desde nuestra aplicación de React, la estamos mostrando aquí.
Así que es un win-win.
Ya tenemos las dos cosas.
Sin embargo, sin embargo, esto está muy bien.
Esto está muy bien, pero pasa una cosa.
Y es que si revisamos el código que tenemos en nuestra aplicación, todavía no está preparado del todo.
Hay una pequeña trampa.
¿Cuál es la trampa?
La trampa es que revisando nuestros ficheros, tal y como los dejamos en la aplicación de React, fíjate la base URL.
Esto tiene aquí un localhost 3001 y aquí en Notas, en Login, tiene localhost 3001 y en Notas 3001.
Claro, si yo deployo esto a producción, pues esto no tiene mucho sentido, ¿no?
Porque va a intentar buscar localhost 3001 y no existe.
No tenemos localhost 3001 en producción.
Lo que vamos a hacer es eliminar esto.
¿Y dónde debería tirar?
Pues vamos a aprovecharnos que está justamente en la misma ruta, ¿no?
Si nos fijamos ahora mismo en localhost 3001, es donde estamos sirviendo nuestra aplicación.
Fíjate que antes la aplicación la servíamos en el 3000, pero aquí, como es el servidor que tenemos y lo tenemos en el puerto 3001,
lo que estamos recuperando son los estáticos, los ficheros estáticos de nuestra aplicación.
Los estamos sirviendo y además tenemos la API levantada en el mismo puerto.
Así que lo que vamos a hacer es utilizar una ruta relativa.
¿Por qué?
Porque cuando deployemos esto, ya sea en el localhost 3001, ya sea en notesapp.com, lo importante es que tengamos las mismas rutas.
Y como nuestra aplicación ahora está toda junta, ya sabemos que las rutas siempre van a encajar perfectamente.
Así que no es tan importante que sea localhost 3001, lo importante son las rutas.
Así que le quitamos lo del localhost 3001.
Vamos a poner esto por aquí, localhost 3001.
Y ahora, pues vamos a, bueno, ahora se debería volver a generar la build y todo esto, ¿no?
Deberíamos ir otra vez a nuestra aplicación, en el notesapp y aquí en el app deberíamos volver a hacer un npm run.
Bueno, esto está otra vez muy pequeño.
npm run, ¿no?
Y nos aparece aquí el build, npm run build y esto nos volvería a generar los estáticos.
Esto al final, claro, podríamos ponerle un watch también para que lo haga automáticamente,
pero al final lo importante es que se debería hacer una sola vez.
Vamos a poner, hay que asegurarse que nuestra aplicación sigue funcionando también en modo de desarrollo.
Así que vamos a ver si la levanto.
Voy a hacer aquí un npm run start, que esto me debería levantar la aplicación en modo de desarrollo en el puerto 3000.
Podemos ver que la aplicación en el puerto 3000, solo la aplicación de React, no me enseña las notas,
pero sí que tengo la API levantada, ¿no?
Si miramos aquí la terminal, esto sería la API, la tengo levantada en el puerto 3001
y aquí es la aplicación de React, el puerto 3000 y no me enseña las notas.
No me las enseña justamente por el cambio que he hecho aquí, ¿no?
Que he hecho relativo, que está intentando buscar, no me las está encontrando,
porque está intentando buscar de forma relativa en el puerto 3000.
Está intentando hacer localhost 3000 barra API barra notes, pero yo lo tengo en el 3001.
Entonces, ¿qué hacemos con esto?
Vaya problema, ¿no?
Pues no es un problema, no pasa nada.
Esto nos está ocurriendo justamente porque estamos desarrollando.
Pues se puede hacer una cosa para arreglar esto.
En el package.json de nuestro proyecto este de notas, la aplicación de React,
lo que podemos es añadir una nueva configuración aquí que sea proxy.
Y lo que le vamos a decir es que tiene que hacer un proxy localhost 3001.
Esto solo funciona en modo desarrollo, justamente para eso, para que no funcione en modo desarrollo.
Vamos a ver si cierro esto y lo vuelvo a levantar.
A ver si ahora lo toma y funciona bien.
¿Ves? Ahora sí que vemos los cambios.
Y si miro, inspecciono la red, vamos a ver, puedo ver aquí que sí que funciona correctamente.
Pese a que está intentando buscar esto, si miramos la request, se la pongo una nueva, ¿veis?
Localhost API notes.
O sea que parece que está funcionando bien.
Esto es en modo desarrollo que tú le puedes decir, vale, ve a buscar a otra URL, a otra dirección,
como si fuese tu propia dirección.
Tienes que hacer un proxy, que esto es interceptar esas requests y hacer pasar que están desde tu mismo dominio.
Esto es súper útil siempre que se trabaja con localhost y cosas así, ¿vale?
Así que con esto ya lo tendríamos solucionado, ya tendríamos nuestra aplicación con las dos cositas
y en este caso tendríamos en modo desarrollo funcionando para las.
Perfecto.
Ya estamos preparando casi, casi, tenemos ya casi nuestra aplicación que estaba a punto de, vamos,
está a punto de caramelo para que la podamos desplegar.
A mí hay una cosa todavía que me está escamando un poco, ¿vale?
Y es que cuando yo estoy aquí trabajando, estoy todo el rato entrando en un proyecto,
en pn run, voy a otro proyecto, en pn run, y es un poco, es un poco rollo, ¿no?
Porque la idea de tener un proyecto, un monorepo, un multipaquete, es que desde la raíz tú puedas lanzar scripts
que funcionen en cualquier workspace.
Pues vamos a hacer que eso sea así, ¿vale?
Por ejemplo, si vamos a la raíz, aquí en el package.json, aquí que pone este test y tal, voy a quitar este script,
este script es solo para la raíz, ¿vale?
¿Qué podemos hacer? Pues podríamos poner, por ejemplo, un build.
La build, esto en realidad es para la aplicación de React, como hemos visto.
Pues vamos a hacer un npm run build y le vamos a indicar en qué workspace tiene que ejecutar este comando.
Así que decimos, esto es para el workspace, le decimos igual a ahora, imagínate que queremos levantar lo que es nuestra API.
Pues podemos poner, y esto debe ser npm run start y le decimos el workspace donde lo tiene que ejecutar ese comando.
Pues podríamos ir un poco más allá, el modo de desarrollo, porque esto es para levantar la API,
pero justamente el modo de desarrollo de la API, pues hacemos esto, npm run primero build.
¿Por qué el build primero?
Porque claro, para que funcione la API ya hemos visto que vamos a necesitar los recursos que nos está dando la compilación de la aplicación de React, ¿no?
Así que vamos a hacer esto y aquí en el igual podemos hacer npm run dev workspace igual API.
Esto podríamos seguir, ¿no? Y ir viendo cuáles son los comandos que queremos hacer desde la raíz y decirle, vale, este npm run build es del workspace app.
Lo puedes ejecutar desde aquí, de hecho lo vamos a hacer, pero esto lo que va a hacer es ejecutar el comando build dentro de app.
Si vamos a app, vamos al package.json y aquí tendríamos, será este de aquí.
Es una forma muy interesante de tenerlo todo en el package.json de la raíz y no tener que preocupar de tener que ir entrando, ver cómo funciona y todo esto.
Así que ya tendríamos aquí los scripts, podríamos ir añadiendo los que necesitemos.
En nuestro caso vamos a poner el de build y este de startup y lo voy a dejar como start y te voy a explicar por qué.
Como vamos a desplegar en Heroku, el tema es que el build se ejecuta justo antes de hacer el despliegue.
Y el start es el comando que Heroku va a ejecutar para levantar el servidor.
Entonces es como un estándar que ya existe.
Y justamente nosotros es lo que necesitamos, que primero construya nuestra aplicación de React y luego ejecute y levante el servidor para que funcione nuestra aplicación.
Así que estos dos comandos, que los podemos utilizar nosotros aquí, también le va a servir justamente a Heroku para que nosotros no tengamos que configurar nada más.
Así que va a ser como construyeme mi aplicación y luego me levantas el servidor.
Si queremos comprobar que esto funciona, podemos ejecutar aquí un npm run build.
Esto debería funcionar bien. Lo estoy haciendo en la raíz, pero esto ha entrado internamente a la app y está construyendo la aplicación.
Y lo mismo si hago un npm start, pues me debería levantar nuestra API y ya estaría.
Ya hemos cambiado la URL, ya tenemos esto. Pues yo creo que lo único que nos queda es hacer nuestro repositorio.
Al final, nuestro repositorio, voy a crear por aquí new y vamos a poner nodes app mono repo.
Por ejemplo, vamos a hacer que sea público, creo el repositorio. Ahora que hemos creado el repositorio, pues lo que puedo hacer aquí es un git init.
Voy a inicializar el repositorio del proyecto este, donde tengo mis dos paquetes.
Hago un git remote at origin y nos copiamos este de aquí.
¿Vale? Estamos por aquí. Ya tenemos la dirección remota de nuestro repositorio.
Y ahora, bueno, puedes dejar master o puedes cambiar a otra rama para que sea main, que es lo que ahora se lleva.
En lugar de utilizar master se utiliza main, el que prefieras, el que más te guste.
Hay un comando, esto solo lo hago por si acaso.
Esto es porque antes API y app tenían sus propios repositorios de git.
Quizás no lo necesitamos, pero hay veces que se puede quedar en caché que tenías un repositorio dentro de otro repositorio.
Así que esto que voy a hacer es como para eliminar, o para asegurarme que no está cacheado.
Vale, no hay ningún problema. Así que, vale, por si acaso.
Vale, por si acaso. Para evitar que me diga, oye, que tienes un repositorio dentro del repositorio.
Ahora que ya tengo esto, vale, sí, me lo está encontrando como directorio, o sea que ningún problema.
Voy a añadir todos los ficheros que tengo y los voy a ver que están poniéndolos correctamente.
A ver que no haya nada raro por aquí. Parece que sí.
Profile, bueno, profile ese no es importante.
Vale, estaba mirando a ver si estaba el .env, pero ya veo que no está.
Vale, perfecto. Pues nada, vamos a añadir estos ficheros.
Add files y de esto deberíamos hacer un git push origin main.
Y si todo funciona bien, ¿qué debería ser?
Deberíamos poder volver a nuestro repositorio, refrescar y aquí ahora tenemos toda la información.
Tenemos ya toda la API, el app y nuestro package JSON.
Más cositas todavía, ¿no?
Ahora tendríamos que crear nuestra app con Heroku.
La voy a crear ya. Heroku create, ¿vale?
Crea nuestra aplicación. Ya tenemos aquí una URL con nuestra aplicación.
Perfecto. Pero antes de desplegar esto a producción en Heroku, hay otro detallito que tenemos que hacer.
Lo puedo desplegar, pero como tarda bastante en desplegarse y tal, y sé que me va a dar problemas, ya te lo cuento.
El tema es que tú en Heroku le puedes indicar qué versión de Node quieres utilizar a la hora de desplegarse.
Por defecto, como no le estamos poniendo aquí ninguna versión, por defecto la versión que va a utilizar es la 14.
Y la 14 viene con npm 6. Y entonces no nos funcionaría correctamente, porque hemos dicho que los workspaces están en npm 7.
Así que lo que podemos hacer es utilizar en chains y aquí le puedes decir, vale, pues además le puedes decir la versión de Node, la que sea, ¿no?
Puedes decir Node, esta tiene que ser la 15.
Otra cosa que puedes hacer es decirle de npm necesito la versión, pues creo que la última es la 7.9.0.
Bueno, pues le vamos a poner justamente esta para que nos instale esta en concreto.
Otro problema que sé que vamos a tener.
Como no estamos enviando los archivos .env, este archivo de aquí, el de la app, que tenía justamente este flag, este flag va a desaparecer y nos va a volver a dar problemas.
El problema nos lo vamos a encontrar en este comando.
En este comando build, este comando nos va a dar problemas.
Así que lo que puedo hacer es justamente añadir aquí el flag directamente.
Como esto es una variable en el entorno, le voy a decir, oye, mira, el comando este me lo ejecutas, pero con el flag este.
Y de esta forma, cuando se despliegue, no nos debería dar problemas.
Entonces lo voy a hacer justamente para evitarlo.
Porque como no enviamos el .env, porque fíjate que lo que se despliega con Heroku es lo que vamos a tener en el repositorio en master.
Como el archivo .env no va a estar ahí porque lo ignoramos, pues lo vamos a perder.
Otro tema que nos falta.
¿Qué nos falta?
Claro que la API también tiene su .env.
Y esto es una pregunta que también me habéis hecho un montón.
Oye, pero ¿qué pasa?
Claro, es que este archivo .env no lo puedo subir a Heroku porque no lo tengo en mi repositorio.
¿Y qué hago?
Porque no puedo hacer nada.
Vale, hay dos formas de arreglar esto.
Una podría ser Heroku config, dos puntos, set.
Leerías la variable de entorno.
En este caso creo que tenemos dos.
Una para la conexión de MongoDB y otra para la palabra secret.
Así que pondrías, bueno, creo que es una vez secret y aquí le pondrías dos puntos y pondrías el secret que quisieras para generar los passwords.
Y pues pones aquí lo que sea.
Esto podría ser una otra forma.
Una forma.
Voy a enseñarte otra que es la que voy a utilizar.
Aquí puedes ver la aplicación que tenemos.
Es First Shelf 74800.
Vale, pues vamos aquí, First Shelf.
Vamos aquí a Settings.
Y aquí en Settings veis que pone Config Bars.
Y tienes Reveal Config Bars.
Pues aquí lo que puedes hacer es Reveal Config Bars.
Y aquí puedes ir añadiendo justamente las keys.
Voy a ir aquí a mi Notes App.
Voy a ir por aquí y me lo voy a traer, ¿vale?
Me lo voy a traer un momento.
Y lo voy a añadir.
No es por nada.
No es que no me fíe de ustedes.
Porque me fío.
Pero es por si acaso.
Porque como alguien me la lié, a lo mejor estamos aquí hasta mañana arreglándolo.
Vale, entonces voy a poner aquí el MongoDB URI.
Le voy a copiar justamente el que tengo.
Pero no equivocarme porque si me equivoco no va a funcionar el deploy.
Vale, y ahora voy a poner el secret.
El secret es el middle secret.
Entonces, perfecto.
Ya los he puesto.
Le he dado a ocultar.
Y ya estarían ahí.
Ya los debería poder utilizar.
Ya no hace falta que enviemos el archivo de env.
Porque al final estos env los estamos poniendo ahí como key value.
Le estamos diciendo esta key tiene este valor.
Es importante que no pongáis el del puerto.
¿Por qué?
Porque Heroku ya automáticamente le asigna un puerto.
Entonces no lo tienes que utilizar.
Ok, ya tenemos las variables de entorno.
Ya tenemos esto de build.
A ver, aquí pueden pasar un montón de cosas.
Puede ser que todo funcione, puede ser que no.
Vamos a probar.
Primero voy a hacer un commit.
Add new config for Heroku.
Vamos a deployar.
Esto lo vamos a poner en nuestro repositorio de GIP.
Y ahora lo que tenemos que hacer es desplegar con Heroku.
Hacemos git push Heroku.
Y le decimos, vale, al remote de Heroku, al repositorio remoto de Heroku, le vas a enviar la rama main.
Vamos a hacer un git push Heroku.
A ver qué tal.
Ahora está haciendo el push y ahora empieza ya a hacer la instalación.
¿Ves?
Aquí justamente installing binaries.
Dice, engines npm ha detectado 7.9.0.
Entonces tenía, estaba resolviendo la versión 14, pero esto pues debe cambiar por otra, ¿no?
Porque, ¿ves?
Tenía la 6.14, que es la que tiene por defecto, y la está reemplazando por la 7.9.0, que es la que le he dicho yo.
Ahora debería hacer un montón de instalaciones de un montón de cosas.
Quiero que revisemos el repositorio para que veáis un poco cómo ha quedado, ¿vale?
El monorepo.
Fíjate, tenemos la API y la app en un mismo repositorio.
Y los dos están compartiendo un mismo package.json de raíz, donde tenemos el linter, que el linter no lo hemos probado, pero funciona correctamente.
Podríamos añadir aquí, vamos a añadirlo.
De hecho, nos van a salir errores del linter, pero ahora te explicaré por qué.
Si ponemos aquí en script, vamos a ejecutar uno que sea lint, y vamos a poner aquí que esto es slint.
¿Cómo es esto de slint?
Porque creo que slint, creo que hay que decirle .api.app.
Creo que hay que decirle las carpetas, si no, no funciona.
Vamos a ejecutarlo, a ver.
Slint, API y app.
Está tardando, o sea que me imagino que está funcionando.
Vale, hay un montón de errores.
Muchos de los errores que ocurren es porque nuestra aplicación anteriormente, nuestra aplicación esta, la que teníamos en Career Rackup, estaba utilizando otro linter distinto.
Estaba utilizando el linter de React Skip.
Y claro, eso no está bien, no está bien.
Así que esa es una de las razones por las que es buena idea que el linter esté en la raíz, para que siempre utilices las mismas reglas y tal,
y te evites problemas de, en uno utilizas puntos y comas, en otro no, pues bueno, si lo tienes en la raíz, lo compartes.
Luego, muchos de otros errores, debe ser porque no está ignorando la carpeta build.
Así que esto lo podemos hacer aquí fácilmente.
Creo que es ignore patterns, y aquí le podemos poner build.
O sea, hacemos mpn run link, ahora deberían salir 60 o 50, ¿vale?
Que si te fijas son todos de la aplicación de notas, porque tenía otro diferente.
Una cosa que podemos intentar es hacer un fix, a ver cuánto se arregla, debe arreglar bastantes.
Mira, solo nos queda un solo error, y es porque no estamos gestionando el error.
Pues podemos ir a app.js, a ver dónde nos dice el error, aquí.
¿Veis este error? No estamos gestando, y por eso se queja.
Ahora ya, podríamos hacer un mpn run link, y de esta forma, el linter, que es una de las dependencias más grandes,
pues la estamos compartiendo con todos los paquetes de nuestra aplicación.
Lo mejor de esto, es que ya nuestro, esto está preparado para escalar bastante bien.
Tenemos la API, tenemos la app, podríamos poner otra cosa que fuese el state.
Por ejemplo, podríamos tener todo nuestro estado de redax totalmente separado y tenerlo ahí.
Podría pasar, podría ser totalmente lícito.
O tener los componentes, ¿no? Components, y dentro tener storybook.
Pues bueno, podría ser un montón de soluciones.
Podemos ir escalando nuestro proyecto, y es tan fácil que solo está en un sitio, para que lo tengamos que mirar.
Un solo repositorio, te lo bajas, comparte dependencias, haces un mpn install más rápido,
un deploy mucho más sencillo, y una maravilla.
Esta es nuestra aplicación, que está desplegada en producción,
y tenemos la API y la app funcionando en el mismo sitio, funcionando sin ningún problema.
Aquí podemos ver que ha tirado de la API.
De hecho, si aquí vamos a network, aquí tenemos la API, vamos a abrirlo en otra app base.
Aquí lo tenemos en el mismo dominio, funcionando la API.
Y por otro lado, aquí tenemos nuestra app de React.
Esto gracias a que lo que ha hecho primero es ejecutar, cuando hemos hecho el despliegue con Heroku,
ha hecho primero build, nos ha conseguido los estáticos de la aplicación de React.
Esto no difiere absolutamente nada de lo que harías en una aplicación real en producción.
De hecho, en el Full Stack Bootcamp, en la última clase, veremos cómo hacer Continuous Integration y Continuous Deployment,
y haremos algo muy similar a lo que hemos hecho, en el sentido de que primero hacemos build, es normal,
y luego tenemos que hacer el start para empezar a levantar nuestro servidor.
Con esto ya lo tenemos en producción, con un monorepo multipaquete.
Espero que te haya gustado.
Espero que te haya gustado.
A ver qué me contáis.
Yo tengo una pregunta.
Tengo un repositorio en el que cada vez que realizo un push, me pide mis credenciales.
¿Cómo puedo concluir?