Aprovechamiento de los componentes de React Server en RedwoodJS

El equipo de React lanzó React 18 en mayo de 2023, que incluía un mejor soporte para los Componentes de Servidor React (RSC). Menos de un año después, RedwoodJS anunció la compatibilidad con el renderizado del lado del servidor y los RSC. Esto supone un cambio respecto al enfoque tradicional de Redwood en GraphQL, pero mantiene la idea de que te ayudará a pasar de la idea a la startup lo más rápido posible.
En este artículo, veremos qué significa este cambio para el desarrollo con Redwood, crearemos una aplicación simple para explorar RSC en el marco y analizaremos algunas de las soluciones alternativas que deberá utilizar mientras Bighorn aún esté en desarrollo activo.
- Componentes del servidor Bighorn y React de RedwoodJS
- Introducción a los RSC en RedwoodJS
-
Advertencias actuales sobre el uso de RSC en RedwoodJS
- Aún no puedes usar el servidor de desarrollo
- Utilice un hash #al reemplazar la URL actual
- Editar manualmente el entries.tsarchivo de enrutamiento
- Agregar Metadatasolo a componentes del cliente
- Sin acceso a las variables principales del nodo
- Aún no hay acciones del servidor
- Aún no hay celdas de servidor en los diseños
- Representación de componentes del servidor en componentes del cliente
- RedwoodJS frente a otros frameworks compatibles con RSC
- Conclusión
- ¿Estás agregando nuevas bibliotecas de JavaScript para crear nuevas funciones o mejorar el rendimiento? ¿Qué pasa si hacen lo contrario?
Componentes del servidor Bighorn y React de RedwoodJS
RedwoodJS ya era fácil de usar. Ya lo había probado y estaba considerando usarlo para mis proyectos secundarios, pero en aquel momento estaba en fase alfa. Ahora que está listo para producción (aunque los RSC no lo están), lo estoy revisando de nuevo, y creo que los RSC lo mejorarán aún más.
A pesar de ser fácil de usar, cuando usé el framework por primera vez, no conocía GraphQL. No es que fuera difícil de entender, pero había algunos gastos generales que gestionar que sé que ya he olvidado por completo.
Plantilla y guía del documento de requisitos del productoSi necesitara retomar GraphQL, tendría que volver a caer en el mismo abismo. Con esta nueva versión, ya no tendrás que hacerlo. Aunque Redwood con RSC es una versión canaria y no está lista para producción (y Redwood seguirá siendo compatible con GraphQL), en el futuro será RSC por defecto.
Si bien lleva algo de tiempo comprender los RSC, al menos ya estás parte del camino cuando conoces React.
Introducción a los RSC en RedwoodJS
RedwoodJS facilita el desarrollo. Ya lo he probado antes. Pero esta vez tuve algunos problemas al compilar y servir la aplicación, así que la configuración no fue tan sencilla como la última vez. Por suerte, lo resolví, así que no tendrás que enfrentarte a los mismos problemas.
Configuración de su entorno de desarrollo
Con la versión actual de RedwoodJS que uso, es decir, [Node v20.10.0 o superior], debes usar Node v20.10.0 o superior. Supongo que cualquier versión futura lo requerirá, lo cual explicaré después de los pasos de instalación.8.0.0-canary.496
Una vez que tenga una versión compatible de Node, ejecute este comando:
npx - y create - redwood - app@canary - y redwood_rsc_app
No olvides este paso (que realicé inicialmente), o en los siguientes pasos verás una abreviatura de . Aquí está el siguiente comando:error Command "rw" not found.
rw
redwood
instalación de hilo
Si recibe un error al ejecutar el último comando, ejecute esto:
Paquete de núcleos Habilitar
Para utilizar React Server Components con RedwoodJS, debe instalar estas funciones experimentales:
Crear un menú desplegable en FigmaConfiguración experimental de hilo rw - transmisión - ssr - fConfiguración experimental de hilo rw - rsc
Luego ejecute los siguientes comandos para compilar e iniciar la aplicación:
construcción de hilo rwhilo rw servir
Este es el paso donde me encontré con este error:
".../client-build-manifest.json" necesita una aserción de importación de tipo "json"
Fue porque estaba usando Node v20.3.0. De hecho, localicé el problema y edité los archivos de mi node_modules
carpeta para solucionarlo, pero tras investigar y experimentar un poco, descubre que en Node v20.10.0, el siguiente tipo de aserción:
importar datos de './data.json' afirmar { tipo : 'json
Cambiado a esto:
Implementación de proyectos piloto: propósito, proceso y mejores prácticasimportar datos de './data.json' con { tipo : 'json
Aquí tienes más detalles sobre el problema que encontré. Actualizar a Node v20.10.0 y ejecutarlo yarn install
de nuevo solucionó mis problemas sin modificar ningún archivo. Esto es lo que deberías obtener al visitar http://localhost:8910/ :
Construyendo un juego de memoria para gatos con RedwoodJS y RSCs
Esta aplicación de ejemplo se centra en el uso de componentes de React Server en Redwood. Si quieres ver un ejemplo que muestra más funciones de RedwoodJS, consulta Cómo crear una aplicación full-stack en RedwoodJS.
Para simplificar el proceso y empezar a usar las tarjetas RSC más rápido, usaré un proyecto que acabo de crear tal cual y colocaré el juego de memoria en la página principal. Usaré la API gratuita de Cat como servicio (Cataas) para crear las tarjetas:
Puedes consultar el código fuente del proyecto en este repositorio de GitHub.
Celdas y servicios de servidor
En el desarrollo tradicional de Redwood, las celdas tenían una función QUERY que contenía la consulta GraphQL para obtener datos de la base de datos. Para crear una celda de servidor, se exporta una función. Los datos devueltos por esta función se pasarán al componente de éxito.data()
Aquí está mi servidor de celda para obtener imágenes de gatos aleatorias para usar en las tarjetas:
importar placa desde 'src/components/Board' importar { cats } desde 'src/services/cats' // La única diferencia entre el desarrollo tradicional y el RSC RedwoodJS // Reemplaza la función QUERY que contenía la consulta GraphQL export const data = async () = { return { cats : await cats () } } exportar const Cargando = () = div Cargando .../ div exportar const Vacío = () = div Vacío/div export const Error = ({ error }) = div Error: { error . mensaje }/ div exportar const Éxito = ({ gatos }) = { return Tablero gatos ={ gatos } / }
A decir verdad, no hay mucho que ver aquí. En Redwood, una celda gestiona la obtención de datos y simplifica su integración en la interfaz de usuario. Cada estado se gestiona mediante un componente diferente.
Aquí está el cats
servicio que llama a la API de Cataas:
const swap = (matriz, i, j) = { const temp = matriz[i] matriz[i] = matriz[j] matriz[j] = temp} const shuffle = (array) = { const length = array.length for(let i = length; i 0; i --) { const randomIndex = Math.floor(Math.random() * i) const currIndex = i - 1 swap(array, currIndex, randomIndex) } return array } exportar const gatos = async() = { const res = await fetch('https://cataas.com/api/cats?type=squarelimit=12') const datos = await res.json() const doble = datos.flatMap((i) = [i, i]) const barajado = barajar(doble) devolver barajado}
Esto solo hace llamar a la API, duplicar los resultados para tener dos de cada gato, mezclar el array y devolver los resultados a la celda. En RedwoodJS tradicional con GraphQL, los servicios se guardan en la api
carpeta del proyecto. Con RSC, esto no es posible. En cambio, se guarda en la carpeta.web/src/services/cats.ts
Hasta ahora hemos visto dos pequeñas diferencias en la estructuración de proyectos, pero en definitiva, es bastante fácil empezar. Si eres nuevo en React Server Components, como yo, repítete esto mientras escribes código interactivo:
- Los componentes del servidor nunca se vuelven a renderizar
- No utilice el estado en los componentes del servidor.
Trabajar con componentes de servidor requiere una visión diferente del proyecto. Si estás acostumbrado a escribir frontend con React, puedes que te lleve un tiempo hacerlo bien. Refactoricé mi componente dos veces antes de conseguirlo. Por suerte, hay muchas maneras de lograrlo.Board /
Sabía que necesitaba el estado para registrar las cartas encontradas, las que se pulsaban y los intentos. Lo tuve en cuenta, pero escribí la lógica del juego en el componente del tablero mientras aún era un componente del servidor, solo para solucionarlo. Me apareció este error:
Reaccionar. useState no es una función o su valor de retorno no es iterable
Pero esperaba algo, así que lo refactoricé.
Convirtí el componente en un componente de cliente añadiéndolo en la parte superior, pero dejé la propiedad en el componente. Tras este cambio, no hubo errores, pero tampoco se registraron eventos de clic. Así que lo refactoricé de nuevo.Board /
use client
onClick
Card /
Aquí está la refactorización final:
'usar cliente'importar { useEffect } desde 'react' importar tarjeta desde 'src/components/Card' const Tablero = ({ gatos }) = { const [ CartasElegidas , establecerCartasElegidas ] = React . useState ([]) const [ CartasEncontradas , establecerCartasEncontradas ] = React . useState ([]) const [ intentos , establecerIntentos ] = React. useState (0) const tiempo de espera = React. useRef ( null ) // Verificar la elección de cartas useEffect (() = { if ( choseCards . length === 2 ) { setTimeout ( checkCards , 1000 ) } } , [ choseCards ]) // Notificar al usuario sobre la victoria useEffect (() = { if ( foundCards . length === cats . length / 2 ) { alert (` Ganaste en $ { tries } intentos `) } }, [ foundCards , cats , tries ]) const checkCards = () = { const [ primero , segundo ] = elegidoCards if ( gatos [ primero ]. _id === gatos [ segundo ]. _id ) { setFoundCards (( prev ) = [... prev , gatos [ primero ]. _id ]) setChosenCards ([]) return } tiempo de espera . actual = setTimeout(() = { setChosenCards([])}, 1000)} const handleCardClick = (índice) = { if ( foundCards.include(cats[índice]._id)) return if ( chosenCards.length === 1 chosenCards[0]!== índice) { setChosenCards((prev) = [... prev, índice]) setTries((tries) = tries + 1)} else { clearTimeout(timeout.current) setChosenCards([índice])} } const isFlipped = (índice) = { return chosenCards. incluye ( índice ) } const isFound = ( _id ) = { return Boolean ( foundCards . incluye ( _id )) } devolver ( div estilo ={{ ancho : '100vw' , alto : '100vh' , pantalla : 'flex' , flexWrap : 'wrap' , espacio : '20px' , margen : '20px' , }} { gatos . mapa (( cat , id ) = ( // eslint-deshabilitar-siguiente-línea jsx-a11y/eventos-de-clic-tienen-eventos-clave, jsx-a11y/interacciones-de-elementos-sin-estáticos div key ={ cat._id } onClick ={() = handleCardClick ( id )} Imagen de la tarjeta ={ isFlipped ( id ) || se encuentra ( gato._id )? ` https://cataas.com/cat?_id=$ { cat._id } ` : ' https://d33wubrfki0l68.cloudfront.net/72b0d56596a981835c18946d6c4f8a968b08e694/82254/images/logo.svg ' } // div ))} / div ) } Exportar placa predeterminada
En la versión que finalmente funcionó correctamente, lo envolví en otro que manejaría los eventos de clic, y ahora solo tiene un accesorio:Card /
div /
image
const Tarjeta = ({ imagen }) = { return ( div estilo ={{ ancho : '240px' , alto : '240px' , radio del borde : '10px' , sombra del cuadro : '0 0 10px rgba(0, 0, 0, 0.1)' , pantalla : 'flex' , justificar contenido : 'centrar' , alinear elementos : 'centrar' , }} img src={image} alt="cat" style={{ objectFit: 'cover', ancho: '200px', alto: '200px' }} / /div )}exportar tarjeta predeterminada
Usar RSC te hace reflexionar más sobre cómo estructurar tus componentes. Debes decidir qué componentes serán esencialmente estáticos y con cuáles interactuará el usuario.
Pero se pueden anidar componentes de servidor dentro de componentes de cliente. En este proyecto, el único componente de cliente es Board /
porque usa el estado y sus Card /
componentes secundarios son componentes de servidor.
Consulte el código de este proyecto en este repositorio.
Advertencias actuales sobre el uso de RSC en RedwoodJS
Si está acostumbrado a desarrollar con RedwoodJS, existen algunas soluciones alternativas que deberá usar con los RSC. Es posible que algunas o todas estas no sean necesarias una vez que Bighorn se oficialice.
Aún no puedes usar el servidor de desarrollo
Por ahora, compila y sirve cada vez que hagas cambios. Así que:
- Hacer algunos cambios
- Golpea
Ctrl c
para detener el servidor. - Ejecútalo
yarn rw build yarn rw serve
nuevamente para ver los cambios.
Utilice un hash #al reemplazar la URL actual
Anteriormente en RedwoodJS, se podía modificar la URL actual sin recargar la página usando ` { replace: true }
with` navigate()
. Esto cambiaba la dirección en el historial sin interacción con el servidor.
Sin embargo, en la nueva versión de Canary y Cambium RSC, esto activa una llamada al servidor, redibujando la página completa. Esto podría provocar que se activen las transiciones y que la página parpadee con cada cambio.
Para evitar esto, utilice un símbolo de almohadilla #
en lugar de un signo de interrogación ?
:
// RedwoodJS clásico http://localhost:8910/products/shoes?color=redsize=10// RedwoodJS con RSC http://localhost:8910/products/shoes#color=redsize=10
Editar manualmente el entries.tsarchivo de enrutamiento
Actualmente, se creará un /web/src/entries.ts
en su proyecto:
importar { defineEntries } de '@redwoodjs/vite/entries' exportar predeterminado defineEntries( // obtenerEntrada async (id) = { cambiar (id) { caso 'Acerca de': devolver importación('./pages/AboutPage/AboutPage') caso 'Página de inicio': devolver importación('./pages/Página de inicio/Página de inicio') caso 'Entrada del servidor': devolver importación('./entry.server') predeterminado: devolver nulo } })
Cualquier ruta que defina en el enrutador ( web/src/Routes.tsx
) necesitará su propia entrada allí:
importar { Router, Route, Set } desde '@redwoodjs/router' importar NavigationLayout desde 'src/layouts/NavigationLayout' importar NotFoundPage desde 'src/pages/NotFoundPage' const Routes = () = { return ( Router Set wrap={NavigationLayout} Ruta path="/" page={HomePage} name="home" / Ruta path="/about" page={AboutPage} name="about" / / Establecer ruta notfound page={NotFoundPage} / / Router )} Exportar rutas predeterminadas
En el futuro, /web/src/entries.ts
desaparecerá y el marco se encargará de esta parte por usted.
Agregar Metadatasolo a componentes del cliente
El componente de Redwood Metadata
se basa en React Context, que usa el estado, y este se limita a los componentes del lado del cliente. Por lo tanto, al usar este componente para agregar metaetiquetas en la sección de encabezado de tus páginas, asegúrate de usarlo dentro de un componente marcado con use client
.
Sin acceso a las variables principales del nodo
Aunque Redwood renderiza componentes y servicios en el servidor, no podrá usar variables como __filename
y __dirname
. Redwood aún usa el formato CJS para los módulos, pero se está actualizando a ESM.
Por ahora, use path.resolve()
para construir la ruta de relleno completa en relación con su ubicación de ejecución, no con su fuente original.
Aún no hay acciones del servidor
El canario de Redwood Bighorn ofrece un vistazo a sus capacidades de obtención de datos, pero actualmente es de solo lectura. No se preocupe si la modificación de datos (mutaciones) aún no está disponible: las acciones del servidor, que desbloquean esta funcionalidad, están en desarrollo.
Aún no hay celdas de servidor en los diseños
RedwoodJS ofrece Celdas de Servidor para crear elementos de interfaz de usuario dinámicos. Sin embargo, anidarlos directamente en los diseños aún no es totalmente compatible, por lo que podrías encontrarte con errores si lo intentas. El equipo de Redwood está trabajando en una solución.
Representación de componentes del servidor en componentes del cliente
En Redwood, puedes marcar componentes para renderizarlos en el lado del cliente con use client
, pero también puedes anidar componentes de servidor dentro de componentes de cliente… si lo haces correctamente. Si lo haces mal, los componentes de servidor también se renderizarán en el navegador, lo que invalida el propósito de usar RSC.
Para hacerlo correctamente, aísle la lógica del lado del cliente (como la gestión de temas) en un componente cliente independiente. Este componente puede actuar como componente principal de los componentes del servidor, lo que permite importarlos children
y renderizarlos en el servidor según lo previsto.
RedwoodJS frente a otros frameworks compatibles con RSC
RedwoodJS no es el único framework que utiliza RSC. Ni siquiera es el primero. Aquí tienes otros frameworks compatibles con React Server Components:
- Siguiente.js:Este es probablemente el framework más conocido que utiliza RSC, ya que su atractivo reside en sus capacidades de renderizado del lado del servidor. Además, es el único mencionado en la documentación de React. Next.js también ofrece diversas estrategias de renderizado del servidor, incluyendo el renderizado estático (SSG), incremental (ISR) y dinámico (SSR).
- De:Waku es un framework React minimalista diseñado para proyectos pequeños y medianos. Fue desarrollado desde cero para usar RSC. Sin embargo, Waku aún se encuentra en desarrollo activo, por lo que es posible que falten algunas funciones. Aún no se recomienda para aplicaciones de producción, pero están trabajando para obtener una versión estable.
- Gatsby:Gatsby es conocido tradicionalmente por sus capacidades de generación de sitios estáticos e integración con React, pero también puedes usar SSR. En este caso, Gatsby usa componentes de servidor React cuando necesitas generar HTML dinámicamente.
En resumen, así es como RedwoodJS se compara con Next.js, Waku y Gatsby:
RedwoodJS | Next.js | Tuyo | Gatsby | |
---|---|---|---|---|
Recomendaciones del proyecto | Cualquier tamaño de aplicación, desde proyectos individuales hasta empresas. | Pequeñas y medianas empresas | Pequeñas y medianas empresas. No aptas para empresas. | Ideal para sitios web estáticos o proyectos que priorizan el SEO y el rendimiento. |
¿Listo para la producción? | El desarrollo tradicional es, pero las RSC aún no lo son. | Sí | Aún no | Sí |
Comunidad y ecosistema | Comunidad en crecimiento con desarrollo activo. | La comunidad más grande de la lista con muchos recursos. | Un marco relativamente nuevo con una comunidad pequeña pero en crecimiento. | Gran comunidad y extenso ecosistema enfocado al desarrollo web estático. |
Conclusión
El equipo de RedwoodJS tiene trabajo por delante antes de que los RSC estén listos para las aplicaciones de producción, pero avanzan con rapidez. Aún necesitan:
- Haga que SSR funcione con RSC para que la carga inicial de la página contenga HTML pre-renderizado
- Complete las acciones del servidor para poder guardar datos en su base de datos
- Modificar la autorización para trabajar con RSC
- Actualice los generadores para crear plantillas RSC o GraphQL dinámicamente
Pero una vez hecho esto, RedwoodJS podría ser un elemento innovador a la hora de crear aplicaciones React que no solo se carguen rápidamente, sino que también sean rápidas y fáciles de desarrollar.
¿Estás agregando nuevas bibliotecas de JavaScript para crear nuevas funciones o mejorar el rendimiento? ¿Qué pasa si hacen lo contrario?
Sin duda, los frontends son cada vez más complejos. A medida que añadas nuevas bibliotecas de JavaScript y otras dependencias a tu aplicación, necesitarás mayor visibilidad para garantizar que tus usuarios no se encuentren con problemas desconocidos.
Construya con confianza: comience a monitorear de forma gratuita.
Si quieres conocer otros artículos parecidos a Aprovechamiento de los componentes de React Server en RedwoodJS puedes visitar la categoría Guias.
Entradas Relacionadas