Tips & Tricks (Actualizado: 2/6/2026)

Code splitting y lazy loading con Claude Code

Implementa code splitting en React y Next.js con Claude Code: ejemplos, pasos, riesgos, verificación y CTA.

Code splitting y lazy loading con Claude Code

Cuando una app de React o Next.js se siente lenta, muchas veces el problema está en el JavaScript inicial. El usuario entra para leer una página o pulsar un CTA, pero el navegador descarga también paneles de administración, editores, gráficos y widgets que no necesita todavía.

Code splitting significa dividir ese JavaScript en archivos más pequeños. Lazy loading significa cargar cada parte solo cuando hace falta. La idea es sencilla: no enviar toda la aplicación a cada visita inicial.

En esta guía verás cómo pedirle a Claude Code una implementación revisable, no solo una transformación automática. Usaremos React.lazy, Suspense, import() dinámico, next/dynamic, división por rutas o páginas, riesgos de hydration y una lista de verificación. Para completar el flujo, enlaza este tema con análisis de bundle, tree shaking y optimización de performance.

Conceptos básicos

Un bundle es el paquete de JavaScript enviado al navegador. Un chunk es un archivo más pequeño después de dividirlo. Un dynamic import, como import("./Chart"), carga un módulo en tiempo de ejecución. Suspense es el límite de React que muestra una UI temporal mientras se carga el componente.

hydration es el proceso en el que JavaScript del cliente conecta eventos y estado al HTML que ya vino del servidor. Si el servidor renderiza una cosa y el cliente otra, aparecen errores de hydration. Esto ocurre con facilidad cuando se leen window, localStorage, fechas o valores aleatorios demasiado pronto.

CandidatoPor qué convieneCuidado con
Paneles de administraciónNo todos los usuarios los abrenEstados de permisos y carga
Gráficos, mapas, editoresDependencias pesadasReservar altura para evitar saltos
Modales y asistentesSolo aparecen tras una acciónPrefetch si el primer clic tarda
Video, audio o búsquedaSuelen estar más abajoAccesibilidad y mensajes de error

Darle límites claros a Claude Code

No pidas solamente “haz code splitting”. Define objetivo, archivos y comprobaciones.

Objetivo:
- Cargar de forma diferida la UI pesada que no es necesaria al inicio.
- No mover hero, texto, navegación ni CTA detrás de lazy loading.
- Usar React.lazy/Suspense o next/dynamic según el framework.

Archivos objetivo:
- src/features/reports/ReportsPanel.tsx
- src/features/editor/RichEditor.tsx
- app/admin/page.tsx

Verificación:
- npm run lint
- npm run build
- Revisar initial JS y chunks diferidos en la pestaña Network.
- Revisar móvil para que el fallback no tape el CTA.

Así Claude Code trabaja con una superficie pequeña y no rompe contenido que genera confianza o ingresos.

React.lazy y Suspense

La documentación oficial de React explica que lazy retrasa la carga de un componente hasta su primer render, y Suspense muestra un fallback mientras tanto. Declara los componentes lazy en el nivel superior del módulo, no dentro de otro componente.

// src/App.tsx
import { Suspense, lazy, useState } from "react";

const ReportsPanel = lazy(() => import("./ReportsPanel"));

function PanelSkeleton() {
  return (
    <div role="status" aria-live="polite" style={{ minHeight: 180 }}>
      Cargando reportes...
    </div>
  );
}

export default function App() {
  const [showReports, setShowReports] = useState(false);

  return (
    <main>
      <h1>Dashboard</h1>
      <button type="button" onClick={() => setShowReports(true)}>
        Ver reportes
      </button>

      {showReports ? (
        <Suspense fallback={<PanelSkeleton />}>
          <ReportsPanel />
        </Suspense>
      ) : (
        <p>La UI pesada de reportes se carga solo cuando hace falta.</p>
      )}
    </main>
  );
}
// src/ReportsPanel.tsx
const rows = [
  { label: "Lectura completa", value: "68%" },
  { label: "Clics en CTA", value: "4.2%" },
  { label: "Visitas a consultoría", value: "1.1%" },
];

export default function ReportsPanel() {
  return (
    <section aria-label="Reportes">
      <h2>Reporte de conversión</h2>
      <ul>
        {rows.map((row) => (
          <li key={row.label}>
            {row.label}: {row.value}
          </li>
        ))}
      </ul>
    </section>
  );
}

lazy espera un default export. Para named exports, adapta el módulo.

// src/lazyNamed.tsx
import { lazy, type ComponentType } from "react";

export function lazyNamed<TModule, TName extends keyof TModule>(
  loader: () => Promise<TModule>,
  name: TName
) {
  return lazy(async () => {
    const module = await loader();
    return {
      default: module[name] as ComponentType,
    };
  });
}
// src/AnalyticsSlot.tsx
import { Suspense } from "react";
import { lazyNamed } from "./lazyNamed";

const BarChart = lazyNamed(() => import("./charts"), "BarChart");

export function AnalyticsSlot() {
  return (
    <Suspense fallback={<p>Cargando gráfico...</p>}>
      <BarChart />
    </Suspense>
  );
}

Dynamic import en Next.js

Next.js ya separa código por páginas y rutas. Usa next/dynamic cuando un Client Component sea pesado o dependa del navegador. El import() debe estar dentro de dynamic() y la declaración debe quedar en el nivel superior del módulo.

// app/admin/EditorSlot.tsx
"use client";

import dynamic from "next/dynamic";

const RichEditor = dynamic(() => import("./RichEditor"), {
  ssr: false,
  loading: () => (
    <p aria-live="polite" style={{ minHeight: 160 }}>
      Cargando editor...
    </p>
  ),
});

export default function EditorSlot() {
  return <RichEditor initialMarkdown="# Draft" />;
}
// app/admin/page.tsx
import EditorSlot from "./EditorSlot";

export default function AdminPage() {
  return (
    <main>
      <h1>Editor de artículos</h1>
      <p>El texto y el CTA se muestran primero. Solo se retrasa el editor pesado.</p>
      <EditorSlot />
    </main>
  );
}

ssr: false sirve para editores o previews que usan APIs del navegador, pero no debe ocultar texto de venta, precios, FAQ, títulos o CTA principales.

Dividir por rutas y páginas

Antes de dividir cada componente, empieza por rutas. En Next.js, rutas como app/reports/page.tsx y app/settings/page.tsx ya separan el código de forma natural. En una SPA con React Router, puedes lazy-loadear los componentes de ruta.

// src/AppRouter.tsx
import { Suspense, lazy } from "react";
import { BrowserRouter, Link, Route, Routes } from "react-router-dom";

const HomePage = lazy(() => import("./pages/HomePage"));
const ReportsPage = lazy(() => import("./pages/ReportsPage"));
const SettingsPage = lazy(() => import("./pages/SettingsPage"));

function RouteFallback() {
  return <p aria-live="polite">Cargando página...</p>;
}

export default function AppRouter() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/reports">Reports</Link>
        <Link to="/settings">Settings</Link>
      </nav>
      <Suspense fallback={<RouteFallback />}>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/reports" element={<ReportsPage />} />
          <Route path="/settings" element={<SettingsPage />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

No encierres toda la página en un único Suspense si solo el gráfico es lento. Mantén visibles el título, la promesa y el CTA.

Casos de uso

Primero, dashboards SaaS. La navegación y el resumen se cargan de inmediato; analítica avanzada, logs y exportaciones se cargan después de verificar permisos.

Segundo, plataformas editoriales o cursos. El artículo, la lección y el CTA de compra deben renderizar primero. El editor Markdown, recorte de imágenes y vista previa pueden retrasarse.

Tercero, landing pages con mapas, gráficos, videos o calculadoras. El mensaje inicial aparece rápido y los widgets pesados cargan al hacer scroll o clic. Para UI multimedia, revisa video player y accesibilidad.

Cuarto, modales de cotización o checkout. El botón está disponible desde el inicio y el formulario de varios pasos se descarga bajo demanda.

Fallos frecuentes

  1. Dividir demasiado genera muchos requests pequeños y puede empeorar la interacción.
  2. Declarar lazy o dynamic dentro de un componente reinicia estado y dificulta el preloading.
  3. Un fallback sin altura fija causa layout shift y puede tapar el CTA.
  4. Hydration mismatch aparece si servidor y cliente renderizan datos distintos.
  5. Poner contenido SEO o monetizable detrás de ssr: false reduce visibilidad y confianza.

Verificación

Pedido de revisión para Claude Code:
- Confirma que lazy/dynamic están en el nivel superior del módulo.
- Revisa default export frente a named export.
- Revisa si los límites de Suspense son demasiado amplios.
- Confirma que ssr:false no oculta texto SEO ni CTAs.
- Busca riesgos con window/date/random/localStorage.
- Explica cómo comparar initial JS, chunks lazy y número de requests.
npm run lint
npm run build

Después abre DevTools, filtra Network por JS, recarga y confirma que los chunks pesados no vienen en la carga inicial. Activa el reporte, editor o modal y verifica que el chunk aparezca solo entonces.

Enlaces oficiales y CTA

Consulta siempre las fuentes oficiales: React lazy, React Suspense, Next.js Lazy Loading y Next.js Layouts and Pages.

Para convertir esto en un flujo repetible, empieza con el cheatsheet gratuito de Claude Code. Para prompts reutilizables de implementación y revisión, usa 50 Claude Code Prompt Templates. Para equipos que necesitan reglas, CLAUDE.md y revisión de performance en repos reales, usa la consultoría y formación.

Nota práctica

La mejora fue más estable cuando se decidió antes qué no debía moverse: contenido inicial, navegación y CTA quedaron renderizados; reportes y editor pasaron a chunks lazy. Una petición vaga como “haz lazy loading” produjo límites de Suspense demasiado grandes y ssr: false innecesario.

#Claude Code #code splitting #performance #React #Next.js
Gratis

PDF gratis: cheatsheet de Claude Code

Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.

Cuidamos tus datos y no enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero enfocado en workflows prácticos con Claude Code.