Dejo esto acá para mi yo del futuro😐
query GetPlantList{
plantCollection(limit:10, skip:20){
total
skip
limit
items{
slug
}
}
}
Introducción: rendering modes de Next.js
Sitios estáticos y Jamstack
Modos de rendering en Next.js
Arquitectura del proyecto
Arquitectura de la app y GraphQL
Configurando Contentful y tokens
Clonando el proyecto e importando contenidodesde CLI
Explorando la app de Next.js
GraphQL API y autogeneración de código
Static Generation
Página Home: lista
Moviendo al servidor: getStaticProps
Página de entrada: detalle
Moviendo al servidor: getStaticPaths
Trade-offs: consideraciones adicionales de SSG
Incremental Static Generation
Habilitando Incremental Static Generation
Estrategias de carga: fallback vs. bloqueante
El enfoque stale-while-revalidate
Trade-offs de ISG
Otras alternativas: comparación entre SSG y SSR
Siguientes pasos
Continúa con el Curso de Next.js: Deploy a Producción
Bonus
Explorando la flexibilidad de getStaticPaths con fileSystem
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Cuando construimos aplicaciones web, una estrategia eficiente de renderizado puede marcar la diferencia en la experiencia del usuario. En Next.js, getStaticProps
juega un papel crucial para optimizar nuestras páginas, especialmente cuando se trata del "Build Time". Este método es ideal para las páginas no dinámicas ya que proporciona a React información de manera anticipada sobre qué datos se requerirán.
¿Cómo funciona getStaticProps
?
Por ejemplo, si queremos alimentar nuestra página con información de una planta, getStaticProps
nos permite definir qué propiedades (props) necesita React para renderizar la página correctamente.
export async function getStaticProps(context) {
const data = await fetch('https://miapi.com/planta');
const planta = await data.json();
return {
props: {
planta,
},
};
}
Aquí, recuperamos los datos de una API y los pasamos como propiedades que usará la página.
Cuando te encuentras gestionando páginas dinámicas, como entradas de blogs con slugs dinámicos en sus URLs, getStaticPaths
es tu aliado. Este método complementa a getStaticProps
y le dice a Next.js qué rutas dinámicas necesitamos generar en el momento de la construcción.
¿Cómo definir los caminos con getStaticPaths
?
export async function getStaticPaths() {
const res = await fetch('https://miapi.com/plantas');
const plantas = await res.json();
const paths = plantas.map((planta) => ({
params: { slug: planta.slug },
}));
return { paths, fallback: false };
}
En el ejemplo, se traen las plantas desde una API, generando un array de rutas que Next.js usará para crear esas páginas en el build time.
El uso combinado de getStaticProps
y getStaticPaths
proporciona eficiencia, pero, como cualquier estrategia, tiene sus limitaciones. Por ejemplo, la necesidad de definir todas las rutas en build time puede presentar problemas si el número de páginas crece enormemente. Para abordar esta limitación:
La capacidad de generar páginas de manera estática es solo una de las muchas características avanzadas de Next.js. Para profundizar y dominar estas técnicas, considera explorar cursos que cubren desde fundamentos hasta aspectos técnicos avanzados. ¡Nunca dejes de aprender y experimentar con nuevas estrategias para mejorar la experiencia y el rendimiento de tus proyectos!
Aportes 5
Preguntas 3
Dejo esto acá para mi yo del futuro😐
query GetPlantList{
plantCollection(limit:10, skip:20){
total
skip
limit
items{
slug
}
}
}
<Layout>
<Grid container spacing={4} >
<Grid item xs={12} md={8} lg={9} component="article">
<figure>
<img width={952} src={plant.image.url} alt={plant.image.title} />
</figure>
<div className="px-12 pt-8">
<Typography variant="h2">{plant.plantName} </Typography>
</div>
<div className="p-10">
<RichText richText={plant.description} />
</div>
</Grid>
<Grid item xs={12} md={4} lg={3} component="aside">
<section>
<Typography variant="h5" component="h3" className="mb-4" >
Recent post
</Typography>
</section>
{otherEntries?.map((plantEntry) => (
<article className='mb-4' key={plantEntry.id}>
<PlantEntryInline {...plantEntry}/>
</article>
))}
<section className='mt-10'>
<Typography variant="h5" component="h3" className='mb-4'>
Categories
</Typography>
<ul className='list'>
{categories?.map((category) => (
<li key={category.id}>
<Link passHref href={`/category/${category.slug}`}>
<Typography variant="h6" component="a">
{category.title}
</Typography>
</Link>
</li>
))}
</ul>
</section>
</Grid>
</Grid>
<section className='my-4 border-t-2 border-b-2 border-gray-200 pt-12 pb-7'>
<AuthorCard {...plant.author} />
</section>
</Layout>
También estaba pensando en esa desventaja mencionada al final de la clase. Qué pasaría con blogs que superen los 500 blogposts? (por poner un número)
El resultado final del código:
import { useEffect, useState } from 'react';
import { useRouter } from 'next/router'
import {getPlantList, getPlant, QueryStatus, getCategoryList } from '@api'
import { Layout } from '@components/Layout';
import { Typography } from '@material-ui/core';
import { Grid } from '@ui/Grid'
import { PlantEntryInline } from '@components/PlantCollection';
import { RichText } from '@components/RichText'
import { AuthorCard } from '@components/AuthorCard'
import { GetStaticProps, InferGetStaticPropsType } from 'next';
import Link from 'next/link';
// Definición del tipo para el Path que se utiliza en getStaticPaths.
type PathType = {
params: {
slug: string
}
}
// Esta función determina todas las rutas que se pre-renderizarán en tiempo de construcción.
export const getStaticPaths = async () => {
// Aquí obtenemos la lista de plantas para luego generar las rutas.
const entries = await getPlantList({limit:10})
// Creamos la lista de rutas a partir de la lista de plantas.
const paths: PathType[]= entries.map(plant => ({
params: {
slug: plant.slug
}
}))
// Devolvemos la lista de rutas y establecemos el fallback en false, lo que significa que si se intenta acceder a una ruta que no está en la lista, se mostrará una página 404.
return {
paths,
fallback: false
}
}
// Definición de los props para este componente.
type PlantEntryProps = {
plant: Plant | null
otherEntries: Plant[] | null
categories: Category[] | null
}
// Esta función se encarga de obtener los datos necesarios para pre-renderizar la página.
export const getStaticProps: GetStaticProps<PlantEntryProps> = async ({ params }) => {
const slug = params?.slug;
// Comprueba si el slug es de tipo string, si no, devuelve notFound.
if (typeof slug !== 'string'){
return { notFound: true }
}
// Intenta obtener los datos de la planta, otras entradas y categorías. Si falla, devuelve notFound.
try{
const plant = await getPlant(slug)
const otherEntries = await getPlantList({ limit: 5})
const categories = await getCategoryList({ limit: 10})
return {
props: {
plant,
otherEntries,
categories
}
}
}catch(error) {
return {
notFound: true
}
}
}
// Definición del componente principal de la página de entrada de la planta.
export default function PlantEntryPage({
plant,
otherEntries,
categories,
}: InferGetStaticPropsType <typeof getStaticProps>) {
// Renderiza la página con la información de la planta, otras entradas y categorías.
return(
<Layout>
<Grid container spacing={4} >
<Grid item xs={12} md={8} lg={9} component="article">
<figure>
<img width={952} src={plant.image.url} alt={plant.image.title} />
</figure>
<div className="px-12 pt-8">
<Typography variant="h2">{plant.plantName} </Typography>
</div>
<div className="p-10">
<RichText richText={plant.description} />
</div>
</Grid>
{/*Esta sección se encarga de renderizar el aside del layout.*/}
<Grid item xs={12} md={4} lg={3} component="aside">
<section>
<Typography variant="h5" component="h3" className="mb-4" >
Recent post
</Typography>
</section>
{/*Aquí mapeamos y renderizamos las otras entradas de plantas obtenidas.*/}
{otherEntries?.map((plantEntry) => (
<article className='mb-4' key={plantEntry.id}>
<PlantEntryInline {...plantEntry}/>
</article>
))}
{/*Sección para renderizar las categorías.*/}
<section className='mt-10'>
<Typography variant="h5" component="h3" className='mb-4'>
Categories
</Typography>
<ul className='list'>
{/*Mapeamos y renderizamos las categorías obtenidas.*/}
{categories?.map((category) => (
<li key={category.id}>
{/*Aquí utilizamos el componente Link de Next.js para crear enlaces a las páginas de las categorías.*/}
<Link passHref href={`/category/${category.slug}`}>
<Typography variant="h6" component="a">
{category.title}
</Typography>
</Link>
</li>
))}
</ul>
</section>
</Grid>
</Grid>
{/*Sección para renderizar la tarjeta del autor de la planta.*/}
<section className='my-4 border-t-2 border-b-2 border-gray-200 pt-12 pb-7'>
<AuthorCard {...plant.author} />
</section>
</Layout>
)
}
Es la forma en que se genera paginas estaticas en build time.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?