Integración Next.js#

El paquete @snapkit-studio/nextjs proporciona una integración profunda con Next.js, ofreciendo compatibilidad completa con las APIs del componente Next.js Image mientras añade las poderosas capacidades de transformación de Snapkit.

Instalación#

Instala Snapkit para tu proyecto Next.js:

npm install @snapkit-studio/nextjs
# o
yarn add @snapkit-studio/nextjs
# o
pnpm add @snapkit-studio/nextjs

Inicio Rápido#

Configuración del Entorno#

Primero, configura tus variables de entorno en .env.local:

NEXT_PUBLIC_SNAPKIT_ORGANIZATION_NAME=your-organization-name
NEXT_PUBLIC_SNAPKIT_DEFAULT_QUALITY=85
NEXT_PUBLIC_SNAPKIT_DEFAULT_OPTIMIZE_FORMAT=auto

Configuración App Router#

Configura Snapkit en tu layout raíz:

// app/layout.tsx
import { SnapkitProvider } from '@snapkit-studio/nextjs';
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="es">
      <body>
        <SnapkitProvider
          baseUrl="https://snapkit-cdn.snapkit.studio"
          organizationName="your-org"
          defaultQuality={85}
          defaultFormat="auto"
        >
          {children}
        </SnapkitProvider>
      </body>
    </html>
  );
}

Configuración Pages Router#

Para Pages Router, añade el provider a _app.tsx:

// pages/_app.tsx
import { SnapkitProvider } from '@snapkit-studio/nextjs';
import type { AppProps } from 'next/app';
 
export default function App({ Component, pageProps }: AppProps) {
  return (
    <SnapkitProvider
      baseUrl="https://snapkit-cdn.snapkit.studio"
      organizationName="your-org"
      defaultQuality={85}
      defaultFormat="auto"
    >
      <Component {...pageProps} />
    </SnapkitProvider>
  );
}

Características Principales#

Reemplazo Directo#

Reemplaza el componente Next.js Image sin cambios de configuración:

// Antes
import Image from 'next/image';
 
// Después
import { Image } from '@snapkit-studio/nextjs';
 
// El uso permanece igual
<Image
  src="/hero.jpg"
  alt="Imagen hero"
  width={800}
  height={600}
  priority
/>

Ejemplo de Uso Básico#

Uso simple con optimización automática:

import { Image } from '@snapkit-studio/nextjs';
 
<Image
  src="/photo.jpg"
  width={800}
  height={600}
  alt="Foto"
  priority
  transforms={{
    format: 'auto',
    quality: 85
  }}
/>

Transformaciones Mejoradas#

Añade poderosas transformaciones más allá de las capacidades de Next.js:

import { Image } from '@snapkit-studio/nextjs';
 
<Image
  src="/product.jpg"
  alt="Imagen del producto"
  width={400}
  height={300}
  transforms={{
    format: 'auto',
    quality: 90,
    sharpen: true,
    blur: 0,
    grayscale: false
  }}
  className="rounded-lg shadow-md"
/>

Optimización Automática#

Selección de Formato#

Sirve automáticamente formatos modernos basados en el soporte del navegador:

<Image
  src="/photo.jpg"
  width={600}
  height={400}
  transforms={{
    format: 'auto' // Sirve WebP, AVIF o formato original
  }}
/>

Ajuste de Calidad#

Optimización de calidad consciente de la red:

<Image
  src="/high-res.jpg"
  width={1200}
  height={800}
  transforms={{
    quality: 'auto' // Se ajusta según la velocidad de conexión
  }}
/>

Características Específicas de Next.js#

Optimización de Imágenes#

Imports Estáticos#

Soporte completo para imports de imágenes estáticas con optimización build-time:

import heroImage from '@/public/hero.jpg';
 
<Image
  src={heroImage}
  alt="Hero"
  placeholder="blur"
  priority
  transforms={{ format: 'auto' }}
/>

Imports Dinámicos#

Para imágenes cargadas dinámicamente:

<Image
  src={`/products/${productId}.jpg`}
  width={500}
  height={500}
  transforms={{
    format: 'auto',
    fit: 'cover'
  }}
/>

Imágenes Responsivas#

Llenar Contenedor#

Para layouts responsivos basados en contenedor:

<div className="relative aspect-video">
  <Image
    src="/banner.jpg"
    alt="Banner"
    fill
    sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
    className="object-cover"
    transforms={{ format: 'auto' }}
  />
</div>

Dirección Artística#

Diferentes imágenes para diferentes breakpoints:

<picture>
  <source
    media="(max-width: 768px)"
    srcSet="/mobile-hero.jpg"
  />
  <Image
    src="/desktop-hero.jpg"
    width={1920}
    height={1080}
    alt="Hero responsivo"
    transforms={{ format: 'auto' }}
  />
</picture>

Características de Rendimiento#

Priority Loading#

Para optimización LCP:

<Image
  src="/above-fold.jpg"
  width={1200}
  height={600}
  priority
  transforms={{
    format: 'auto',
    quality: 90
  }}
/>

Lazy Loading con Placeholder#

Experiencia de carga suave:

<Image
  src="/gallery-image.jpg"
  width={400}
  height={300}
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,..."
  loading="lazy"
/>

Configuración#

Configuración next.config.js#

Configura Snapkit como tu solución de optimización de imágenes:

// next.config.js
module.exports = {
  images: {
    domains: ['snapkit-cdn.snapkit.studio'],
    loader: 'custom',
    loaderFile: './snapkit-loader.js',
  },
};

Loader Personalizado#

Crea un loader personalizado para casos de uso avanzados:

// snapkit-loader.js
export default function snapkitLoader({ src, width, quality }) {
  const url = new URL(`https://your-org-cdn.snapkit.studio/${src}`);
 
  const params = {
    w: width,
    q: quality || 75,
    auto: 'format',
  };
 
  Object.keys(params).forEach(key =>
    url.searchParams.set(key, params[key])
  );
 
  return url.href;
}

Características App Router#

Componentes Servidor#

Soporte completo para React Server Components:

// app/gallery/page.tsx
import { Image } from '@snapkit-studio/nextjs';
 
export default async function Gallery() {
  const images = await fetchImages();
 
  return (
    <div className="grid grid-cols-3 gap-4">
      {images.map((img) => (
        <Image
          key={img.id}
          src={img.url}
          width={400}
          height={300}
          alt={img.alt}
          transforms={{ format: 'auto' }}
        />
      ))}
    </div>
  );
}

Componentes Cliente#

Integración perfecta con características del lado del cliente:

'use client';
 
import { useState } from 'react';
import { Image } from '@snapkit-studio/nextjs';
 
export default function InteractiveGallery() {
  const [selectedImage, setSelectedImage] = useState(0);
 
  return (
    <Image
      src={images[selectedImage]}
      width={800}
      height={600}
      transforms={{
        format: 'auto',
        quality: 90
      }}
    />
  );
}

Uso Avanzado#

Generación de Metadatos#

Para SEO y compartir en redes sociales:

// app/products/[id]/page.tsx
import { Metadata } from 'next';
 
export async function generateMetadata({ params }): Promise<Metadata> {
  const product = await getProduct(params.id);
 
  return {
    openGraph: {
      images: [{
        url: `https://your-cdn.snapkit.studio/${product.image}?w=1200&h=630&fit=cover`,
        width: 1200,
        height: 630,
      }],
    },
  };
}

ISR y SSG#

Soporte completo para Incremental Static Regeneration:

// app/blog/[slug]/page.tsx
export const revalidate = 3600; // Revalidar cada hora
 
export default async function BlogPost({ params }) {
  const post = await getPost(params.slug);
 
  return (
    <Image
      src={post.featuredImage}
      width={1200}
      height={600}
      alt={post.title}
      priority
      transforms={{ format: 'auto' }}
    />
  );
}

Edge Runtime#

Optimizado para Edge runtime:

export const runtime = 'edge';
 
export default function EdgeOptimizedPage() {
  return (
    <Image
      src="/edge-optimized.jpg"
      width={600}
      height={400}
      transforms={{
        format: 'auto',
        quality: 85
      }}
    />
  );
}

Guía de Migración#

Desde next/image#

Cambios mínimos requeridos:

// Paso 1: Actualizar import
- import Image from 'next/image';
+ import { Image } from '@snapkit-studio/nextjs';
 
// Paso 2: Añadir transforms (opcional)
<Image
  src="/photo.jpg"
  width={500}
  height={300}
+ transforms={{ format: 'auto' }}
/>

Desde Next.js Legacy#

Para Next.js 12 y anteriores:

// Antes (Next.js 12)
<Image
  src="/photo.jpg"
  width={500}
  height={300}
  layout="responsive"
/>
 
// Después (con Snapkit)
<Image
  src="/photo.jpg"
  width={500}
  height={300}
  sizes="100vw"
  style={{
    width: '100%',
    height: 'auto',
  }}
  transforms={{ format: 'auto' }}
/>

Optimización de Rendimiento#

Optimización Build-Time#

Generar imágenes optimizadas durante el build:

// next.config.js
module.exports = {
  experimental: {
    optimizeImages: true,
  },
};

Optimización Runtime#

Optimización dinámica basada en el contexto del usuario:

<Image
  src="/dynamic.jpg"
  width={800}
  height={600}
  transforms={{
    format: 'auto',
    quality: typeof window !== 'undefined'
      ? navigator.connection?.saveData ? 60 : 85
      : 85,
  }}
/>

Mejores Prácticas#

  1. Usar App Router: Aprovecha React Server Components para mejor rendimiento.

  2. Habilitar Caching: Configura headers de cache apropiados para imágenes optimizadas.

  3. Optimizar Above-the-fold: Usa la prop priority para imágenes críticas.

  4. Imágenes Responsivas: Siempre proporciona la prop sizes para layouts responsivos.

  5. Formato Auto: Deja que Snapkit elija automáticamente el mejor formato.

Solución de Problemas#

Problemas Comunes#

  1. Mismatch de Hidratación: Asegura renderizado consistente entre servidor y cliente.

  2. Problemas CORS: Configura dominios en next.config.js.

  3. Errores de Build: Verifica que todos los imports estáticos sean válidos.

  4. Problemas de Rendimiento: Verifica la configuración de cache.

Resumen de Características Principales#

  • Integración perfecta del componente Next.js Image
  • Transformación automática de imágenes
  • Generación dinámica de srcset basada en DPR
  • Selección inteligente de formato (WebP, AVIF)
  • Soporte para componentes de servidor y cliente
  • Definiciones TypeScript
  • Cobertura de pruebas del 90%+

Recursos#