Lazy Load
El "Lazy Load" (carga perezosa) es una técnica que permite cargar solo los componentes necesarios cuando el usuario navega a una ruta específica. Esto reduce el tamaño inicial del bundle (Javascript enviado al navegador) y mejora los tiempos de carga.
En React Router, puedes implementar el lazy loading usando la función React.lazy()
junto con el componente Suspense
para manejar el estado de carga.
Ejemplo básico
Supongamos que tienes tres componentes: Home
, About
y Contact
. Sin lazy loading, los importarías directamente al inicio del archivo:
routes.jsx
import { createBrowserRouter } from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import Contact from "./components/Contact";
export const router = createBrowserRouter([
{
path: "/",
element: <Home />,
},
{
path: "/about",
element: <About />,
},
{
path: "/contact",
element: <Contact />,
},
]);
main.jsx
import React from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { router } from './router/index.jsx'
import { RouterProvider } from 'react-router-dom'
createRoot(document.getElementById('root')).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
)
Esto carga todos los componentes al mismo tiempo, incluso los que no se necesitan inmediatamente. Con lazy loading, solo se cargan cuando el usuario navega a la ruta correspondiente:
routes.jsx
import React from "react";
import { createBrowserRouter } from "react-router-dom";
const Home = React.lazy(() => import("./components/Home"));
const About = React.lazy(() => import("./components/About"));
const Contact = React.lazy(() => import("./components/Contact"));
export const router = createBrowserRouter([
{
path: "/",
element: <Home />,
},
{
path: "/about",
element: <About />,
},
{
path: "/contact",
element: <Contact />,
},
]);
main.jsx
import React, { Suspense } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { router } from './router/index.jsx'
import { RouterProvider } from 'react-router-dom'
createRoot(document.getElementById('root')).render(
<React.StrictMode>
<Suspense fallback={<div>Cargando...</div>}>
<RouterProvider router={router} />
</Suspense>
</React.StrictMode>
)
Explicación del código
- React.lazy(): Carga los componentes de manera diferida. Cada llamada a
lazy
devuelve una promesa que importa el componente cuando se necesita. - Suspense: Muestra un contenido temporal (como un spinner o mensaje) mientras se carga el componente diferido.
- fallback: Define qué se muestra mientras se resuelve la carga del componente.
- createBrowserRouter: Función de React Router v6 para crear el enrutador.
- RouterProvider: Componente de React Router v6 para proporcionar el enrutador a la aplicación.
Beneficios del Lazy Load
El lazy load mejora el rendimiento de las aplicaciones React al reducir el tiempo de carga inicial y optimizar el uso de los recursos del navegador. Esto es especialmente relevante en aplicaciones grandes con muchas rutas y componentes.
Buenas prácticas
El uso de lazy load debe ser estratégico para maximizar su efectividad. Aquí hay algunas buenas prácticas explicadas en detalle:
Proporcionar un contenido de fallback adecuado
Cuando utilizas Suspense
, es importante proporcionar un contenido visual que informe al usuario que algo se está cargando. Esto mejora la experiencia del usuario y evita confusión. Por ejemplo:
- Mal ejemplo: Mostrar un
div
vacío o nada.
<Suspense fallback={null}>
<Home />
</Suspense>
- Buen ejemplo: Mostrar un mensaje o un spinner.
<Suspense fallback={<div>Cargando...</div>}>
<Home />
</Suspense>
Esto asegura que el usuario tenga una respuesta visual clara mientras se carga el componente.
Agrupar componentes relacionados
Si tienes rutas o funcionalidades relacionadas (como un panel de administración), puedes agruparlas en un solo "chunk" de código para que se carguen juntas. Esto reduce la cantidad de peticiones y mejora la navegación interna.
- Ejemplo práctico: En lugar de cargar cada componente de administración individualmente:
// routes.jsx
export const router = createBrowserRouter([
{
path: "/dashboard",
lazy: () => import("./components/Dashboard"),
},
{
path: "/users",
lazy: () => import("./components/Users"),
},
{
path: "/reports",
lazy: () => import("./components/Reports"),
},
]);
Agrúpalos en un módulo único:
// routes.jsx
export const router = createBrowserRouter([
{
path: "/admin",
lazy: () => import("./components/Admin"),
children: [
{
path: "dashboard",
lazy: () => import("./components/Admin/Dashboard"),
},
{
path: "users",
lazy: () => import("./components/Admin/Users"),
},
{
path: "reports",
lazy: () => import("./components/Admin/Reports"),
},
],
},
]);
Así, todo el panel de administración se carga como un único bloque cuando el usuario accede a él.
Usar lazy load en rutas secundarias
El lazy load es más útil en rutas que no se ven inmediatamente al cargar la página, como configuraciones o secciones de detalles. Por ejemplo:
Ruta principal (sin lazy load): Si un componente es esencial en la primera carga, no uses lazy load:
// routes.jsx
import Home from "./components/Home";
export const router = createBrowserRouter([
{
path: "/",
element: <Home />,
},
// ...
]);
Ruta secundaria (con lazy load): Diferir rutas secundarias como "perfil" o "configuración".
// routes.jsx
export const router = createBrowserRouter([
// ...
{
path: "/profile",
lazy: () => import("./components/Profile"),
},
{
path: "/settings",
lazy: () => import("./components/Settings"),
},
]);
Esto asegura que solo se carguen los componentes necesarios según la navegación del usuario.