{"_id":"07-router-yeltsin","_rev":"2-c607ec6adbc3243c6f4bd56a1f302d9c","name":"07-router-yeltsin","dist-tags":{"latest":"0.0.2"},"versions":{"0.0.0":{"name":"07-router-yeltsin","version":"0.0.0","type":"module","main":"lib/index.js","module":"lib/index.js","exports":{".":{"import":"./lib/index.js","require":"./lib/index.js"},"./package.json":"./package.json"},"scripts":{"dev":"vite","build":"vite build","prepare":"swc ./src/*.jsx -d lib && mv ./lib/src/*.js ./lib && rm -R ./lib/src && rm lib/App.js lib/main.js lib/Router.test.js && cp src/*.js lib","lint":"eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0","preview":"vite preview","test":"vitest","test:ui":"vitest --ui"},"dependencies":{"path-to-regexp":"6.2.1"},"peerDependencies":{"react":"18.2.0","react-dom":"18.2.0"},"devDependencies":{"@testing-library/react":"14.2.2","@types/react":"18.2.64","@types/react-dom":"18.2.21","@vitejs/plugin-react-swc":"3.5.0","@vitest/ui":"1.4.0","eslint":"8.57.0","eslint-plugin-react":"7.34.0","eslint-plugin-react-hooks":"4.6.0","eslint-plugin-react-refresh":"0.4.5","happy-dom":"14.0.0","vite":"5.1.6","vitest":"1.4.0"},"_id":"07-router-yeltsin@0.0.0","gitHead":"f94eb1b15a69a31aa8bcb02f8a9ee3ea2333a775","description":"✅ Instalar el linter","_nodeVersion":"20.10.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-wt8XIRWe1SAmh/9+XICCl9K636xCWk339e1QpHprpumucbwe2W16uBkNi42AzgvO8zWCJ4ebZE0az0nmh9Z/2w==","shasum":"eb44f27e8eb32ead31aa7752ce037bf2db5726ce","tarball":"https://registry.npmjs.org/07-router-yeltsin/-/07-router-yeltsin-0.0.0.tgz","fileCount":12,"unpackedSize":15372,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEeUITMgVepM5CbYUUf/4BiPxw6o1IKvopi0eWOiysbqAiBf43bXjHrE/m/s76d6wC/v1LBeaEozX0PpE3+zVwM7ag=="}]},"_npmUser":{"name":"yeltinbaltoleo","email":"gbl_leo_30@hotmail.com"},"directories":{},"maintainers":[{"name":"yeltinbaltoleo","email":"gbl_leo_30@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/07-router-yeltsin_0.0.0_1710923366207_0.8858478233933631"},"_hasShrinkwrap":false},"0.0.1":{"name":"07-router-yeltsin","version":"0.0.1","type":"module","main":"lib/index.js","module":"lib/index.js","exports":{".":{"import":"./lib/index.js","require":"./lib/index.js"},"./package.json":"./package.json"},"scripts":{"dev":"vite","build":"vite build","prepare":"swc ./src/*.jsx -d lib && mv ./lib/src/*.js ./lib && rm -R ./lib/src && rm lib/App.js lib/main.js lib/Router.test.js && cp src/*.js lib","lint":"eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0","preview":"vite preview","test":"vitest","test:ui":"vitest --ui"},"dependencies":{"path-to-regexp":"6.2.1"},"peerDependencies":{"react":"18.2.0","react-dom":"18.2.0"},"devDependencies":{"@testing-library/react":"14.2.2","@types/react":"18.2.64","@types/react-dom":"18.2.21","@vitejs/plugin-react-swc":"3.5.0","@vitest/ui":"1.4.0","eslint":"8.57.0","eslint-plugin-react":"7.34.0","eslint-plugin-react-hooks":"4.6.0","eslint-plugin-react-refresh":"0.4.5","happy-dom":"14.0.0","vite":"5.1.6","vitest":"1.4.0"},"_id":"07-router-yeltsin@0.0.1","gitHead":"f94eb1b15a69a31aa8bcb02f8a9ee3ea2333a775","description":"✅ Instalar el linter","_nodeVersion":"20.10.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-XS8B4EasjCqPRctT2u7u/ezcAtyxcdFPtsx3cNgZycbUAWa2J7gz+pHGni1SlNAtzVlX2kZegqj9vesSzrU96w==","shasum":"b3feff683a5593fbc578603d8a95ac5faddfa27c","tarball":"https://registry.npmjs.org/07-router-yeltsin/-/07-router-yeltsin-0.0.1.tgz","fileCount":12,"unpackedSize":15360,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFJ1PWIuQiTer4FRCZrKTw881V8Ho3mel7gwDW8XccomAiAHrbLVsXB9u+k3ZxfjruPYvb8lQeECz0XPk3nOPVQDtQ=="}]},"_npmUser":{"name":"yeltinbaltoleo","email":"gbl_leo_30@hotmail.com"},"directories":{},"maintainers":[{"name":"yeltinbaltoleo","email":"gbl_leo_30@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/07-router-yeltsin_0.0.1_1710924700334_0.06014413644175742"},"_hasShrinkwrap":false},"0.0.2":{"name":"07-router-yeltsin","version":"0.0.2","type":"module","main":"lib/index.js","module":"lib/index.js","exports":{".":{"import":"./lib/index.js","require":"./lib/index.js"},"./package.json":"./package.json"},"scripts":{"dev":"vite","build":"vite build","prepare":"swc ./src/*.jsx -d lib && mv ./lib/src/*.js ./lib && rm -R ./lib/src && rm lib/App.js lib/main.js lib/Router.test.js && cp src/*.js lib","lint":"eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0","preview":"vite preview","test":"vitest","test:ui":"vitest --ui"},"dependencies":{"path-to-regexp":"6.2.1"},"peerDependencies":{"react":"18.2.0","react-dom":"18.2.0"},"devDependencies":{"@testing-library/react":"14.2.2","@types/react":"18.2.64","@types/react-dom":"18.2.21","@vitejs/plugin-react-swc":"3.5.0","@vitest/ui":"1.4.0","eslint":"8.57.0","eslint-plugin-react":"7.34.0","eslint-plugin-react-hooks":"4.6.0","eslint-plugin-react-refresh":"0.4.5","happy-dom":"14.0.0","vite":"5.1.6","vitest":"1.4.0"},"_id":"07-router-yeltsin@0.0.2","gitHead":"f94eb1b15a69a31aa8bcb02f8a9ee3ea2333a775","description":"✅ Instalar el linter","_nodeVersion":"20.10.0","_npmVersion":"10.2.3","dist":{"integrity":"sha512-r+kHx4XTxovAc7qF1yV7RDWChlgaRHu8HONdwejECGxpta29a2XfEhzeNs5umHnTxkBU5ttWwI9CWA2FE1kybw==","shasum":"6ea152b733b40d9b2133187c20fc78ea369cf45a","tarball":"https://registry.npmjs.org/07-router-yeltsin/-/07-router-yeltsin-0.0.2.tgz","fileCount":8,"unpackedSize":12502,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG7i5IFvKFxlA1n5C/xQxY4882b1hhYJlzQbO3wresg5AiBKTOr4kO0E2Li0erVKEIUNwtjRYY/Y7lCl2Fblk2SNsQ=="}]},"_npmUser":{"name":"yeltinbaltoleo","email":"gbl_leo_30@hotmail.com"},"directories":{},"maintainers":[{"name":"yeltinbaltoleo","email":"gbl_leo_30@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/07-router-yeltsin_0.0.2_1710925028668_0.20186940584247104"},"_hasShrinkwrap":false}},"time":{"created":"2024-03-20T08:29:26.207Z","0.0.0":"2024-03-20T08:29:26.361Z","modified":"2024-03-20T08:57:09.273Z","0.0.1":"2024-03-20T08:51:40.515Z","0.0.2":"2024-03-20T08:57:08.826Z"},"maintainers":[{"name":"yeltinbaltoleo","email":"gbl_leo_30@hotmail.com"}],"description":"✅ Instalar el linter","readme":"# Crear un React Router desde Cero\n\n✅ Instalar el linter\n\n✅ Crear una forma de hacer MPAs (Multiple Page Application)\n\n✅ Crea una forma de hacer SPAs (Single Page Applications)\n\n✅ Poder navegar entre páginas con el botón de atrás\n\n✅ Crear componente Link para hacerlo declarativo\n\n✅ Crear componente Router para hacerlo más declarativo\n\n✅ Soportar ruta por defecto (404)\n\n✅ Soportar rutas con parámetros\n\n✅ Componente para hacerlo declarativo\n\n✅ Lazy Loading de las rutas\n\n✅ Hacer un i18n con las rutas\n\n✅ Testing\n\n✅ Publicar el paquete en NPM\n\n## Proceso\n\n- Crear una forma de hacer MPAs (Multiple Page Application)\n  - Se hizo con UseState y con condicionales para mostrar la página.\n- Crea una forma de hacer SPAs (Single Page Applications)\n  - Se usó el UseEffect para que se ejecute única vez cuando cargue la primera vez de la pagina.\n  - Actualizamos el estado del UseState cuando se cambie la URL.\n  _ Nos suscribimos al evento creado para que haga la actualización del estado y luego removemos el evento.\n  - En los botones se usa la función para navegar, donde se agregó la forma de no recargar toda la página al cambiar la URL.\n- Navegar entre páginas con el botón de atrás del navegador\n  - En el UseEffect, se agregó otro EventListener con el `popstate` para poder retroceder porque en el anterior solo funcionaba la pagina hacia adelante con el `pushestate`\n- Componente Link para hacerlo declarativo\n  - Se creó el componente que recibe todas las propiedades del `<a/>` mediante los props.\n  - Este componente tiene la lógica para hacer click y presionar a la vez los botones del teclado.\n  - Usa el `navigate` para evitar recargar la página cuando cambia la URL.\n  - Devuelve un `<a/>` con todas sus propiedad que se le pasaron en las props.\n  - En el Home.jsx y About.jsx, se cambio el uso del navigate para que ahora use el componente del Link pasándole el path de la URL y el children.\n- Componente Router para hacerlo más declarativo\n  - Extraer las rutas que se tiene en un array de objetos, asi se puede agregar mas rutas si es necesario fácilmente.\n  - Router.jsx: se crea una función que recibirá como parámetro el array de las rutas y por defecto tendrá un componente que indicará la ruta no encontrada.\n    - Se extrae toda la lógica del router realizado en el App.jsx y lo agregamos en esta función.\n    - Al fina de la lógica extraída, iteramos el array y buscamos el path para comparar si es el mismo del estado actual, si es el mismo obtenemos el componente, de lo contrario, mostrará el componente por defecto.\n- Soportar ruta por defecto (404)\n  - Se crea un nuevo componente que se le pasará en el parámetro por defecto de la función del Router.jsx\n- Soportar rutas con parámetros\n  - Instalamos la dependencia de Regexp `npm install path-to-regexp -E`\n  - Modificamos la lógica de la función del Router para utilizar el 'match' del `path-to-regexp`.\n  - Al momento de iterar el array con las rutas, indicamos que evalúe si existe rutas dinámicas, de existir lo agregamos en una variable que se le pasará a componente como parámetro.\n  - En la función de este componente se debe de agregar como parámetro el valor que recibirá y asi poder utilizarlo dentro de ella.\n  - En el App.jsx agregamos otra ruta indicando el ':query' que será la ruta dinámica (parámetro).\n- Componente para hacerlo declarativo\n  - Se crea un componente Route que servirá como 'puente' para pasar los 'path' y 'Component' al Router.jsx donde está la lógica de los routers.\n  - Se modifica el App.jsx para que utilice el nuevo componente Route pasándole los valores correspondientes a los 'path' y 'Component'.\n  - En la función del Router agregamos como prop el 'children' que es quien recibirá los valores del 'path' y 'Component'  como array, si no se pasa como array se tiene que convertirlo a uno.\n  - Utilizamos el 'Children.map' de React para poder iterar el prop children y obtenemos su 'props' y 'type' del mismo.\n    - El prop contiene los valores 'path' y 'Component'\n    - El type indica si es el componente Route.\n  - Verificamos si se esta utilizando el componente Route para devolver el props.\n  - En una constante guardamos la concatenación de los valores del prop con el routers que recibe la función como parámetro y lo iteramos.\n    - Reemplazamos la iteración del routers por esta nueva constante.\n- Lazy Loading de las rutas\n  - Usamos el 'Lazy' de React:\n    - permite importar de forma dinámica los componentes.\n    - No renderiza los componentes hasta que los necesitemos.\n  - Se le debe de indicar a React que tendrá una parte de la UI que no estará disponible desde el principio y por ello se envuelve una parte de la aplicación con el componente '<Suspense/>' de React, que indica que está en estado suspendido.\n  - Usando un 'fallback' dentro del Suspense, se puede agregar un loader o lo que deseamos antes de mostrar el componente que se requiere.\n- Hacer un i18n con las rutas\n  - Creamos una constante de array con los datos en español e ingles para poder diferenciar en que idioma queremos los textos.\n  - En este caso, en la propia ruta se agregó como path el valor del idioma.\n- Testing\n  - Instalamos dependencias\n    - Vitest: para haces los test.\n    - Vitest/ui: para ver los test en la web.\n    - Happy-Dom: para simular un árbol de elementos, como un navegador sin tener un navegador.\n    - @testing-library/react: renderiza y se pregunta si existe el componente, elemento, acciones, etc.\n  - En la configuración de vite.config, indicamos que el entorno donde se ejecutarán los test es en `happy-dom`.\n  - Creamos el archivo 'Router.test.jsx' para hacer los test a los routers.\n    - Limpiar la pantalla (html) y mockups al ejecutar cada test.\n    - Test del Router sin path.\n    - Test del Router sin path pero con DefaultComponent para buscar el texto dentro del html.\n    - Test del Router pasando los routers (path y component) y buscar el texto dentro del html.\n    - Test haciendo la navegación click en el Link y buscar el texto en el html del nuevo renderizado.\n- Publicar el paquete en NPM\n  - Instalar la dependencia SWC porque permite compilar los ficheros para poder utilizarlo sin un compilador.\n  - Creamos un archivo `.swcrc` y copiamos el contenido desde la web de `https://swc.rs/docs/configuration/swcrc` para configurar la compilación\n    - Modificamos algunos valores\n      - Minify: true (para minificar el código)\n      - Target: \"es2020\"\n      - Loose: true (hará el código mas eficiente pero no cumple al 100% la especificación)\n      - Jsx: true\n      - Transform: {\n        \"react\": {\n          \"runtime\": \"automatic\"\n        }\n      } (hace una transformación mas optima utilizando el `jsx` en lugar del React.createElement)\n  - Utilizamos el siguiente comando en la terminal para compilar los archivo metiéndolos en una carpeta lib.\n    - `npx swc ./src/*.jsx -d lib`\n    - Los archivos creados deben estar en la carpeta lib, si creara lib/src y luego los archivos, utilizar este comando: `npx swc ./src/*.jsx -d lib && mv ./lib/src/*.js ./lib && rm -R ./lib/src`.\n    - El comando anterior compila los archivos, luego mueve los archivos del src al lib y por ultimo elimina la carpeta src.\n  - En el package.json también se harán cambios para la configuración\n    - Dentro del script agregamos un 'prepare'\n      - Prepare: \"swc ./src/*.jsx -d lib && rm lib/App.js lib/main.js lib/Router.test.js && cp src/*.js lib\" (script especial del package.json que se va a ejecutar justo antes de que se haga el publish)\n      - Los archivos creados deben estar en la carpeta lib, si creara lib/src y luego los archivos, reemplazar el `prepare` por esto: `\"swc ./src/*.jsx -d lib && mv ./lib/src/*.js ./lib && rm -R ./lib/src && rm lib/App.js lib/main.js lib/Router.test.js && cp src/*.js lib\"`.\n      - El comando anterior compila los archivos, mueve los archivos del src al lib y elimina la carpeta src, luego elimina algunos archivos js dentro del lib y por ultimo copia los js del src para pegarlos en el lib.\n    - Eliminamos el private\n    - Modificamos la version : \"0.0.1\"\n    - Main: \"lib/index.js\"\n    - Module: \"lib/index.js\"\n    - Export: {\n        \".\": {\n          \"import\": \"./lib/index.js\",\n          \"require\": \"./lib/index.js\"\n        },\n        \"./package.json\": \"./package.json\"\n      }\n    - PeerDependencies: agregamos la referencias a las dependencias de React y React-Dom, esto significa que no lo instalaremos nosotros sino que dependerá del proyecto que lo va a utilizar, debe de tener estas dependencias instaladas.\n  - Creamos un archivo `index.jsx` para exportar los archivos necesarios para la publicación, se debe de exportarlo sin su extensión '.jsx'.\n  - Crear un archivo `.npmignore` para ignorar la carpeta src.\n  - En la terminal\n    - Ingresamos: `npm login`, luego nos pide las credencias para acceder a nuestra cuenta de npm.\n    - Ejecutamos: `npm publish` y por cada cambio se debe de actualizar la versión del package.json y volver a publicar.\n","readmeFilename":"README.md"}