¿Recuperación de API interna con getServerSideProps? (Siguiente.js)

Resuelto m4tt asked hace 3 años • 3 respuestas

Soy nuevo en Next.js y estoy tratando de comprender la estructura sugerida y manejar datos entre páginas o componentes.

Por ejemplo, dentro de mi página home.js, obtengo una API interna llamada /api/user.jsque devuelve algunos datos de usuario de MongoDB. Estoy haciendo esto llamando fetch()a la ruta API desde dentro getServerSideProps(), que pasa varios accesorios a la página después de algunos cálculos.

Según tengo entendido, esto es bueno para SEO, ya que los accesorios se obtienen/modifican en el lado del servidor y la página los prepara para renderizarse. Pero luego leí en la documentación de Next.js que no debes usar fetch()todas las rutas API en getServerSideProps(). Entonces, ¿qué se supone que debo hacer para cumplir con las buenas prácticas y el buen SEO?

La razón por la que no estoy haciendo los cálculos necesarios home.jsen la ruta API en sí es que necesito datos más genéricos de esta ruta API, ya que también los usaré en otras páginas.

También tengo que considerar el almacenamiento en caché, que en el lado del cliente es muy sencillo al usar SWR para obtener una API interna, pero en el lado del servidor todavía no estoy seguro de cómo lograrlo.

home.js:

export default function Page({ prop1, prop2, prop3 }) {
        // render etc.
}

export async function getServerSideProps(context) {
  const session = await getSession(context)
  let data = null
  var aArray = [], bArray = [], cArray = []
  const { db } = await connectToDatabase()

  function shuffle(array) {
    var currentIndex = array.length, temporaryValue, randomIndex;
    while (0 !== currentIndex) {
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex -= 1;
      temporaryValue = array[currentIndex];
      array[currentIndex] = array[randomIndex];
      array[randomIndex] = temporaryValue;
    }
    return array;
  }

  if (session) {
    const hostname = process.env.NEXT_PUBLIC_SITE_URL
    const options = { headers: { cookie: context.req.headers.cookie } }
    const res = await fetch(`${hostname}/api/user`, options)
    const json = await res.json()
    if (json.data) { data = json.data }

    // do some math with data ...
    // connect to MongoDB and do some comparisons, etc.
m4tt avatar Jan 17 '21 01:01 m4tt
Aceptado

Pero luego leí en la documentación de Next.js que no debes usar fetch()todas las rutas API en getServerSideProps().

Desea utilizar la lógica que está en su ruta API directamente en getServerSideProps, en lugar de llamar a su API interna. Esto se debe a que getServerSidePropsse ejecuta en el servidor al igual que las rutas API (realizar una solicitud desde el servidor al servidor mismo no tendría sentido). Puede leer desde el sistema de archivos o acceder a una base de datos directamente desde getServerSideProps. Tenga en cuenta que esto solo se aplica a llamadas a rutas API internas; está perfectamente bien llamar a API externas desde getServerSideProps.

De getServerSidePropsla documentación de Next.js:

Puede resultar tentador buscar una ruta API cuando desee obtener datos del servidor y luego llamar a esa ruta API desde getServerSideProps. Este es un enfoque innecesario e ineficiente, ya que provocará que se realice una solicitud adicional debido a que ambas getServerSidePropsrutas API se ejecutan en el servidor.

(...) En su lugar, importe directamente la lógica utilizada dentro de su ruta API a getServerSideProps. Esto podría significar llamar a un CMS, una base de datos u otra API directamente desde dentro getServerSideProps.

(Tenga en cuenta que lo mismo se aplica cuando se utilizan getStaticProps/ getStaticPathsmétodos )


A continuación se muestra un pequeño ejemplo de refactorización que le permite reutilizar la lógica de una ruta API en getServerSideProps.

Supongamos que tiene esta ruta API simple.

// pages/api/user
export default async function handler(req, res) {
    // Using a fetch here but could be any async operation to an external source
    const response = await fetch(/* external API endpoint */)
    const jsonData = await response.json()
    res.status(200).json(jsonData)
}

Puede extraer la lógica de recuperación a una función separada (aún puede conservarla api/usersi lo desea), que aún se puede utilizar en la ruta API.

// pages/api/user
export async function getData() {
    const response = await fetch(/* external API endpoint */)
    const jsonData = await response.json()
    return jsonData
}

export default async function handler(req, res) {
    const jsonData = await getData()
    res.status(200).json(jsonData)
}

Pero también le permite reutilizar la getDatafunción en getServerSideProps.

// pages/home
import { getData } from './api/user'

//...

export async function getServerSideProps(context) {
    const jsonData = await getData()
    //...
}
juliomalves avatar Jan 17 '2021 13:01 juliomalves