Contenido del curso
Integración de la API de Contentful con Next.js para Imágenes
Comando: git checkout -b dev 3-image-loader
Angelo Zambrano
EstudianteCristian Alejandro
EstudianteLuis Berenguer
EstudianteJoseph Manuel Salen Pantoja
EstudianteCesar Gonzalez Groh
EstudiantePablo Orozco Monte
Company_adminAndres Prieto
EstudianteUlqernesh Karvenae
EstudianteUlqernesh Karvenae
EstudianteJuan Pablo Arango
EstudianteJonathan 🦑 Alvarez
ProfesorCristian Mauricio Cavanzo Arias
EstudianteCristian Iñiguez
EstudianteTener en cuenta que la API de contentful sólo soporta tamaños menores a 4000. Si el height o el width superan ese valor salta un error y no se renderiza la imágen.
No tengo ni puta idea de como integrar el API de contentfull a NextJs
A leer un poco de documentación compañero💪
Saludos amigo, antes de este curso se pasa por el Curso de Next.js: Sitios Estáticos y Jamstack, ahí se explica lo que necesitas para integrar el API de Contentful :D adicionalmente la documentación de Contentful es bastante amigable
No entendí por qué hay que volver a calcular el height dentro del loader
En el loader llega el width de las versiones más pequeñas de la misma imagen, ej: 750, 400, 300, 150. Entonces se debe calcular el height de cada una.
Creo que es bueno mencionar que desde la versión 13 Nextjs eliminó la propiedad "layout"
Ref:
Mi solución
type AspectRatio = '1:1' | '4:3' | '16:9' export type ContentfulFit = | 'pad' | 'fill' | 'scale' | 'crop' | 'thumb' export type ContentfulFocus = | 'center' | 'face' | 'top' | 'bottom' | 'left' | 'right' export type ImageProps = { layout: 'responsive' | 'intrinsic' src: string width: number height?: never aspectRatio: AspectRatio fit?: ContentfulFit f?: ContentfulFocus quality?: number } function Image({ layout, src, width, aspectRatio, fit = "fill", f , quality}: ImageProps) { const height = calcAspectRatioHeight(aspectRatio, width) const loader = ({ src, width, quality: loaderQuality }: ImageLoaderProps) => { const h = calcAspectRatioHeight(aspectRatio, width) const finalQuality = quality || loaderQuality return src.concat(`?w=${width}&h=${h}&fit=${fit}${f ? `&f=${f}` : ''}${finalQuality ? `&q=${finalQuality}` : ''}`) } return <NextImage layout={layout} src={src} width={width} height={height} loader={loader} /> } const calcAspectRatioHeight = (aspectRatio: AspectRatio, width: number) => { const aspectRatioParts = aspectRatio.split(':') const [w, h] = aspectRatioParts const height = (parseInt(h) * width) / parseInt(w) return height }
Otra forma de calcular el AspectRatioHeight mas escalable es
const calcAspectRatioHeight = (aspectRatio: AspectRatio, width: number) => {
const aspectRatioParts = aspectRatio.split(':')
const [ w , h ] = aspectRatioParts
const height = (parseInt(h) * width) / parseInt(w)
return height
}
La imagen de next puede hacer el objectFit, por que es mejor hacerlo con el API ?
Gran observación Juan Pablo!
Solo mostraba varias opciones por própositos académicos.
En general, si con next/image funciona tu Layout, así está perfecto 👌
En calcAspectRatio estamos diciendo a aspectRatio que puede ser una de las siguientes opciones: '1:1' | '4:3' | '16:9' y a width que sea number, esto esta bien sin embargo si aspectRatio cambia de ImageProps tendriamos que tambien cambiar el de la funcion una forma de que siempre se mantenga actualizado los tipos
type ImageProps = { layout: 'responsive' | 'intrinsic' src: string width: number height?: never aspectRatio: '1:1' | '4:3' | '16:9' fit?: 'pad' | 'fill' | 'cropt' } const calcAspectRatio = ( aspectRatio: ImageProps['aspectRatio'], width: ImageProps['width'] ) => {}
Este es mi componente Image con algunas mejoras en el tipado
// components/Image.tsx import { FC } from 'react' import NextImage, { ImageLoader } from 'next/image' type AspectRatio = '1:1' | '4:3' | '16:9' const aspectRatioToRatio: { [key in AspectRatio]: number } = { '1:1': 1, '4:3': 3 / 4, '16:9': 9 / 16, } function calcAspectRatio(aspectRatio: AspectRatio, width: number): number { const ratio = aspectRatioToRatio[aspectRatio] return Math.floor(width * ratio) } type ImageProps = { layout: 'fill' | 'fixed' | 'intrinsic' | 'responsive' | undefined src: string width: number height?: never aspectRatio: AspectRatio fit?: 'pad' | 'fill' | 'crop' | 'scale' } const Image: FC<ImageProps> = ({ layout, src, width, aspectRatio, fit = 'scale', }) => { const height = calcAspectRatio(aspectRatio, width) const loader: ImageLoader = (args) => { const loaderHeight = calcAspectRatio(aspectRatio, args.width) return `${args.src}?w=${width}&h=${loaderHeight}&fit=${fit}` } return <NextImage {...{ layout, src, width, height, loader }} unoptimized /> } export default Image