<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ NextJS - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ NextJS - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 15 May 2026 04:13:42 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/tag/nextjs/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Next.js vs React : Diferencias y cómo elegir el adecuado para tu proyecto ]]>
                </title>
                <description>
                    <![CDATA[ Como desarrollador, hay muchas herramientas, lenguajes, frameworks y paquetes de código abierto que tienes que aprender para que tu trabajo se facilite y sea sencillo (aunque el trayecto no es sencillo, lo lograrás). Algunas de estas herramientas, lenguajes, o frameworks son usados diariamente por miembros de la comunidad y pueden ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/next-js-vs-react-diferencias-y-como-elegir-el-adecuado-para-tu-proyecto/</link>
                <guid isPermaLink="false">67ff2616e738c10479d3f336</guid>
                
                    <category>
                        <![CDATA[ NextJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ csr ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elias Ezequiel Pereyra Gomez ]]>
                </dc:creator>
                <pubDate>Fri, 20 Jun 2025 15:06:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2025/04/Captura-desde-2025-04-16-00-38-46.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Como desarrollador, hay muchas herramientas, lenguajes, frameworks y paquetes de código abierto que tienes que aprender para que tu trabajo se facilite y sea sencillo (aunque el trayecto no es sencillo, lo lograrás).</p><p>Algunas de estas herramientas, lenguajes, o frameworks son usados diariamente por miembros de la comunidad y pueden padecer cambios fundamentales en cómo son implementados o escritos con el tiempo.</p><p>En este artículo, exploraremos dos tecnologías populares de JavaScript, Next.js y React.js, comparando sus diferencias claves, examinando sus fortalezas, y ofreciendo perspectivas para ayudar a los desarrolladores a elegir la mejor opción para sus proyectos.</p><h2 id="tabla-de-contenido"><strong><strong>Tabl</strong>a<strong> </strong>de<strong> </strong>Contenido</strong></h2><!--kg-card-begin: markdown--><ul>
<li><a href="#entendiendo-react">Entendiendo React</a>
<ul>
<li><a href="#renderizado-lado-cliente">Renderizado del lado del Cliente</a></li>
<li><a href="#casos-uso-react-desarrollo-web">Casos de uso para React en Desarrollo Web</a></li>
</ul>
</li>
<li><a href="#explorando-nextjs">Explorando Next.js</a>
<ul>
<li><a href="#renderizado-lado-servidor">Renderizado del lado del Servidor</a></li>
<li><a href="#casos-uso-nextjs-desarrollo-web">Casos de uso para Next.js en Desarrollo Web</a></li>
</ul>
</li>
<li><a href="#diferencia-clave-nextjs-react">Diferencias claves entre Next.js y React</a>
<ul>
<li><a href="#metodos-renderizado">Métodos de renderizado: lado del cliente vs. lado del servidor</a></li>
<li><a href="#consideraciones-rendimiento">Consideraciones de rendimiento</a></li>
<li><a href="#implicaciones-seo">Implicaciones sobre SEO</a></li>
<li><a href="#escalabilidad-complejudad-proyecto">Escalabilidad y complejidad del proyecto</a></li>
</ul>
</li>
<li><a href="#cuando-usar-react-nextjs">Cuándo usar React o Next.js</a>
<ul>
<li><a href="#cuando-usar-react">Cuándo usar React</a></li>
<li><a href="#cuando-usar-nextjs">Cuándo usar Next.js</a></li>
</ul>
</li>
<li><a href="#conclusion">Conclusión</a></li>
</ul>
<!--kg-card-end: markdown--><!--kg-card-begin: html--><h2 id="entendiendo-react">Entendiendo React</h2><!--kg-card-end: html--><p>Frecuentemente nos confundimos en cuanto si React es un framework de JavaScript o no, pero acá está la respuesta a esa pregunta. React no es un framework de JavaScript, sino una librería. Ahora, estas dos terminologías son intercambiables con frecuencia o mal usadas, pero los explicaré en breve.</p><p>Una librería es una colección de código ya escrito que puede ser re-usado o llamarse cuando construyes tu proyecto.</p><p><strong>Ejemplo</strong>: Imagina una biblioteca en donde vas a estudiar. Los libros ya están disponibles en los estantes – simplemente agarras uno que necesitas y comienzas a leer. De forma similar, en programación, una librería (o biblioteca) provee herramientas ya terminadas que puedes usar en tu proyecto sin tener que empezar de cero.</p><p>Por otro lado, un framework es como una estructura ya hecha que te ayuda a construir tu proyecto. Te da una fundación sólida para trabajar, de forma que no tengas que comenzar desde cero o escribir código repetitivo. En cambio, te enfocas en agregar tus propias características y lógica, mientras que el framework se encarga de ejecutar cosas en el momento exacto y de la forma correcta.</p><p><strong>Ejemplo</strong>: Imagina que un framework es como una casa en construcción donde los muros, el fundamento, y el techo ya están construidos. Todo lo que necesitas hacer es decidir cómo diseñar el interior – cómo elegir los muebles, la pintura y las decoraciones. El framework maneja el trabajo pesado, cómo asegurar que la casa se mantenga fuerte, mientras te enfocas en hacer lo tuyo. De forma similar, en programación, el framework provee la estructura, y tu agregas tu lógica personalizada para completar el proyecto.</p><p>Con eso fuera del camino, continuemos.</p><p>React es una de las librerías de JavaScript más populares usadas por los desarrolladores para construir interfaces de usuario rápidos, interactivos y confiables. Es una librería declarativa que ayuda a los desarrolladores crear aplicaciones web basado en componentes. Facebook desarrolló esta librería en 2011 y ha sido tendencia desde entonces.</p><p>Usualmente, cuando se escribe código JavaScript, creamos un archivo con la extensión <code>js</code>. Por ejemplo: <code>App.js</code>, <code>script.js</code>, y así sucesivamente. En React creamos un archivo con la extensión <code>jsx</code>. Eso es: <code>index.jsx</code>, <code>Home.jsx</code>, y así sucesivamente. El <code>jsx</code> es una extensión de React que te permite escribir un código de JavaScript que se parece a HTML. La sintaxis, cuando se ejecuta, pasa a través de pre-procesadores/transpiladores los cuales transforman el código parecido a HTML a código estándar de JavaScript.</p><p>En el corazón de todas las aplicaciones de React están los componentes. Los componentes son trozos de interfaces de usuario (UI) los cuales son hechos de forma independiente y pueden ser re-usados en partes distintas en tu proyecto. Distintos componentes pueden ser hechos de forma separada y luego se juntan para formar una interfaz de usuario compleja (UI).</p><p><strong>Nota</strong>: Cada aplicación de React tiene al menos un componente, comúnmente referido como el componente raíz. Este componente representa la aplicación entera. Dentro del componente raíz, con frecuencia hay otros componentes, conocidos como componentes hijos, que ayudan a estructurar y manejar distintas partes de la aplicación.</p><p>Acá hay una representación estructural de los componentes raíz e hijos.</p><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732758941272/17c6b471-b2a7-40ae-83f8-4e215a50c853.png" class="kg-image" alt="structural representation of root and child components" width="939" height="753" loading="lazy"></figure><p>De la imagen de arriba, puedes entender con claridad de qué tratan los componentes. <code>App</code> es el componente raíz, y dentro del componente raíz tenemos los componentes hijos: <code>Navbar</code>, <code>Profile</code>, <code>Blog</code> y <code>Footer</code>. Los hijos componentes pueden ser re-usados en otras páginas del proyecto sin tener que re-escribir el código nuevamente.</p><!--kg-card-begin: html--><h3 id="renderizado-lado-cliente">Renderizado del lado del cliente</h3><!--kg-card-end: html--><p>El renderizado del lado del cliente (CSR – Client Side Rendering en inglés) es una técnica común, especialmente en librerías como React y frameworks como Vue.js, Angular, y así sucesivamente. Aquí, el navegador descarga y procesa los archivos de JavaScript para renderizar dinámicamente el contenido directamente en el dispositivo del usuario. Con CSR, las páginas web se generan de forma dinámica, y cualquier actualización o cambio al código se aplica sin requerir una recarga completa de página. Solamente las partes específicas que han cambiado se actualizan, asegurando una experiencia de usuario fluida y eficiente.</p><p>Por lo tanto, en CSR, la lógica y la estructura de la página web se maneja por el cliente (navegador) y una recarga completa de página se muestra.</p><p>Para ayudarte a entender CSR, <a href="https://www.freecodecamp.org/news/rendering-patterns/#heading-single-page-applications-spas-with-client-side-rendering-csr">he agregado un artículo aquí</a>. </p><!--kg-card-begin: html--><h3 id="casos-uso-react-desarrollo-web">Casos de uso para React en Desarrollo Web</h3><!--kg-card-end: html--><p>Desde que React se volvió la opción preferida de muchos desarrolladores, su flexibilidad lo ha hecho conveniente para un amplio rango de casos de uso en desarrollo web. Aquí hay unos pocos casos:</p><ul><li><strong>Aplicaciones de una Sola Página<strong> (SPAs):</strong></strong> Cuando hablamos sobre SPAs, no nos referimos realmente que tu aplicación web tiene solamente una página, puede tener múltiples páginas. En SPAs, tus archivos de aplicación web (HTML, CSS, JS) se generan una vez en tu página web y cuando las actualizaciones subsecuentes se realizan en el archivo, tu página no tendrá que recargar completamente. Este enfoque ayuda a asegurar una transición más rápida, reduce la carga en el servidor y mejorar la experiencia general de usuario.</li><li><strong>Interfaces de Usuario <strong>Interactiv</strong>os<strong>:</strong></strong> React es idóneo para construir interfaces de usuarios interactivos, de vez en cuando, pasa por actualizaciones dinámicas basadas en las acciones de los usuarios. Ejemplos son formularios en línea, paneles de control, sitios web (sitios web de comercio electrónico), y así sucesivamente.</li><li><strong>Aplicaciones Multiplataforma<strong>:</strong></strong> Tener conocimientos de React viene a la mano cuando se construyen aplicaciones móviles, simplificando la conexión entre aplicaciones web y aplicaciones móviles. Herramientas como React Native te ayudan a lograr este proceso.</li></ul><!--kg-card-begin: html--><h2 id="explorando-nextjs">Explorando Next.js</h2><!--kg-card-end: html--><p>Next.js es un framework popular basado en React usado para construir aplicaciones web con el uso de componentes de React. Next.js provee estructura adicional, características, y optimización para tu aplicación web.</p><p>A diferencia de React, Next.js soporta renderizado del lado del servidor (SSR), por lo que las solicitudes se procesan y se generan desde el servidor y luego mostrado en el navegador (cliente).</p><!--kg-card-begin: html--><h3 id="renderizado-lado-servidor">Renderizado del lado del Servidor</h3><!--kg-card-end: html--><p>El Renderizado del lado del servidor (SSR - en inglés "Server Side-Rendering") es una técnica en el desarrollo web donde un servidor genera el HTML para una página web en el servidor y lo envía al navegador (cliente). En otras palabras, el servidor maneja las estructuras y la lógica de la página y muestra una página totalmente renderizada en la pantalla.</p><p>En el renderizado del lado del servidor, una solicitud se envía primero al servidor (cliente), luego el servidor comienza a procesar la solicitud y cuando termina de procesar la solicitud, ejecuta la solicitud al generar y muestra un archivo HTML con el contenido en el navegador (lado del cliente). Cuando un cambio se hace o una nueva página se solicita, una nueva solicitud se envía nuevamente al servidor y es procesado nuevamente – un nuevo archivo HTML y totalmente renderizado será generado y mostrado en el navegador (cliente).</p><p>Para una mejor comprensión de CSR y SSR, agregué un <a href="https://youtu.be/-JXUaydU1J0?si=U3PrqicrIJoLYOM9">vídeo de YouTube aquí</a>.</p><!--kg-card-begin: html--><h3 id="casos-uso-nextjs-desarrollo-web">Casos de Uso para Next.js en el desarrollo web</h3><!--kg-card-end: html--><ul><li><strong>Aplicaciones de una Sola Página<strong> (SPAs):</strong></strong> Next.js puede ser usado en la creación de aplicaciones de una sola página, similar a React.</li><li><strong>Optimizado para <strong>SEO:</strong></strong> Next.js ayuda en crear sitios web optimizados para SEO al renderizar un archivo HTML en el servidor y entregarlo al navegador. Esto mejora la visibilidad en el motor de búsquedas, incrementando las chances que tu sitio web aparezca en la parte superior de los resultados de búsqueda.</li><li><strong>Plataformas de <strong>Multi-Us</strong>uarios<strong>:</strong></strong> Debido a la habilidad de Next.js de manejar el enrutamiento dinámico, el manejo de API, y así sucesivamente, es fácil de crear aplicaciones que sirven para diversos propósitos.</li></ul><!--kg-card-begin: html--><h2 id="diferencia-clave-nextjs-react">Diferencia clave entre Next.js y React</h2><!--kg-card-end: html--><!--kg-card-begin: html--><h3 id="metodos-renderizado">Métodos de renderizado: lado del cliente vs. lado del servidor</h3><!--kg-card-end: html--><p>Cuando hablamos sobre el método de renderizado en React, React se base principalmente en el método de renderizado del lado del cliente (CSR). Por lo tanto tanto la lógica como la estructura de la página web será manejado por el navegador (cliente). Aunque este método se usa comúnmente, tiene algunos efectos secundarios como carga de página inicial más lenta.</p><p>Next.js por el otro lado, soporta tanto SSR como CSR ya que fue construido por encima de React. Las páginas web se renderizan en el servidor y tanto la lógica como la estructura de la página se manejan por el servidor. Esto permite una carga más rápida de la página web y también mejora el SEO.</p><!--kg-card-begin: html--><h3 id="consideraciones-rendimiento">Consideraciones de rendimiento</h3><!--kg-card-end: html--><p>En términos de consideraciones de rendimiento, Next.js se prefiere frecuentemente porque ofrece múltiples opciones de renderizado, incluyendo renderizado del lado del servidor (SSR), generación de sitios estáticos (SSG), Regeneración estático incremental (ISR), y renderizado del lado del cliente (CSR). En contraste, React primariamente provee un enfoque de renderizado único: renderizado del lado del cliente.</p><!--kg-card-begin: html--><h3 id="implicaciones-seo">Implicaciones de SEO</h3><!--kg-card-end: html--><p>React está menos optimizado para SEO porque los motores de búsqueda puede tener dificultades al indexar contenido que requiere ejecución de JavaScript para renderizar.</p><p>Del otro lado, Next.js está más optimizado para SEO que React porque renderiza contenido en el servidor, provee HTML totalmente renderizado para los motores de búsqueda para facilitar el indexado.</p><!--kg-card-begin: html--><h3 id="escalabilidad-complejudad-proyecto">Escalabilidad y complejidad del Proyecto</h3><!--kg-card-end: html--><p>En términos de escalabilidad y complejidad del proyecto, Next.js es generalmente mejor que React. Next.js provee funciones integradas que mejoran la escalabilidad de tu proyecto. Estos incluyen:</p><ul><li>Renderizado del lado del servidor (SSR) y generación de sitios estáticos (SSG) para mejor rendimiento y SEO.</li><li>Una función de rutas API incorporada para crear funciones serverless sin problemas.</li><li>Un sistema de enrutamiento basado en archivos que simplifica la organización de proyectos más grandes.</li></ul><p>En contraste, con React, eres responsable de configurar y mantener la estructura para la escalabilidad. Para proyectos más grandes, esto frecuentemente requiere agregar herramientas adicionales tales como:</p><ul><li>Librerías de gestión de estado (por ejemplo, Redux, Recoil, y así sucesivamente)</li><li>Librerías de enrutamiento (por ejemplo, React Router)</li></ul><p>Estas herramientas son necesarias para mejorar la escalabilidad de React y abarcar la complejidad del proyecto, pero también incrementan la carga y esfuerzo necesario para configurar y gestionar la aplicación.</p><p>En resumen, aquí una tabla que lo desglosa:</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>Factores</th>
<th>React</th>
<th>Next.js</th>
</tr>
</thead>
<tbody>
<tr>
<td>Escalabilidad</td>
<td>Es posible pero para incrementar la escalabilidad, requiere herramientas adicionales y una configuración personalizada.</td>
<td>Es escalable y ya tiene herramientas integradas que incrementan la escalabilidad.</td>
</tr>
<tr>
<td>Rendimiento</td>
<td>Provee solamente una opción de renderizado el cual es el renderizado del lado del cliente (CSR).</td>
<td>Ofrece múltiples opciones de renderizado, incluyendo SSR, SSG, ISR, y CSR.</td>
</tr>
<tr>
<td>SEO</td>
<td>No está optimizado para el SEO porque a los motores de búsquedas les podría costar indexar el contenido que requiere ejecución de JavaScript para renderizar.</td>
<td>Está más optimizado para el SEO que React porque renderiza el contenido en el servidor, proveyendo HTML totalmente renderizado para los motores de búsqueda para indexar más fácilmente.</td>
</tr>
<tr>
<td>Caso de uso</td>
<td>Mayormente usado en proyectos más pequeños o únicos.</td>
<td>Mayormente usado en proyectos de gran escala y mejora el rendimiento el SEO.</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><!--kg-card-begin: html--><h2 id="cuando-usar-react-nextjs">Cuándo usar React o Next.js</h2><!--kg-card-end: html--><p>Elegir la herramienta correcta para tu proyecto depende únicamente en la complejidad de la solución del proyecto que estás construyendo. Mientras que React y Next.js están relacionados cercanamente, cada uno tiene sus fortalezas y casos de uso óptimos.</p><!--kg-card-begin: html--><h3 id="cuando-usar-react">Cuándo usar React</h3><!--kg-card-end: html--><p>Aquí hay algunos casos donde es mejor usar React para tu proyecto:</p><ul><li>Cuando construyes aplicaciones altamente interactivas.</li><li>Cuando tu proyecto requiere manejo manual de enrutamiento, gestión de estado o/e integración de API.</li><li>Cuando tu proyecto requiere renderizado del lado del cliente (CSR)</li></ul><!--kg-card-begin: html--><h3 id="cuando-usar-nextjs">Cuándo usar Next.js</h3><!--kg-card-end: html--><p>Aquí hay algunos casos donde es mejor usar Next.js:</p><ul><li>Cuando tu proyecto requiere un mejor SEO.</li><li>Cuando tu proyecto requiere renderizado del lado del servidor.</li><li>Cuando tu proyecto requiere que construyas APIs junto con tu código de frontend.</li><li>Cuando construyes sitios web basado en contenido como blogs o sitios e-commerce. Debido a su uso de renderizado del lado del servidor, ayuda en mejorar los tiempos de carga de los contenidos en la página.</li><li>Next.js se usa mejor cuando quieres optimizar imágenes en tu proyecto.</li></ul><!--kg-card-begin: html--><h2 id="conclusion">Conclusión</h2><!--kg-card-end: html--><p>A este punto creo que tienes una clara comprensión de React y de Next.js, los conceptos del renderizado del lado del servidor y del lado del cliente, los casos de uso tanto para React como para Next.js, y las diferencias claves entre ellos.</p><p>Gracias por tomarte el tiempo de leer este artículo. Espero que lo hayas encontrado útil.</p><p>Feliz codificación.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo crear y enviar Plantillas de Email usando React Email y Resend en Next.js ]]>
                </title>
                <description>
                    <![CDATA[ Las aplicaciones modernas de Software frecuentemente se basan en comunicación por email para interactuar con los usuarios. Podrían enviar códigos de autenticación durante intentos de inicio de sesión, emails de marketing, o boletines informativos, por ejemplo. Esto significa que las notificaciones de email son típicamente el medio más común de ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-crear-y-enviar-plantillas-de-email-usando-react-email-y-resend-en-next-js/</link>
                <guid isPermaLink="false">67cf85b759617604dd901b87</guid>
                
                    <category>
                        <![CDATA[ next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ NextJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ resend ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elias Ezequiel Pereyra Gomez ]]>
                </dc:creator>
                <pubDate>Tue, 15 Apr 2025 14:26:02 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2025/03/3450a9b3-e740-4362-b0ab-0269646e725c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Las aplicaciones modernas de Software frecuentemente se basan en comunicación por email para interactuar con los usuarios. Podrían enviar códigos de autenticación durante intentos de inicio de sesión, emails de marketing, o boletines informativos, por ejemplo. Esto significa que las notificaciones de email son típicamente el medio más común de comunicación con los usuarios.</p><p>En este tutorial, aprenderás cómo diseñar plantillas asombrosas de email con <a href="https://react.email/docs/introduction">React Email</a> y enviarlos usando <a href="https://resend.com/docs/send-with-nextjs">Resend</a> – una potente plataforma API de correo electrónico. </p><h2 id="pre-requisitos"><strong>Pre-requisitos</strong></h2><p>Para aprovechar lo máximo de este tutorial, deberías tener un entendimiento básico de React o Next.js.</p><p>También haremos uso de las siguientes herramientas:</p><ul><li>React Email: Una librería que te permite crear plantillas de email diseñadas hermosamente usando componentes de React.</li><li>Resend: Una poderosa y sencilla plataforma API para enviar emails desde tus aplicaciones.</li></ul><h2 id="c-mo-construir-la-aplicaci-n-con-next-js"><strong>Cómo construir la Aplicación con Next.js</strong></h2><p>En esta sección, crearás una aplicación sencilla de soporte de cliente. La aplicación incluirá un formulario para usuarios para enviar sus solicitudes, el cual dispara una notificación de email confirmando que un ticket de soporte ha sido creado.</p><p>Para comenzar, primero configuraremos la interfaz de usuario y un endpoint de la API.</p><p>Ejecuta el siguiente comando para crear un nuevo proyecto de Next.js con TypeScript:</p><pre><code class="language-bash">npx create-next-app react-email-resend
</code></pre><p>Actualiza el archivo <code>app/page.tsx</code> para renderizar un formulario que recoge los detalles del cliente, incluyendo su nombre completo, la dirección de email, el asunto del ticket, y un mensaje con detalles describiendo el problema. Cuando el formulario se envía, los datos son registrados a la consola usando la función <code>handleSubmit</code>.</p><pre><code class="language-typescript">"use client";
import support from "@/app/images/support.jpg";
import { useState } from "react";
import Image from "next/image";

export default function Page() {
    //👇🏻 estados de las entradas
    const [name, setName] = useState&lt;string&gt;("");
    const [email, setEmail] = useState&lt;string&gt;("");
    const [subject, setSubject] = useState&lt;string&gt;("");
    const [content, setContent] = useState&lt;string&gt;("");

    const handleSubmit = async (e: React.FormEvent) =&gt; {
        e.preventDefault();
        //👇🏻 registra las entradas del usuario
        console.log({ name, email, subject, content });
    };
return ({/** -- elementos de UI -- */})
}
</code></pre><p>Regresa los elementos UI del formulario que aceptan el nombre completo del usuario, la dirección de email, asunto del ticket, y un mensaje con los detalles describiendo el problema.</p><pre><code class="language-typescript">    return (
        &lt;main className='w-full min-h-screen flex items-center justify-between'&gt;
                &lt;form className='w-full' onSubmit={handleSubmit}&gt;
                    &lt;label htmlFor='name' className='opacity-60'&gt;
                        Full Name
                    &lt;/label&gt;
                    &lt;input
                        type='text'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='name'
                        required
                        value={name}
                        onChange={(e) =&gt; setName(e.target.value)}
                    /&gt;

                    &lt;label htmlFor='email' className='opacity-60'&gt;
                        Email Address
                    &lt;/label&gt;
                    &lt;input
                        type='email'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='email'
                        value={email}
                        onChange={(e) =&gt; setEmail(e.target.value)}
                        required
                    /&gt;

                    &lt;label htmlFor='subject' className='opacity-60'&gt;
                        Subject
                    &lt;/label&gt;
                    &lt;input
                        type='text'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='subject'
                        value={subject}
                        onChange={(e) =&gt; setSubject(e.target.value)}
                        required
                    /&gt;

                    &lt;label htmlFor='message' className='opacity-60'&gt;
                        Message
                    &lt;/label&gt;
                    &lt;textarea
                        rows={7}
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='message'
                        required
                        value={content}
                        onChange={(e) =&gt; setContent(e.target.value)}
                    /&gt;

                    &lt;button className='w-full bg-blue-500 py-4 px-3 rounded-md font-bold text-blue-50'&gt;
                        SEND MESSAGE
                    &lt;/button&gt;
                &lt;/form&gt;
            &lt;/div&gt;
        &lt;/main&gt;
    );
</code></pre><p>Aquí está la página resultante del componente:</p><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733748196715/703e7e5b-f868-45e6-b62f-64a2d6dd279e.png" class="kg-image" alt="The Page component renders a form that accepts the user's input" width="2560" height="1420" loading="lazy"></figure><p>Luego, crea un endpoint de la API (<code>/api/route.ts</code>) que acepta las entradas del cliente.</p><pre><code class="language-bash">cd app
mkdir api &amp;&amp; cd api
touch route.ts
</code></pre><p>Copia el siguiente código en el archivo <code>api/route.ts</code>. El endpoint de la API registra la entrada del cliente a la consola después de recibirla.</p><pre><code class="language-typescript">import { NextRequest, NextResponse } from "next/server";

export async function POST(req: NextRequest) {
    const { name, email, subject, content } = await req.json();
    //👇🏻 registra los contenidos
    console.log({ name, email, subject, content });
    return NextResponse.json({
        message: "Email enviado con éxito",
        data,
 });
}
</code></pre><p>Actualiza la función <code>handleSubmit</code> para enviar los datos del cliente al endpoint de la API y regresa la respuesta JSON:</p><pre><code class="language-typescript">const handleSubmit = async (e: React.FormEvent) =&gt; {
    e.preventDefault();

    try {
        const response = await fetch("/api", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({ name, email, subject, content }),
        });
        const data = await response.json();
        alert(data.message);
    } catch (error) {
        console.error(error);
        alert("Un error ocurrió, por favor intenta nuevamente más tarde");
    }
    setName("");
    setEmail("");
    setSubject("");
    setContent("");
};
</code></pre><p>¡Felicidades! Has configurado la colección de datos y el envío. En las próximas secciones, te mostraré cómo crear y enviar plantillas de email con React Email y Resend.</p><h2 id="c-mo-crear-plantillas-de-email-usando-react-email"><strong>Cómo crear Plantillas de Email usando React Email</strong></h2><p>React Email te permite construir y enviar componentes de email usando React y TypeScript. Soporta múltiples clientes de email, incluyendo Gmail, Mail de Yahoo, Outlook, y Mail de Apple.</p><p>React Email también provee múltiples <a href="https://react.email/components">componentes UI</a> que te permiten personalizar las plantillas de email según tu diseño preferido usando componentes de React JSX/TSX.</p><p>Instala el paquete React Email y sus componentes al ejecutar el fragmento de código de abajo:</p><pre><code class="language-bash">npm install react-email -D -E
npm install @react-email/components -E
</code></pre><p>Incluye este escript en tu archivo <code>package.json</code>. Dirige a React Email a dónde están localizados las plantillas de email en tu proyecto.</p><pre><code class="language-json">  "scripts": {
    "email": "email dev --dir src/emails"
  },
</code></pre><p>Una de las características de React Email es la habilidad de pre-visualizar tu plantilla de email en tu navegador durante el desarrollo, permitiéndote ver cómo aparecerá en el email del receptor.</p><p>Así que luego, crea una carpeta <code>emails</code> que contenga un archivo <code>TicketCreated.tsx</code> dentro de la carpeta <code>src</code> de Next.js y copia el siguiente fragmento de código en el archivo:</p><pre><code class="language-typescript">import * as React from "react";
import {
    Body,
    Container,
    Head,
    Heading,
    Hr,
    Html,
    Link,
    Preview,
    Text,
    Tailwind,
} from "@react-email/components";

interface TicketCreatedProps {
    username: string;
    ticketID: string;
}

const baseUrl = process.env.VERCEL_URL || "http://localhost:3000";
</code></pre><p>En el fragmento de código de arriba, importamos los componentes necesarios para construir la plantilla de email.</p><p>Luego, agrega el componente <code>TicketCreated</code> al archivo para renderizar la plantilla de email usando los <a href="https://react.email/components">componentes de React Email</a>.</p><pre><code class="language-typescript">export const TicketCreated = ({ username, ticketID }: TicketCreatedProps) =&gt; {
    return (
        &lt;Html&gt;
            &lt;Head /&gt;
            &lt;Preview&gt;Email de Confirmación del Ticket de Soporte 🎉&lt;/Preview&gt;
            &lt;Tailwind&gt;
                &lt;Body className='bg-white my-auto mx-auto font-sans px-2'&gt;
                    &lt;Container className='border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] max-w-[465px]'&gt;
                        &lt;Heading className='text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0'&gt;
                            Tu Ticket ha sido creado
                        &lt;/Heading&gt;
                        &lt;Text className='text-black text-[14px] leading-[24px]'&gt;
                        Hola {username},
                        &lt;/Text&gt;
                        &lt;Text className='text-black text-[14px] leading-[24px]'&gt;
                            &lt;strong&gt;El Ticket de Soporte&lt;/strong&gt; (&lt;Link href={`${baseUrl}/ticket/${ticketID}`} className='text-blue-600 no-underline'&gt;{`#${ticketID}`}&lt;/Link&gt;) ha sido creado con éxito.
                        &lt;/Text&gt;

                        &lt;Text className='text-black text-[14px] leading-[24px]'&gt;El Equipo de Soporte revisará tu ticket y volverán contigo en breve.
                        &lt;/Text&gt;

                        &lt;Hr className='border border-solid border-[#eaeaea] my-[26px] mx-0 w-full' /&gt;
                        &lt;Text className='text-[#666666] text-[12px] leading-[24px]'&gt;Este mensaje estaba dirigido a {" "} &lt;span className='text-black'&gt;{username}&lt;/span&gt;. Si no creaste este ticket, por favor ignora este email.
                        &lt;/Text&gt;
                    &lt;/Container&gt;
                &lt;/Body&gt;
            &lt;/Tailwind&gt;
        &lt;/Html&gt;
    );
};
</code></pre><p>Finalmente, expórtalo y agrega un valor predeterminado para las props:</p><pre><code class="language-typescript">TicketCreated.PreviewProps = {
    username: "alanturing",
    ticketID: "9083475",
} as TicketCreatedProps;

export default TicketCreated;
</code></pre><p>Ejecuta <code>npm run email</code> en tu terminal para pre-visualizar la plantilla de email.</p><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733752824765/6c5e1518-fc85-4d79-bd05-f4a2c2381976.png" class="kg-image" alt="6c5e1518-fc85-4d79-bd05-f4a2c2381976" width="2553" height="1276" loading="lazy"></figure><p>Esta plantilla de email notifica a los clientes que su ticket de soporte ha sido creado y que alguien del equipo de soporte se comunicarán con ellos.</p><p>React Email ofrece una variedad de plantillas de email pre-diseñada, facilitando el crear email con estilos hermosos para distintos propósitos. Puedes revisar el <a href="https://demo.react.email/preview/notifications/vercel-invite-user">demo disponible para ver ejemplos</a> de lo que es posible.</p><h2 id="c-mo-enviar-emails-con-resend"><strong>Cómo enviar Emails con Resend</strong></h2><p>Resend es una API de email sencilla que te permite enviar emails dentro de tu aplicación de software. Soporta un montón de lenguajes de programación, incluyendo JavaScript (Next.js, Express, Node.js), Python, PHP, Go, and Rust, entre otros.</p><p>Resend y React Email pueden ser fácilmente integrados juntamente ya que el co-fundador de Resend, <a href="https://github.com/bukinoshita">Bu Kinoshita</a>, es también el creador de React Email.</p><p>Crea una cuenta en <a href="https://resend.com/docs/send-with-nextjs">Resend</a>. Una vez que iniciaste sesión, navega hacia la sección de claves de API en tu panel y copia tu clave de API en un archivo <code>.env.local</code>.</p><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1733753483127/4a289abc-b7e5-4c81-b7ee-e8f084354fae.png" class="kg-image" alt="4a289abc-b7e5-4c81-b7ee-e8f084354fae" width="2560" height="1384" loading="lazy"></figure><pre><code class="language-bash">//👇🏻 archivo .env.local 
RESEND_API_KEY=&lt;RESEND_API_KEY&gt;
</code></pre><p>Actualiza el endpoint de la API para enviar un email usando la plantilla de React Email, como se muestra abajo:</p><pre><code class="language-typescript">import { NextRequest, NextResponse } from "next/server";
//👇🏻 función generado del ID del boleto
import { v4 as generateID } from "uuid";
//👇🏻 importa la plantilla de email
import TicketCreated from "@/emails/TicketCreated";
//👇🏻 imports Resend
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(req: NextRequest) {
    //👇🏻 acepta la entrada del cliente desde el frontend
    const { name, email, subject, content } = await req.json();
    //👇🏻 los registra
    console.log({ name, email, subject, content });
    //👇🏻 envia una email usando la plantilla de email
    const { data, error } = await resend.emails.send({
        from: "Acme &lt;onboarding@resend.dev&gt;",
        to: [email],
        subject: "Email de Confirmación del Ticket 🎉",
        react: TicketCreated({ username: name, ticketID: generateID() }),
    });

    if (error) {
        return NextResponse.json(
            { message: "Hubo un error al enviar el email" },
            { status: 500 }
        );
    }

    return NextResponse.json({
        message: "El email se envió con éxito",
        data,
    });
}
</code></pre><p>¡Felicidades!🥳 Has completado este tutorial.</p><p>Aquí un breve demo de la aplicación:</p><figure class="kg-card kg-embed-card" data-test-label="fitted">
        <div class="fluid-width-video-container">
          <div style="padding-top: 56.25%;" class="fluid-width-video-wrapper">
            <iframe width="560" height="315" src="https://www.youtube.com/embed/RsNAtwDjAEg" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-size-adjust: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 27.5px; vertical-align: middle; aspect-ratio: 16 / 9; width: 720px; height: auto;" name="fitvid0"></iframe>
          </div>
        </div>
      </figure><h2 id="pr-ximos-pasos"><strong>Próximos Pasos</strong></h2><p>En este tutorial, aprendiste cómo crear plantillas de email con React Email y enviarlos usando Resend. Ambos paquetes te permiten integra la comunicación de email fácilmente con tus aplicaciones.</p><p>Ya sean simples las notificaciones de email, los boletines informativos, o campañas de marketing, React Email y Resend ofrecen una solución eficiente y personalizable para satisfacer tus necesidades.</p><p>Algunos recursos útiles incluyen:</p><ul><li><a href="https://react.email/components">Componentes pre-construidas de React Email</a></li><li><a href="https://react.email/docs/introduction">Documentación de React Email</a></li><li><a href="https://resend.com/docs/send-with-nextjs">Cómo instalar Resend en aplicaciones de Next.js</a></li></ul><p>¡Gracias por leer!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Manual de Next.js:  Aprender Next.js para principiantes ]]>
                </title>
                <description>
                    <![CDATA[ Escribí este tutorial para ayudarte a aprender rápidamente Next.js y familiarizarte con su funcionamiento. Es ideal para ti si tienes cero o poco conocimiento de Next.js, has usado React en el pasado y estás deseando sumergirte más en el ecosistema React, en particular en el renderizado del lado del servidor ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/manual-de-next-js/</link>
                <guid isPermaLink="false">64a2fb5213b6b807a602e5fc</guid>
                
                    <category>
                        <![CDATA[ NextJS ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Santiago Toquica Yanguas ]]>
                </dc:creator>
                <pubDate>Mon, 13 Nov 2023 14:53:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/08/Group-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/the-next-js-handbook/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">The Next.js Handbook – Learn Next.js for Beginners</a>
      </p><h3 id="escrib-este-tutorial-para-ayudarte-a-aprender-r-pidamente-next-js-y-familiarizarte-con-su-funcionamiento-">Escribí este tutorial para ayudarte a aprender rápidamente Next.js y familiarizarte con su funcionamiento.<br></h3><p>Es ideal para ti si tienes cero o poco conocimiento de Next.js, has usado React en el pasado y estás deseando sumergirte más en el ecosistema React, en particular en el renderizado del lado del servidor (<strong>server-side rendering</strong>).</p><p>Next.js me parece una herramienta impresionante para crear Aplicaciones Web, al final de este post espero que estés tan entusiasmado como yo. ¡Espero que te ayude a aprender Next.js!</p><p><a href="https://flaviocopes.com/page/nextjs-handbook/">Nota: puede descargar una versión PDF / ePub / Mobi de este tutorial para poder leerlo sin conexión.</a></p><h2 id="-ndice">Índice</h2><ol><li><a href="#intro">Introducción</a></li><li><a href="#principales">Principales características de Next.js</a></li><li><a href="#vs">Next.js vs Gatsby vs <code>create-react-app</code></a></li><li><a href="#instalar">Cómo instalar Next.js</a></li><li><a href="#ssr">Revisar código fuente para confirmar que SSR funciona</a></li><li><a href="#paquete">Los paquetes de aplicaciones</a></li><li><a href="#icono">¿Qué es ese icono en la parte inferior derecha?</a></li><li><a href="#devtools">Instalar React DevTools</a></li><li><a href="#otras">Otras técnicas de depuración que puedes utilizar</a></li><li><a href="#segunda">Añadir una segunda página al sitio web</a></li><li><a href="#dos">Enlazar las dos páginas</a></li><li><a href="#dinamico">Contenido dinámico con el router</a></li><li><a href="#previa">Prefetching(Búsqueda previa)</a></li><li><a href="#router">Uso del router para detectar el enlace activo</a></li><li><a href="#next-router">Uso de <code>next/router</code></a></li><li><a href="#getinitialprops">Alimentación de datos a los componentes mediante <code>getInitialProps()</code></a></li><li><a href="#css">CSS</a></li><li><a href="#tags">Rellenar la etiqueta head con etiquetas personalizadas</a></li><li><a href="#wrapper">Añadir un componente envolvente (Wrapper component)</a></li><li><a href="#api-routes">Rutas API</a></li><li><a href="#server">Ejecutar código en el lado del servidor o en el lado del cliente</a></li><li><a href="#despliegue">Despliegue de la versión de producción</a></li><li><a href="#now">Despliegue en Now</a></li><li><a href="#paquetes">Análisis de los paquetes de aplicaciones</a></li><li><a href="#carga">Módulos de carga lenta</a></li><li><a href="#ahora">Qué hacer a partir de ahora</a></li></ol><!--kg-card-begin: html--><h2 id="intro">Introducción</h2><!--kg-card-end: html--><p>Trabajar en una aplicación JavaScript moderna impulsada por React es increíble hasta que te das cuenta de que hay un par de problemas relacionados con la representación de todo el contenido en el lado del cliente.</p><p>En primer lugar, la página tarda más en ser visible para el usuario, porque antes de que se cargue el contenido, debe cargarse todo el JavaScript, y su aplicación necesita ejecutarse para determinar qué mostrar en la página.</p><p>En segundo lugar, si usted está construyendo un sitio web disponible al público, tiene un problema de SEO de contenido. Los motores de búsqueda están mejorando en la ejecución e indexación de aplicaciones JavaScript, pero es mucho mejor si podemos enviarles el contenido en lugar de dejar que ellos lo descubran.</p><p>La solución a ambos problemas es el <strong>renderizado del lado del servidor (server rendering</strong>), también llamado "<strong>pre-renderizado estático" </strong>(<strong>static pre-rendering</strong>).</p><p><a href="https://nextjs.org">Next.js </a> es un framework inspirado en React para hacer todo esto de una manera muy sencilla, pero no se limita a esto. Sus creadores lo anuncian como una cadena de <strong>herramientas de configuración cero y una</strong> <strong>interfaz de herramientas para aplicaciones en React.</strong></p><p>Proporciona una estructura común que te permite construir fácilmente un sitio web con React y maneja de forma transparente el renderizado del lado servidor <strong>(server-side rendering)</strong>.</p><!--kg-card-begin: html--><h2 id="principales">Principales características de Next.js</h2><!--kg-card-end: html--><p>He aquí una lista no exhaustiva de las principales características de Next.js:</p><h3 id="recarga-en-caliente-hot-code-reloading-">Recarga en caliente (Hot Code Reloading)</h3><p>Next.js recarga la página cuando detecta algún cambio guardado en disco.</p><h3 id="enrutamiento-autom-tico-automatic-routing-">Enrutamiento automático (Automatic Routing)</h3><p>Cualquier URL es mapeada al sistema de archivos, los cuales se ubican en la carpeta <code>pages</code>. No necesitas ninguna configuración (por supuesto, tienes opciones de personalización).</p><h3 id="componentes-de-un-solo-archivo-single-file-components-">Componentes de un solo archivo (Single File Components)</h3><p>Usando <code>styled-jsx</code>, completamente integrado y construido por el mismo equipo, es trivial añadir estilos al componente.</p><h3 id="renderizaci-n-del-lado-del-servidor-server-rendering-">Renderización del lado del servidor (Server Rendering)</h3><p>Puedes renderizar componentes React en el lado del servidor, antes de enviar el HTML al cliente.</p><h3 id="compatibilidad-con-el-ecosistema">Compatibilidad con el ecosistema</h3><p>Next.js funciona bien con el resto del ecosistema JavaScript, Node y React.</p><h3 id="separaci-n-autom-tica-del-c-digo">Separación automática del código</h3><p>Las páginas se renderizan sólo con las librerías y el JavaScript que requieren, nada más. En lugar de generar un único archivo JavaScript con todo el código de la aplicación, Next.js la divide automáticamente en varios recursos diferentes.</p><p>Al cargar una página sólo se carga el JavaScript necesario para esa página en concreto.</p><p>Next.js lo hace analizando los recursos importados.</p><p>Si sólo una de sus páginas importa la biblioteca Axios, por ejemplo, esa página específica incluirá la biblioteca en su paquete.</p><p>Esto garantiza que la carga de la primera página sea lo más rápida posible y que sólo las cargas de páginas futuras (si es que se activan) envíen el JavaScript necesario al cliente.</p><p>Hay una excepción notable. Las importaciones de uso frecuente se trasladan al paquete principal de JavaScript si se utilizan en al menos la mitad de las páginas del sitio.</p><h3 id="precarga-prefetching-">Precarga (Prefetching)</h3><p>El componente <code>Link</code>, utilizado para enlazar distintas páginas, admite una función de <code>prefetch</code> que precarga automáticamente los recursos de la página (incluido el código que falta debido a la separación del código) en segundo plano.</p><h3 id="componentes-din-micos-dynamic-components-">Componentes dinámicos (Dynamic Components)</h3><p>Puedes importar módulos JavaScript y componentes React de forma dinámica.</p><h3 id="exportaci-n-est-tica-static-exports-">Exportación estática (Static Exports)</h3><p>Usando el comando <code>next export</code>, Next.js te permite exportar un sitio completamente estático de tu aplicación.</p><h3 id="compatibilidad-con-typescript">Compatibilidad con TypeScript</h3><p>Next.js está escrito en TypeScript y como tal viene con un excelente soporte para TypeScript.</p><!--kg-card-begin: html--><h2 id="vs">Next.js vs Gatsby vs <code>create-react-app</code></h2><!--kg-card-end: html--><p>Next.js, <a href="https://flaviocopes.com/gatsby/">Gatsby</a> y <code>create-react-app</code> son herramientas increíbles que podemos utilizar para potenciar nuestras aplicaciones.</p><p>Digamos primero lo que tienen en común. Todas tienen React bajo el capó, potenciando toda la experiencia de desarrollo. También abstraen <a href="https://flaviocopes.com/webpack/">webpack</a> y todas esas cosas de bajo nivel que solíamos configurar manualmente en los viejos tiempos.</p><p><code>create-react-app</code> no te ayuda a generar una aplicación renderizada del lado del servidor fácilmente. Todo lo que viene con ello (SEO, velocidad...) sólo lo proporcionan herramientas como Next.js y Gatsby.</p><p><strong>¿Cuándo es Next.js mejor que Gatsby?</strong></p><p>Ambos pueden ayudar con el renderizado del lado del servidor &nbsp;(<strong>server-side rendering</strong>), pero de 2 maneras diferentes.</p><p>El resultado final usando Gatsby es un generador de sitios estáticos, sin servidor. Usted construye el sitio, y luego despliega el resultado del proceso de construcción estáticamente en Netlify u otro sitio de alojamiento estático.</p><p>Next.js proporciona un backend que puede renderizar del lado del servidor una respuesta a la petición, lo que permite crear un sitio web dinámico, lo que significa que se desplegará en una plataforma que pueda ejecutar Node.js.</p><p>Next.js también puede generar un sitio estático, pero yo no diría que es su principal caso de uso.</p><p>Si mi objetivo fuera construir un sitio estático, me costaría elegir y quizás Gatsby tenga un mejor ecosistema de plugins, incluyendo muchos para blogging en particular.</p><p>Gatsby también se basa en gran medida en <a href="https://graphql.org/">GraphQL</a>, algo que puede gustarte o disgustarte dependiendo de tus opiniones y necesidades.</p><!--kg-card-begin: html--><h2 id="instalar">¿Cómo instalar Next.js?</h2><!--kg-card-end: html--><p>Para instalar Next.js, necesitas tener instalado Node.js.</p><p>Asegúrate de que tienes la última versión de Node. Compruébalo ejecutando <code>node -v</code> en tu terminal y compárala con la última versión LTS listada en <a href="https://nodejs.org/">https://nodejs.org/</a>.</p><p>Después de instalar Node.js, tendrás el comando <code>npm</code> disponible en tu línea de comandos.</p><p>Si tienes algún problema en esta 1 fase, te recomiendo los siguientes tutoriales que he escrito para ti:</p><ul><li><a href="https://flaviocopes.com/node-installation/">Cómo instalar Node.js</a></li><li><a href="https://flaviocopes.com/how-to-update-node/">Cómo actualizar Node.js</a></li><li><a href="https://flaviocopes.com/npm/">Introducción al gestor de paquetes npm</a></li><li><a href="https://flaviocopes.com/node-installation/">Tutorial de Unix Shell</a></li><li><a href="https://flaviocopes.com/macos-terminal/">Cómo usar el terminal de macOS</a></li><li><a href="https://flaviocopes.com/bash/">El intérprete de comandos Bash</a></li></ul><p>Ahora que tienes Node actualizado a la última versión y <code>npm</code>, ¡estamos listos!</p><p>Ahora podemos elegir 2 rutas: usar <code>create-next-app</code> o el enfoque clásico que implica instalar y configurar una aplicación Next manualmente.</p><h3 id="usando-create-next-app">Usando create-next-app</h3><p>Si estás familiarizado con <code>create-react-app</code>, &nbsp;<code>create-next-app</code> es lo mismo - excepto que crea una aplicación Next en lugar de una aplicación React, como su nombre indica.</p><p>Supongo que ya tienes instalado Node.js, desde la versión 5.2 (hace más de 2 años en el momento de escribir esto), viene con el<a href="https://flaviocopes.com/npx/"> comando <code>npx</code></a> incluido. Esta herramienta útil nos permite descargar y ejecutar un comando JavaScript y lo usaremos así:</p><pre><code class="language-bash">npx create-next-app
</code></pre><p>El comando pregunta el nombre de la aplicación (y crea una nueva carpeta para ti con ese nombre), luego descarga todos los paquetes que necesita ( <code>react</code>, <code>react-dom</code>, <code>next</code>), establece el <code>package.json</code> a:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-14-at-16.46.47.png" class="kg-image" alt="package.json" width="600" height="400" loading="lazy"><figcaption>package.json</figcaption></figure><p>y puedes ejecutar inmediatamente la aplicación de ejemplo ejecutando <code>npm run dev</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-14-at-16.46.32.png" class="kg-image" alt="Inicio de ejecución Next js" width="600" height="400" loading="lazy"><figcaption>Inicio de ejecución Next js</figcaption></figure><p>Y aquí está el resultado en <a href="http://localhost:3000">http://localhost:3000</a>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-14-at-16.47.17.png" class="kg-image" alt="Aplicación iniciada en el navegador" width="600" height="400" loading="lazy"><figcaption>Aplicación iniciada en el navegador</figcaption></figure><p>Esta es la forma recomendada de iniciar una aplicación Next.js, ya que te proporciona estructura y código de ejemplo con el que jugar. Hay más ejemplos aparte del predeterminado; puedes usar cualquiera de los ejemplos almacenados en <a href="https://github.com/zeit/next.js/tree/canary/examples">https://github.com/zeit/next.js/tree/canary/examples</a> usando la opción <code>--example</code>. Por ejemplo, prueba:</p><pre><code class="language-bash">npx create-next-app --example blog-starter
</code></pre><p>Lo que le da una instancia de blog inmediatamente utilizable con resaltado de sintaxis también:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-14-at-17.13.29.png" class="kg-image" alt="Aplicación de ejemplo blog" width="600" height="400" loading="lazy"><figcaption>Aplicación de ejemplo blog</figcaption></figure><h3 id="crear-manualmente-una-aplicaci-n-next-js">Crear manualmente una aplicación Next.js</h3><p>Puedes evitar <code>create-next-app</code> si te apetece crear una aplicación Next desde cero. He aquí cómo: crea una carpeta vacía donde quieras, por ejemplo en tu carpeta de inicio y entra en ella:</p><pre><code class="language-sh">mkdir nextjs
cd nextjs
</code></pre><p>y crea tu primer directorio del proyecto Next:</p><pre><code class="language-sh">mkdir firstproject
cd firstproject
</code></pre><p>Ahora usa el comando <code>npm</code> para inicializarlo como un proyecto Node:</p><pre><code class="language-sh">npm init -y
</code></pre><p>La opción <code>-y</code> indica a <code>npm</code> que utilice la configuración predeterminada para un proyecto, rellenando un archivo <code>package.json</code> de ejemplo.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-16.59.21.png" class="kg-image" alt="Inicializando proyecto con npm init -y" width="600" height="400" loading="lazy"><figcaption>Inicializando proyecto con npm init -y</figcaption></figure><p>Ahora instala Next y React:</p><pre><code class="language-sh">npm install next react react-dom
</code></pre><p>Su carpeta de proyecto debe tener ahora 2 archivos:</p><ul><li><code>package.json</code> (<a href="https://flaviocopes.com/package-json/">ver mi tutorial sobre ello</a>)</li><li><code>package-lock.json</code> (<a href="https://flaviocopes.com/package-lock-json/">ver mi tutorial sobre package-lock</a>)</li></ul><p>y la carpeta <code>node_modules</code>.</p><p>Abra la carpeta del proyecto utilizando su editor favorito. Mi editor favorito es <a href="https://flaviocopes.com/vscode/">VS Code</a>. Si lo tienes instalado, puedes ejecutar <code>code .</code> en tu terminal para abrir la carpeta actual en el editor (si el comando no te funciona, mira esto)</p><p>Abra <code>package.json</code>, que ahora tiene este contenido:</p><pre><code class="language-json">{
  "name": "firstproject",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" &amp;&amp; exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies":  {
    "next": "^9.1.2",
    "react": "^16.11.0",
    "react-dom": "^16.11.0"
  }
}
</code></pre><p>y reemplazar la sección de <code>scripts</code> con:</p><pre><code class="language-json">"scripts": {
  "dev": "next",
  "build": "next build",
  "start": "next start"
}
</code></pre><p>Para añadir los comandos de compilación de Next.js, que usaremos pronto.</p><p>Consejo: usa <code>"dev": "next -p 3001"</code>, para cambiar el puerto y ejecutar, en este ejemplo, en el puerto 3001.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-17.01.03.png" class="kg-image" alt="Screen-Shot-2019-11-04-at-17.01.03" width="600" height="400" loading="lazy"></figure><p>Ahora crea una carpeta <code>pages</code> y añade un archivo <code>index.js</code>.</p><p>En este archivo, vamos a crear nuestro primer componente React.</p><p>Vamos a utilizarlo como la exportación por defecto:</p><pre><code class="language-js">const Index = () =&gt; (
  &lt;div&gt;
    &lt;h1&gt;Home page&lt;/h1&gt;
  &lt;/div&gt;
)

export default Index
</code></pre><p>Ahora, usando el terminal, ejecuta <code>npm run dev</code> para iniciar el servidor de desarrollo Next.</p><p>Esto hará que la aplicación esté disponible en el puerto 3000, en localhost.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-11.24.02.png" class="kg-image" alt="Ejecución del proyecto con npm run dev" width="600" height="400" loading="lazy"><figcaption>Ejecución del proyecto con npm run dev</figcaption></figure><p>Abra <a href="http://localhost:3000">http://localhost:3000</a> en su navegador para verlo.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-11.24.23.png" class="kg-image" alt="Componente con el texto Home page" width="600" height="400" loading="lazy"><figcaption>Componente con el texto Home page</figcaption></figure><!--kg-card-begin: html--><h2 id="ssr">Ver código fuente para confirmar que  <em>(Renderizado del lado del servidor)</em> SSR está trabajando</h2><!--kg-card-end: html--><p>Comprobemos ahora que la aplicación funciona como esperamos. Es una aplicación Next.js, por lo que debería renderizarse del lado del servidor (<strong>server side rendered</strong>).</p><p>Es uno de los principales argumentos de venta de Next.js: si creamos un sitio utilizando Next.js, las páginas del sitio se renderizan en el servidor, que entrega HTML al navegador.</p><p>Esto tiene 3 ventajas principales:</p><ul><li>El cliente no necesita instanciar React para renderizar, lo que hace que el sitio sea más rápido para sus usuarios.</li><li>Los motores de búsqueda indexarán las páginas sin necesidad de ejecutar el JavaScript del lado del cliente. Algo que Google comenzó a hacer, pero admitió abiertamente que es un proceso más lento (y debes ayudar a Google tanto como sea posible, si quieres clasificar bien).</li><li>Puede tener metaetiquetas de medios sociales, útiles para añadir imágenes de vista previa, personalizar el título y la descripción de cualquiera de sus páginas compartidas en Facebook, Twitter, etc.</li></ul><p>Vamos a ver la fuente de la aplicación. </p><p>Usando Chrome puede hacer clic derecho en cualquier lugar de la página, y pulse Ver fuente de la página(<strong>View Page Source</strong>).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-11.33.10.png" class="kg-image" alt="Código fuente construido" width="600" height="400" loading="lazy"><figcaption>Código fuente construido</figcaption></figure><p>Si ves el código fuente de la página, verás el fragmento <code>&lt;div&gt;&lt;h1&gt;Home page&lt;/h1&gt;&lt;/div&gt;</code> en el <code>body</code> del HTML, junto con un montón de archivos JavaScript: los paquetes de la aplicación.</p><p>No necesitamos configurar nada, <strong>SSR</strong> (Renderizado del lado del servidor) ya está trabajando para nosotros.</p><p><br>La aplicación React se ejecutará en el cliente y será el que ejecute las interacciones como hacer clic en un enlace, utilizando la renderización del lado del cliente. Pero al recargar una página se volverá a cargar desde el servidor. Y usando Next.js no debería haber ninguna diferencia en el resultado dentro del navegador - una página renderizada desde el servidor debería verse exactamente igual que una página renderizada desde el cliente.</p><!--kg-card-begin: html--><h2 id="paquete">Paquete de aplicación (app bundle)</h2><!--kg-card-end: html--><p>Cuando revisamos el código fuente de la página, vimos que se estaban cargando un montón de archivos JavaScript:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-11.34.41.png" class="kg-image" alt="Scripts cargando en el código fuente" width="600" height="400" loading="lazy"><figcaption>Scripts cargando en el código fuente</figcaption></figure><p>Empecemos por poner el código en un <a href="https://htmlformatter.com/">formateador HTML</a> para formatearlo mejor de modo que los humanos tengamos más posibilidades de entenderlo:</p><figure class="kg-card kg-code-card"><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt;
    &lt;meta charSet="utf-8" /&gt;
    &lt;meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" /&gt;
    &lt;meta name="next-head-count" content="2" /&gt;
    &lt;link rel="preload" href="/_next/static/development/pages/index.js?ts=1572863116051" as="script" /&gt;
    &lt;link rel="preload" href="/_next/static/development/pages/_app.js?ts=1572863116051" as="script" /&gt;
    &lt;link rel="preload" href="/_next/static/runtime/webpack.js?ts=1572863116051" as="script" /&gt;
    &lt;link rel="preload" href="/_next/static/runtime/main.js?ts=1572863116051" as="script" /&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;div id="__next"&gt;
        &lt;div&gt;
            &lt;h1&gt;Home page&lt;/h1&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;script src="/_next/static/development/dll/dll_01ec57fc9b90d43b98a8.js?ts=1572863116051"&gt;&lt;/script&gt;
    &lt;script id="__NEXT_DATA__" type="application/json"&gt;{"dataManager":"[]","props":{"pageProps":{}},"page":"/","query":{},"buildId":"development","nextExport":true,"autoExport":true}&lt;/script&gt;
    &lt;script async="" data-next-page="/" src="/_next/static/development/pages/index.js?ts=1572863116051"&gt;&lt;/script&gt;
    &lt;script async="" data-next-page="/_app" src="/_next/static/development/pages/_app.js?ts=1572863116051"&gt;&lt;/script&gt;
    &lt;script src="/_next/static/runtime/webpack.js?ts=1572863116051" async=""&gt;&lt;/script&gt;
    &lt;script src="/_next/static/runtime/main.js?ts=1572863116051" async=""&gt;&lt;/script&gt;
&lt;/body&gt;

&lt;/html&gt;
</code></pre><figcaption>Página principal construida</figcaption></figure><p>Tenemos 4 archivos JavaScript declarados para ser precargados en la etiqueta <code>head</code>, usando <code>rel="preload" as="script"</code>:</p><ul><li><code>/_next/static/development/pages/index.js</code> (96 LOC)</li><li><code>/_next/static/development/pages/_app.js</code> (5900 LOC)</li><li><code>/_next/static/runtime/webpack.js</code> (939 LOC)</li><li><code>/_next/static/runtime/main.js</code> (12k LOC)</li></ul><p>Esto indica al navegador que empiece a cargar esos archivos lo antes posible, antes de que comience el flujo normal de renderizado. Sin ellos, los scripts se cargarían con un retraso adicional, esto mejora el rendimiento de carga de la página.</p><p>Entonces esos 4 archivos se cargan al final del <code>body</code>, junto con <code>/_next/static/development/dll/dll_01ec57fc9b90d43b98a8.js</code> (31k LOC), y un fragmento JSON que establece algunos valores por defecto para los datos de la página:</p><figure class="kg-card kg-code-card"><pre><code class="language-html">&lt;script id="__NEXT_DATA__" type="application/json"&gt;
{
  "dataManager": "[]",
  "props": {
    "pageProps":  {}
  },
  "page": "/",
  "query": {},
  "buildId": "development",
  "nextExport": true,
  "autoExport": true
}
&lt;/script&gt;
</code></pre><figcaption>Script de Next Js</figcaption></figure><p>Los 4 archivos bundle ya cargados, están implementando una característica llamada división de código. El archivo <code>index.js</code> proporciona el código necesario para el componente <code>index</code>, que sirve a la ruta <code>/</code>, si tuviéramos más páginas tendríamos más paquetes para cada página, que sólo se cargarán si es necesario - para proporcionar un tiempo de carga más eficiente para la página.</p><!--kg-card-begin: html--><h2 id="icono">¿Qué es ese icono de abajo a la derecha?</h2><!--kg-card-end: html--><p>¿Has visto ese pequeño icono en la parte inferior derecha de la página, que parece un rayo?</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-13.21.42.png" class="kg-image" alt="Screen-Shot-2019-11-04-at-13.21.42" width="600" height="400" loading="lazy"></figure><p>Si pasas el ratón por encima, dirá "Página prerrenderizada":</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-13.21.46.png" class="kg-image" alt="Screen-Shot-2019-11-04-at-13.21.46" width="600" height="400" loading="lazy"></figure><p>Este icono, que <em>sólo es visible en el modo de desarrollo</em>, por supuesto, le dice que la página califica para la optimización estática automática, lo que básicamente significa que no depende de los datos que deben obtenerse en el momento de la invocación y puede ser prerenderizada y construida como un archivo HTML estático en tiempo de compilación (cuando ejecutamos <code>npm run build</code>).</p><p>A continuación podemos determinar esto por la ausencia del método <code>getInitialProps()</code> adjunto al componente de página.</p><p>Cuando este es el caso, nuestra página puede ser aún más rápida porque se servirá estáticamente como un archivo HTML en lugar de pasar por el servidor Node.js que genera la salida HTML.</p><p>Otro icono útil que puede aparecer junto a él o en lugar de él en páginas no pre-renderizadas, es un pequeño triángulo animado:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-14-at-14.56.21.png" class="kg-image" alt="Screen-Shot-2019-11-14-at-14.56.21" width="600" height="400" loading="lazy"></figure><p>Este es un indicador de compilación, aparece cuando guardas una página y Next.js está compilando la aplicación antes de que la recarga de código en caliente (hot code reloading) se active para recargar el código en la aplicación automáticamente.</p><p>Es una forma muy agradable de determinar inmediatamente si la aplicación ya ha sido compilada y puedas probar la parte en la que estás trabajando.</p><!--kg-card-begin: html--><h2 id="devtools">Instalar React Developer Tools</h2>
<!--kg-card-end: html--><p>Next.js se basa en React, por lo que una herramienta muy útil que es absolutamente necesario instalar (si aún no lo ha hecho) es React Developer Tools.</p><p>Disponible tanto para <a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en">Chrome</a> como para <a href="https://addons.mozilla.org/en-US/firefox/addon/react-devtools/">Firefox</a>, las React Developer Tools son un instrumento esencial que puedes utilizar para inspeccionar una aplicación React.</p><p>Ahora, las React Developer Tools no son específicas de Next.js pero quiero presentarlas porque puede que no estés 100% familiarizado con todas las herramientas que React proporciona. Es mejor adentrarse un poco en las herramientas de depuración que asumir que ya las conoces.</p><p>Estas proporcionan un inspector que revela el árbol de componentes de React que construye tu página y para cada componente puedes ir a comprobar los props, el estado, hooks y mucho más.</p><p>Una vez que hayas instalado las React Developer Tools, puedes abrir las devtools del navegador normal (en Chrome, es hacer clic con el botón derecho en la página, y luego hacer clic en <code>Inspect</code>) y encontrarás 2 nuevos paneles: <strong>Components</strong> y <strong>Profiler</strong>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-14.26.12.png" class="kg-image" alt="React Developer Tools" width="600" height="400" loading="lazy"><figcaption>React Developer Tools</figcaption></figure><p>Si mueves el ratón sobre los componentes, verás que en la página, el navegador seleccionará las partes que son renderizadas por ese componente.</p><p>Si seleccionas cualquier componente en el árbol, el panel derecho te mostrará una referencia al <strong>componente padre</strong> y los props pasados a él:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-14.27.05.png" class="kg-image" alt="Componente Index en React Developer Tools" width="600" height="400" loading="lazy"><figcaption>Componente Index en React Developer Tools</figcaption></figure><p>Puedes navegar fácilmente haciendo clic alrededor de los nombres de los componentes.</p><p>Puedes hacer clic en el icono del ojo en la barra de herramientas de desarrollador para inspeccionar el elemento DOM, también si utilizas el primer icono, el del ratón (que convenientemente se encuentra debajo del similar icono DevTools regular), puedes pasar por un elemento en la interfaz de usuario del navegador para seleccionar directamente el componente React que lo renderiza.<br></p><p>Puedes usar el icono del error <strong>(bug)</strong> para registrar los datos de un componente en la consola.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-14.31.25.png" class="kg-image" alt="Componentes en la consola" width="600" height="400" loading="lazy"><figcaption>Componentes en la consola</figcaption></figure><p>Esto es bastante impresionante porque una vez que tienes los datos impresos allí, puedes hacer clic derecho en cualquier elemento y pulsar "Almacenar como variable global". Por ejemplo aquí lo hice con la prop <code>url</code> pude inspeccionarla en la consola usando la variable temporal que se le asignó <code>temp1</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-14.40.22.png" class="kg-image" alt="Variables globales" width="600" height="400" loading="lazy"><figcaption>Variables globales</figcaption></figure><p>Usando <strong>Source Maps</strong>, que son cargados por Next.js automáticamente en modo desarrollo, desde el panel Componentes podemos pulsar el código <code>&lt;&gt;</code> y el DevTools cambiará al panel Fuente, mostrándonos el código fuente del componente:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-14.41.33.png" class="kg-image" alt="Componente Index en tab source del navegador" width="600" height="400" loading="lazy"><figcaption>Componente Index en tab source del navegador</figcaption></figure><p>La pestaña <strong>Profiler</strong> es aún más impresionante, si cabe. Nos permite <strong>grabar una interacción</strong> en la app para ver qué ocurre. No puedo mostrar un ejemplo todavía, porque se necesitan al menos 2 componentes para crear una interacción, y ahora sólo tenemos uno. Hablaré de esto más adelante.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-14.42.24.png" class="kg-image" alt="React Dev Tools - Profiler" width="600" height="400" loading="lazy"><figcaption>React Dev Tools - Profiler</figcaption></figure><p>He mostrado todas las capturas de pantalla usando Chrome, pero React Developer Tools funciona de la misma manera en Firefox:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-14.45.20.png" class="kg-image" alt="React Dev Tools - Firefox" width="600" height="400" loading="lazy"><figcaption>React Dev Tools - Firefox</figcaption></figure><!--kg-card-begin: html--><h2 id="otras">Otras técnicas de depuración que puede utilizar</h2><!--kg-card-end: html--><p>Además de las React Developer Tools, que son esenciales para construir una aplicación Next.js, quiero hacer hincapié en 2 formas de depurar aplicaciones en Next.js.</p><p>La primera es obviamente <code>console.log()</code> y todas las <a href="https://flaviocopes.com/console-api/">demás herramientas de la API de Consola</a>. La forma en que funcionan las aplicaciones Next hará que una declaración de tipo log funcione en la consola del navegador o en la terminal donde iniciaste Next usando <code>npm run dev</code>.</p><p>En particular, si la página se carga desde el servidor, cuando apuntas la URL a ella, o pulsas el botón refrescar / cmd/ctrl-R, cualquier registro de consola ocurre en la terminal.</p><p>Las subsiguientes transiciones de página que ocurran al pulsar el ratón harán que todo el registro de consola ocurra dentro del navegador.</p><p>Sólo recuerde si usted se sorprende por la falta de registro de mensajes.</p><p>Otra herramienta que es esencial es la palabra <code>debugger</code>. Añadiendo esta sentencia a un componente se pausará el renderizado de la página por parte del navegador:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-15.10.32.png" class="kg-image" alt="debugger en componente Index" width="600" height="400" loading="lazy"><figcaption>debugger en componente Index</figcaption></figure><p>Realmente impresionante porque ahora puedes usar el depurador del navegador para inspeccionar valores y ejecutar tu aplicación línea a línea.</p><p>También puedes usar el depurador de VS Code para depurar código del lado del servidor. Menciono esta técnica y <a href="https://github.com/Microsoft/vscode-recipes/tree/master/Next-js">este tutorial</a> para configurar esto.</p><!--kg-card-begin: html--><h2 id="segunda">Añadir una segunda página al sitio web</h2><!--kg-card-end: html--><p>Ahora que tenemos un buen conocimiento de las herramientas que podemos utilizar para ayudarnos a desarrollar aplicaciones Next.js, vamos a continuar desde donde dejamos nuestra primera aplicación:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-13.21.42-1.png" class="kg-image" alt="Localhost en Firefox" width="600" height="400" loading="lazy"><figcaption>Localhost en Firefox</figcaption></figure><p>Quiero añadir una segunda página a este sitio web, un blog. Va a ser servido en <code>/blog</code> y por el momento sólo contendrá una simple página estática, al igual que nuestro primer componente <code>index.js</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-15.39.40.png" class="kg-image" alt="Componente Blog" width="600" height="400" loading="lazy"><figcaption>Componente Blog</figcaption></figure><p>Después de guardar el nuevo archivo, el proceso <code>npm run dev</code> ya en ejecución es capaz de renderizar la página, sin necesidad de reiniciarlo.<br></p><p>Cuando pulsamos la URL <a href="http://localhost:3000/blog">http://localhost:3000/blog</a> tenemos la nueva página:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-15.41.39.png" class="kg-image" alt="Ruta con componente Blog" width="600" height="400" loading="lazy"><figcaption>Ruta con componente Blog</figcaption></figure><p>y esto es lo que nos dijo el terminal:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-15.41.03.png" class="kg-image" alt="Terminal con estado exitoso" width="600" height="400" loading="lazy"><figcaption>Terminal con estado exitoso</figcaption></figure><p>Ahora el hecho de que la URL sea <code>/blog</code> depende sólo del nombre del archivo y de su posición dentro de la carpeta <code>pages</code>.</p><p>Puedes crear una página <code>pages/hey/ho</code> y esta página aparecerá en la URL <a href="http://localhost:3000/hey/ho">http://localhost:3000/hey/ho</a>.</p><p>Lo que no importa, a efectos de la URL, es el nombre del componente dentro del archivo.</p><p>Intenta ir y ver el código fuente de la página, cuando se carga desde el servidor listará <code>/_next/static/development/pages/blog.js</code> como uno de los paquetes cargados y no <code>/_next/static/development/pages/index.js</code> como en la página de inicio. Esto se debe a que gracias a la división automática del código no necesitamos el bundle que sirve a la página de inicio. Sólo el paquete de aplicación<strong>(bundle)</strong> que sirve la página del blog.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-16.24.53.png" class="kg-image" alt="Código fuente de ruta /blog" width="600" height="400" loading="lazy"><figcaption>Código fuente de ruta /blog</figcaption></figure><p>También podemos simplemente exportar una función anónima desde <code>blog.js</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">export default () =&gt; (
  &lt;div&gt;
    &lt;h1&gt;Blog&lt;/h1&gt;
  &lt;/div&gt;
)
</code></pre><figcaption>Componente Blog con función anónima de flecha</figcaption></figure><p>o si prefiere la sintaxis de funciones sin flechas:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">export default function() {
  return (
    &lt;div&gt;
      &lt;h1&gt;Blog&lt;/h1&gt;
    &lt;/div&gt;
  )
}
</code></pre><figcaption>Componente Blog sin función flecha</figcaption></figure><!--kg-card-begin: html--><h2 id="dos">Enlazar las dos páginas</h2>
<!--kg-card-end: html--><p>Ahora que tenemos 2 páginas, definidas por <code>index.js</code> y <code>blog.js</code>, podemos introducir enlaces.</p><p>Los enlaces HTML normales dentro de las páginas se hacen utilizando la etiqueta <code>a</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-html">&lt;a href="/blog"&gt;Blog&lt;/a&gt;
</code></pre><figcaption>Etiqueta "a" (Hipervinculos)</figcaption></figure><p>No podemos hacer eso en Next.js.</p><p>¿Por qué? Técnicamente podemos, claro, porque esto es la Web y en la Web las cosas nunca se rompen (por eso podemos seguir usando la etiqueta <code>&lt;marquee&gt;</code>. Pero una de las principales ventajas de usar Next, es que una vez cargada una página, las transiciones a otra son muy rápidas gracias al renderizado del lado del cliente.</p><p>Si usas un simple enlace <code>a</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const Index = () =&gt; (
  &lt;div&gt;
    &lt;h1&gt;Home page&lt;/h1&gt;
    &lt;a href='/blog'&gt;Blog&lt;/a&gt;
  &lt;/div&gt;
)

export default Index
</code></pre><figcaption>Componente Index con etiqueta a</figcaption></figure><p>Ahora abre el <strong>DevTools</strong>, y el panel de <strong>Network panel </strong>(Panel Red). La primera vez que cargamos <a href="http://localhost:3000/">http://localhost:3000/</a> se cargan todos los paquetes de páginas:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-16.26.00.png" class="kg-image" alt="Network tab" width="600" height="400" loading="lazy"><figcaption>Network tab</figcaption></figure><p>Ahora, si haces clic en el botón "Conservar registro" (para evitar que se borre el panel Red), haces clic en el enlace "Blog", esto es lo que ocurre:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-16.27.16.png" class="kg-image" alt="Network tab cargando código" width="600" height="400" loading="lazy"><figcaption>Network tab cargando código</figcaption></figure><p>Tenemos todo ese JavaScript del servidor, ¡otra vez! Pero... no necesitamos todo ese JavaScript si ya lo tenemos. Sólo necesitaríamos el paquete de página <code>blog.js</code>, el único que es nuevo en la página.</p><p>Para solucionar este problema, utilizamos un componente proporcionado por Next, llamado <strong>Link</strong>.</p><p>Lo importamos:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import Link from 'next/link'
</code></pre><figcaption>Componente Link en Next Js</figcaption></figure><p>y luego lo usamos para envolver nuestro enlace, así:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import Link from 'next/link'

const Index = () =&gt; (
  &lt;div&gt;
    &lt;h1&gt;Home page&lt;/h1&gt;
    &lt;Link href='/blog'&gt;
      &lt;a&gt;Blog&lt;/a&gt;
    &lt;/Link&gt;
  &lt;/div&gt;
)

export default Index
</code></pre><figcaption>Componente Link envolviendo etiqueta a</figcaption></figure><p>Ahora si vuelves a intentar lo que hicimos anteriormente, podrás ver que sólo se carga el bundle <code>blog.js</code> cuando pasamos a la página del blog:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-04-at-16.35.18.png" class="kg-image" alt="Screen-Shot-2019-11-04-at-16.35.18" width="600" height="400" loading="lazy"></figure><p>y la página se cargó tan rápido que ni siquiera apareció el spinner habitual del navegador en la pestaña. Sin embargo, la URL cambió, como puedes ver. Esto funciona perfectamente con la <a href="https://flaviocopes.com/history-api/">API del historial del navegador</a>.</p><p>Esto es renderizado del lado del cliente en acción.</p><p>¿Y si ahora pulsas el botón Atrás? No se descarga nada, porque el navegador todavía tiene el antiguo paquete <code>index.js</code>, listo para cargar la ruta <code>/index</code>. Todo es automático.</p><!--kg-card-begin: html--><h2 id="dinamico">Contenido dinámico con el router</h2><!--kg-card-end: html--><p>En el capítulo anterior vimos cómo enlazar la página home con la página del blog.</p><p>Un blog es un gran caso de uso para Next.js, que seguiremos explorando en este capítulo añadiendo más <strong>artículos al blog</strong>.</p><p>Los artículos de blog tienen una URL dinámica. Por ejemplo, una entrada titulada "Hello World" podría tener la URL <code>/blog/hello-world</code>. Una entrada titulada "My second post" podría tener la URL <code>/blog/my-second-post</code>.</p><p>Este contenido es dinámico y puede proceder de una base de datos, archivos markdown u otros.</p><p>Next.js puede servir contenido dinámico basado en una <strong>URL dinámica</strong>.</p><p>Creamos una URL dinámica creando una página dinámica con la sintaxis <code>[]</code>.</p><p>¿Cómo? Añadimos un archivo <code>pages/blog/[id].js</code>. Este archivo manejará todas las URLs dinámicas bajo la ruta <code>/blog/</code>, como las que mencionamos anteriormente: <code>/blog/hello-world</code>, <code>/blog/my-second-post</code> y más.</p><p>En el nombre del archivo, <code>[id]</code> dentro de los corchetes significa que cualquier cosa que sea dinámica será puesta dentro del parámetro <code>id</code> de la <strong>propiedad query </strong>del <strong>enrutador</strong>.</p><p>Vale, son demasiadas cosas a la vez.</p><p>¿Qué es el <strong>enrutador?</strong></p><p>El enrutador es una biblioteca proporcionada por Next.js.</p><p>Lo importamos desde <code>next/router</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import { useRouter } from 'next/router'
</code></pre><figcaption>importar enrutador</figcaption></figure><p>y una vez que tenemos <code>useRouter</code>, instanciamos el objeto router usando:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const router = useRouter()
</code></pre><figcaption>Hook para usar el enrutador</figcaption></figure><p>Una vez que tenemos este objeto router, podemos extraer información de él.</p><p>En particular, podemos obtener la parte dinámica de la URL en el archivo <code>[id].js</code> accediendo a <code>router.query.id</code>.</p><p>La parte dinámica también puede ser sólo una parte de la URL, como <code>post-[id].js</code>.</p><p>Así que vamos a seguir adelante y aplicar todas esas cosas en la práctica.</p><p>Crea el archivo <code>pages/blog/[id].js</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import { useRouter } from 'next/router'

export default () =&gt; {
  const router = useRouter()

  return (
    &lt;&gt;
      &lt;h1&gt;Blog post&lt;/h1&gt;
      &lt;p&gt;Post id: {router.query.id}&lt;/p&gt;
    &lt;/&gt;
  )
}
</code></pre><figcaption>Uso del Hook useRouter</figcaption></figure><p>Ahora si vas al router <code>http://localhost:3000/blog/test</code>, deberías ver esto:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-05-at-16.41.32.png" class="kg-image" alt="Componente renderizado Blog con uso enrutador" width="600" height="400" loading="lazy"><figcaption>Componente renderizado Blog con uso enrutador</figcaption></figure><p>Podemos utilizar este parámetro <code>id</code> para recoger el artículo de una lista de articulos. De una base de datos, por ejemplo. Para mantener las cosas simples vamos a añadir un archivo<code>posts.json</code> en la carpeta raíz del proyecto:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">{
  "test": {
    "title": "test post",
    "content": "Hey some post content"
  },
  "second": {
    "title": "second post",
    "content": "Hey this is the second post content"
  }
}
</code></pre><figcaption>Json con los diferentes artículos o posts</figcaption></figure><p>Ahora podemos importarlo y buscar el puesto a partir de la clave <code>id</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import { useRouter } from 'next/router'
import posts from '../../posts.json'

export default () =&gt; {
  const router = useRouter()

  const post = posts[router.query.id]

  return (
    &lt;&gt;
      &lt;h1&gt;{post.title}&lt;/h1&gt;
      &lt;p&gt;{post.content}&lt;/p&gt;
    &lt;/&gt;
  )
}
</code></pre><figcaption>Código con los artículos</figcaption></figure><p>La recarga de la página debería mostrarnos este resultado:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-05-at-16.44.07.png" class="kg-image" alt="Componente con artículo ejemplo" width="600" height="400" loading="lazy"><figcaption>Componente con artículo ejemplo</figcaption></figure><p>Pero no es así. En su lugar, obtenemos un error en la consola, y un error en el navegador también:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-05-at-18.18.17.png" class="kg-image" alt="Error con propiedad title del artículo esta en undefined" width="600" height="400" loading="lazy"><figcaption>Error con propiedad title del artículo esta en undefined</figcaption></figure><p>¿Por qué? Porque... durante el renderizado, cuando se inicializa el componente, los datos no están ahí todavía. Veremos cómo proporcionar los datos al componente con getInitialProps en la próxima lección.</p><p>Por ahora, añade una pequeña comprobación <code>if (!post) return &lt;p&gt;&lt;/p&gt;</code> antes de devolver el JSX:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import { useRouter } from 'next/router'
import posts from '../../posts.json'

export default () =&gt; {
  const router = useRouter()

  const post = posts[router.query.id]
  if (!post) return &lt;p&gt;&lt;/p&gt;

  return (
    &lt;&gt;
      &lt;h1&gt;{post.title}&lt;/h1&gt;
      &lt;p&gt;{post.content}&lt;/p&gt;
    &lt;/&gt;
  )
}
</code></pre><figcaption>Comprobación en caso de que un post sea indefinido</figcaption></figure><p>Ahora las cosas deberían funcionar. Inicialmente el componente se muestra sin la información dinámica <code>router.query.id</code>. Después de la representación, Next.js activa una actualización con el valor de la consulta y la página muestra la información correcta.</p><p>Y si ves el código fuente, hay una etiqueta <code>&lt;p&gt;</code>vacía en el HTML</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-05-at-18.20.58.png" class="kg-image" alt="Comprobación de código fuente artículo undefined" width="600" height="400" loading="lazy"><figcaption>Comprobación de código fuente artículo undefined</figcaption></figure><p>Pronto solucionaremos este problema que no implementa SSR y esto perjudica tanto a los tiempos de carga para nuestros usuarios, SEO y el compartir en redes sociales como ya comentamos.</p><p>Podemos completar el ejemplo del blog listando esas entradas en <code>pages/blog.js</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import posts from '../posts.json'

const Blog = () =&gt; (
  &lt;div&gt;
    &lt;h1&gt;Blog&lt;/h1&gt;

    &lt;ul&gt;
      {Object.entries(posts).map((value, index) =&gt; {
        return &lt;li key={index}&gt;{value[1].title}&lt;/li&gt;
      })}
    &lt;/ul&gt;
  &lt;/div&gt;
)

export default Blog
</code></pre><figcaption>Componente blog listando articulos</figcaption></figure><p>Y podemos enlazarlos a las páginas individuales de los posts, importando <code>Link</code> desde <code>next/link</code> usándolo dentro del bucle de posts:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import Link from 'next/link'
import posts from '../posts.json'

const Blog = () =&gt; (
  &lt;div&gt;
    &lt;h1&gt;Blog&lt;/h1&gt;

    &lt;ul&gt;
      {Object.entries(posts).map((value, index) =&gt; {
        return (
          &lt;li key={index}&gt;
            &lt;Link href='/blog/[id]' as={'/blog/' + value[0]}&gt;
              &lt;a&gt;{value[1].title}&lt;/a&gt;
            &lt;/Link&gt;
          &lt;/li&gt;
        )
      })}
    &lt;/ul&gt;
  &lt;/div&gt;
)

export default Blog
</code></pre><figcaption>Componente blog enlazando articulos</figcaption></figure><!--kg-card-begin: html--><h2 id="previa">Búsqueda previa</h2><!--kg-card-end: html--><p>Anteriormente mencioné como el componente <code>Link</code> Next.js puede ser usado para crear enlaces entre 2 páginas cuando lo usas en Next.js, <strong>maneja de forma transparente el enrutamiento frontend</strong> por nosotros, así que cuando un usuario hace clic en un enlace, frontend se encarga de mostrar la nueva página sin desencadenar un nuevo ciclo de petición y respuesta cliente/servidor, como sucede normalmente con las páginas web.</p><p>Hay otra cosa que Next.js hace por ti cuando utilizas <code>Link</code>.</p><p>Tan pronto como un elemento envuelto dentro de <code>&lt;Link&gt;</code> aparece en la ventana gráfica (lo que significa que es visible para el usuario del sitio web), Next.js precarga la URL a la que apunta, siempre y cuando sea un enlace local (en su sitio web), haciendo que la aplicación sea súper rápida para el espectador.</p><p>Este comportamiento sólo se activa en <strong>modo de producción</strong> (hablaremos de esto en profundidad más adelante), lo que significa que tienes que detener la aplicación si la estás ejecutando con <code>npm run dev</code>, compilar tu bundle de producción con <code>npm run build</code> y ejecutarlo con <code>npm run start</code> en su lugar.</p><p>Usando el inspector de Network(red) en DevTools te darás cuenta de que cualquier enlace por encima del pliegue, en la carga de la página, comienza la precarga tan pronto como el evento <code>load</code> se ha disparado en tu página (se dispara cuando la página está completamente cargada, y sucede después del evento <code>DOMContentLoaded</code>).</p><p>Cualquier otra etiqueta <code>Link</code> que no esté en la ventana gráfica será precargada cuando el usuario haga scroll <code>npm run dev</code>.</p><p>La precarga es automática en conexiones de alta velocidad (Wifi y 3g+), a menos que el navegador envíe el <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Save-Data">encabezado HTTP</a> <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Save-Data"><code>Save-Data</code></a>.</p><p>Usted puede optar por no precargar instancias de <code>Link</code> individuales estableciendo la prop <code>prefetch</code> a <code>false</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">&lt;Link href="/a-link" prefetch={false}&gt;
  &lt;a&gt;A link&lt;/a&gt;
&lt;/Link&gt;
</code></pre><figcaption>Precarga en falso en componente Link</figcaption></figure><!--kg-card-begin: html--><h2 id="router">Uso del router para detectar el enlace activo</h2><!--kg-card-end: html--><p>Una característica muy importante cuando se trabaja con enlaces, es determinar cuál es la URL actual y en particular asignar una clase al enlace activo, para que podamos darle un estilo diferente a los demás.</p><p>Esto es especialmente útil en la cabecera de su sitio, por ejemplo.</p><p>El componente <code>Link</code> por defecto de Next.js que se ofrece en <code>next/link</code> no hace esto automáticamente por nosotros.</p><p>Podemos crear un componente Link nosotros mismos, y lo almacenamos en un archivo <code>Link.js</code> en la carpeta Components e importamos eso en lugar del predeterminado <code>next/link</code>.</p><p>En este componente, primero importaremos React de <code>react</code>, Link de <code>next/link</code> y el hook <code>useRouter</code> de <code>next/router</code>.</p><p>Dentro del componente determinamos si el nombre de la ruta actual coincide con la <code>href</code> &nbsp;prop del componente y si es así añadimos la clase <code>selected</code> a los hijos.</p><p>Finalmente devolvemos estos niños con la clase actualizada, utilizando <code>React.cloneElement()</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'

export default ({ href, children }) =&gt; {
  const router = useRouter()

  let className = children.props.className || ''
  if (router.pathname === href) {
    className = `${className} selected`
  }

  return &lt;Link href={href}&gt;{React.cloneElement(children, { className })}&lt;/Link&gt;
}
</code></pre><figcaption>Detectar enlace activo</figcaption></figure><!--kg-card-begin: html--><h2 id="next-router">Uso de <code>next/router</code></h2><!--kg-card-end: html--><p>Ya hemos visto cómo utilizar el componente Link para manejar el enrutamiento de forma declarativa en las aplicaciones Next.js.</p><p>Es realmente práctico gestionar el enrutamiento en JSX, pero a veces necesitas activar un cambio de enrutamiento mediante programación.</p><p>En este caso, puedes acceder directamente al enrutador Next.js, proporcionado en el paquete <code>next/router</code>, y llamar a su método <code>push()</code>.</p><p>He aquí un ejemplo de acceso al enrutador:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import { useRouter } from 'next/router'

export default () =&gt; {
  const router = useRouter()
  //...
}
</code></pre><figcaption>Uso Hook useRouter</figcaption></figure><p>Una vez que obtenemos el objeto router invocando <code>useRouter()</code>, podemos utilizar sus métodos.</p><p>Este es el router del lado del cliente, por lo que los métodos sólo deben ser utilizados en el código frontend. La forma más fácil de asegurar esto es envolver las llamadas en el hook <code>useEffect()</code> de React o dentro de <code>componentDidMount()</code>en los componentes con estado de React.</p><p>Las más utilizadas son <code>push()</code> y <code>prefetch()</code>.</p><p><code>push()</code> nos permite desencadenar programáticamente un cambio de URL, en el frontend:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">router.push('/login')
</code></pre><figcaption>router API - push</figcaption></figure><p><code>prefetch()</code> nos permite precargar una URL programada, lo que resulta útil cuando no disponemos de una etiqueta <code>Link</code> que gestione automáticamente la precarga por nosotros:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">router.prefetch('/login')
</code></pre><figcaption>router API - prefetch</figcaption></figure><p>Ejemplo completo:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import { useRouter } from 'next/router'

export default () =&gt; {
  const router = useRouter()

  useEffect(() =&gt; {
    router.prefetch('/login')
  })
}
</code></pre><figcaption>router API - prefetch en componente</figcaption></figure><p>También puedes utilizar el router para escuchar <a href="https://nextjs.org/docs#router-events">eventos de cambio de ruta</a>.</p><!--kg-card-begin: html--><h2 id="getinitialprops">Proporcionar datos a los componentes mediante getInitialProps</h2><!--kg-card-end: html--><p>En el capítulo anterior tuvimos un problema con la generación dinámica de la página de publicación, porque el componente requería algunos datos por adelantado y cuando intentamos obtener los datos del archivo JSON:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import { useRouter } from 'next/router'
import posts from '../../posts.json'

export default () =&gt; {
  const router = useRouter()

  const post = posts[router.query.id]

  return (
    &lt;&gt;
      &lt;h1&gt;{post.title}&lt;/h1&gt;
      &lt;p&gt;{post.content}&lt;/p&gt;
    &lt;/&gt;
  )
}
</code></pre><figcaption>Componente Article - Post</figcaption></figure><p>Obtenemos este error:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-05-at-18.18.17-1.png" class="kg-image" alt="Screen-Shot-2019-11-05-at-18.18.17-1" width="600" height="400" loading="lazy"><figcaption>Error datos undefined</figcaption></figure><p>¿Cómo lo solucionamos? ¿Y cómo hacemos que SSR funcione para rutas dinámicas?</p><p>Debemos dotar al componente de props, utilizando una función especial llamada <code>getInitialProps()</code> que se adjunta al componente.</p><p>Para ello, primero nombramos el componente:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const Post = () =&gt; {
  //...
}

export default Post
</code></pre><figcaption>Componente Post</figcaption></figure><p>Entonces le añadimos la función:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const Post = () =&gt; {
  //...
}

Post.getInitialProps = () =&gt; {
  //...
}

export default Post
</code></pre><figcaption>Adición de función&nbsp;</figcaption></figure><p>Esta función obtiene como argumento un objeto que contiene varias propiedades. En concreto, lo que nos interesa ahora es que obtenga el objeto <code>query</code>, el que usamos anteriormente para obtener el id del post.</p><p><em>Así que podemos obtenerlo usando la sintaxis de desestructuración de objetos:</em></p><figure class="kg-card kg-code-card"><pre><code class="language-js">Post.getInitialProps = ({ query }) =&gt; {
  //...
}
</code></pre><figcaption>Desestructuración de Props</figcaption></figure><p>Ahora podemos devolver el post desde esta función:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">Post.getInitialProps = ({ query }) =&gt; {
  return {
    post: posts[query.id]
  }
}
</code></pre><figcaption>getInitialProps -&nbsp;</figcaption></figure><p>Y también podemos eliminar la importación de <code>useRouter</code> y obtenemos el post de la propiedad <code>props</code> pasada al componente <code>Post</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import posts from '../../posts.json'

const Post = props =&gt; {
  return (
    &lt;div&gt;
      &lt;h1&gt;{props.post.title}&lt;/h1&gt;
      &lt;p&gt;{props.post.content}&lt;/p&gt;
    &lt;/div&gt;
  )
}

Post.getInitialProps = ({ query }) =&gt; {
  return {
    post: posts[query.id]
  }
}

export default Post
</code></pre><figcaption>Obtención de props basados en getInitialProps</figcaption></figure><p>Ahora no habrá ningún error, el SSR estará funcionando como se esperaba, como se puede ver comprobando la vista fuente:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-05-at-18.53.02.png" class="kg-image" alt="Código fuente con getInitialProps" width="600" height="400" loading="lazy"><figcaption>Código fuente con getInitialProps</figcaption></figure><p>La función <code>getInitialProps</code> se ejecutará en el lado del servidor, pero también en el lado del cliente, cuando naveguemos a una nueva página utilizando el componente <code>Link</code> como hemos hecho.</p><p>Es importante tener en cuenta que <code>getInitialProps</code> obtiene el objeto de contexto que recibe, además del objeto de <code>query</code>(consulta) estas otras propiedades:</p><ul><li><code>pathname</code>: la sección <code>path</code> de la URL</li><li><code>asPath</code>: Cadena de texto de la ruta real (incluida la consulta) que se muestra en el navegador</li></ul><p>que en el caso de llamar a<code>http://localhost:3000/blog/test</code> dará como resultado respectivamente:</p><ul><li><code>/blog/[id]</code></li><li><code>/blog/test</code></li></ul><p>Y en el caso del renderizado del lado del servidor, también recibirá:</p><ul><li><code>req</code>: el objeto de solicitud HTTP</li><li><code>res</code>: el objeto de respuesta HTTP</li><li><code>err</code>: un objeto de error</li></ul><p><code>req</code> y <code>res</code> te resultarán familiares si has codificado con Node.js.</p><h2 id="css">CSS</h2><p>¿Cómo damos estilo a los componentes React en Next.js?</p><p>Tenemos mucha libertad, porque podemos usar la librería de nuestra preferencia.</p><p>Pero Next.js viene con <a href="https://github.com/zeit/styled-jsx"><code>styled-jsx</code></a> incorporado, porque es una librería construida por la misma gente que trabaja en Next.js.</p><p>Se trata de una biblioteca muy interesante que nos proporciona CSS de ámbito limitado, lo que resulta muy útil para el mantenimiento, ya que el CSS sólo afecta al componente al que se aplica.</p><p>Creo que este es un gran enfoque para escribir CSS, sin la necesidad de aplicar bibliotecas adicionales o preprocesadores que añaden complejidad.</p><p>Para añadir CSS a un componente React en Next.js lo insertamos dentro de un snippet en el JSX, que empieza por</p><figure class="kg-card kg-code-card"><pre><code class="language-js">&lt;style jsx&gt;{`
</code></pre><figcaption>Snippet JSX de estilo de apertura</figcaption></figure><p>y termina con</p><figure class="kg-card kg-code-card"><pre><code class="language-js">`}&lt;/style&gt;
</code></pre><figcaption>Snippet JSX de estilo de cierre</figcaption></figure><p>Dentro de estos extraños bloques escribimos CSS plano, como haríamos en un archivo <code>.css</code>:</p><pre><code class="language-js">&lt;style jsx&gt;{`
  h1 {
    font-size: 3rem;
  }
`}&lt;/style&gt;
</code></pre><p>Lo escribes dentro del JSX, así:</p><pre><code class="language-js">const Index = () =&gt; (
  &lt;div&gt;
		&lt;h1&gt;Home page&lt;/h1&gt;

		&lt;style jsx&gt;{`
		  h1 {
		    font-size: 3rem;
		  }
		`}&lt;/style&gt;
  &lt;/div&gt;
)

export default Index
</code></pre><p>Dentro del bloque podemos utilizar la interpolación para cambiar dinámicamente los valores. Por ejemplo, aquí suponemos que el componente padre pasa una propiedad de <code>size</code> y la utilizamos en el bloque <code>styled-jsx</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const Index = props =&gt; (
  &lt;div&gt;
		&lt;h1&gt;Home page&lt;/h1&gt;

		&lt;style jsx&gt;{`
		  h1 {
		    font-size: ${props.size}rem;
		  }
		`}&lt;/style&gt;
  &lt;/div&gt;
)
</code></pre><figcaption>Componente Index con estilos en el título</figcaption></figure><p>Si desea aplicar un CSS de forma global, no limitado a un componente, añada la palabra clave <code>global</code> a la etiqueta <code>style</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">&lt;style jsx global&gt;{`
body {
  margin: 0;
}
`}&lt;/style&gt;
</code></pre><figcaption>Estilos globales</figcaption></figure><p>Si quieres importar un archivo CSS externo en un componente Next.js, primero tienes que instalar <code>@zeit/next-css</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">npm install @zeit/next-css
</code></pre><figcaption>Paquete para componente externo</figcaption></figure><p>Luego creas un archivo de configuración en la raíz del proyecto, llamado <code>next.config.js</code>, con este contenido:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const withCSS = require('@zeit/next-css')
module.exports = withCSS()
</code></pre><figcaption>Configuración Paquete zeit</figcaption></figure><p>Tras reiniciar la aplicación Next, ya puedes importar CSS como haces normalmente con las bibliotecas o componentes JavaScript:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import '../style.css'
</code></pre><figcaption>Importar CSS debido a zeit</figcaption></figure><p>También puede importar un archivo SASS directamente, utilizando en su lugar la biblioteca <a href="https://github.com/zeit/next-plugins/tree/master/packages/next-sass"><code>@zeit/next-sass</code></a>.</p><!--kg-card-begin: html--><h2 id="tags">Rellenar la etiqueta head con etiquetas personalizadas</h2><!--kg-card-end: html--><p>Desde cualquier componente de página Next.js, puede añadir información a la cabecera de la página.</p><p>Esto es útil cuando:</p><ul><li>Desea personalizar el título de la página</li><li>Desea cambiar una etiqueta <code>meta</code></li></ul><p>¿Cómo puedes hacerlo?</p><p>Dentro de cada componente puedes importar el componente <code>Head</code> desde <code>next/head</code> e incluirlo en la salida JSX de tu componente:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import Head from 'next/head'

const House = props =&gt; (
  &lt;div&gt;
    &lt;Head&gt;
      &lt;title&gt;The page title&lt;/title&gt;
    &lt;/Head&gt;
    {/* Resto de JSX */}
  &lt;/div&gt;
)

export default House
</code></pre><figcaption>Modificar etiqueta Head</figcaption></figure><p>Puedes añadir cualquier etiqueta HTML que quieras que aparezca en la sección <code>&lt;head&gt;</code> de la página.</p><p>Al montar el componente, Next.js se asegurará de que las etiquetas dentro de <code>Head</code> se añadan al encabezado de la página. Lo mismo al desmontar el componente, Next.js se encargará de eliminar esas etiquetas.</p><!--kg-card-begin: html--><h2 id="wrapper">Añadir un componente envoltorio(wrapper component)</h2><!--kg-card-end: html--><p>Todas las páginas de tu sitio tienen más o menos el mismo aspecto. Hay una ventana chrome, una capa base común y sólo quieres cambiar lo que hay dentro.</p><p>Hay una barra de navegación, una barra lateral, y luego el contenido real.</p><p>¿Cómo se construye este sistema en Next.js?</p><p>Hay dos maneras. Una es usando un <a href="https://flaviocopes.com/react-higher-order-components/">Componente de Orden Superior</a><strong>(HOC)</strong>, creando un componente <code>components/Layout.js</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">export default Page =&gt; {
  return () =&gt; (
    &lt;div&gt;
      &lt;nav&gt;
        &lt;ul&gt;....&lt;/ul&gt;
      &lt;/hav&gt;
      &lt;main&gt;
        &lt;Page /&gt;
      &lt;/main&gt;
    &lt;/div&gt;
  )
}
</code></pre><figcaption>componente Page</figcaption></figure><p>Ahí podemos importar componentes separados para el encabezado y/o la barra lateral y también podemos añadir todo el CSS que necesitemos.</p><p>Y lo usas en cada página así:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import withLayout from '../components/Layout.js'

const Page = () =&gt; &lt;p&gt;Here's a page!&lt;/p&gt;

export default withLayout(Page)
</code></pre><figcaption>Componente de Orden Superior</figcaption></figure><p>Pero encontré que esto funciona sólo para casos simples, donde no es necesario llamar a <code>getInitialProps()</code> en una página.</p><p>¿Por qué?</p><p>Porque <code>getInitialProps()</code> sólo se llama en el componente página. Pero si exportamos el componente de orden superior<strong>(HOC)</strong> <code>withLayout()</code> desde una página, <code>Page.getInitialProps()</code> no es llamado. <code>withLayout.getInitialProps()</code> sí lo sería.</p><p>Para evitar complicar innecesariamente nuestra base de código, el enfoque alternativo es utilizar props:</p><pre><code class="language-js">export default props =&gt; (
  &lt;div&gt;
    &lt;nav&gt;
      &lt;ul&gt;....&lt;/ul&gt;
    &lt;/hav&gt;
    &lt;main&gt;
      {props.content}
    &lt;/main&gt;
  &lt;/div&gt;
)
</code></pre><p>y en nuestras páginas ahora lo usamos así:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import Layout from '../components/Layout.js'

const Page = () =&gt; (
  &lt;Layout content={(
    &lt;p&gt;Here's a page!&lt;/p&gt;
  )} /&gt;
)
</code></pre><figcaption>Pasar componente mediante Props</figcaption></figure><p>Este enfoque nos permite utilizar <code>getInitialProps()</code> dentro de nuestro componente de página, con el único inconveniente de tener que escribir el componente JSX dentro del prop <code>content</code>:</p><pre><code class="language-js">import Layout from '../components/Layout.js'

const Page = () =&gt; (
  &lt;Layout content={(
    &lt;p&gt;Here's a page!&lt;/p&gt;
  )} /&gt;
)

Page.getInitialProps = ({ query }) =&gt; {
  //...
}
</code></pre><!--kg-card-begin: html--><h2 id="api-routes">API Routes</h2><!--kg-card-end: html--><p>Además de crear <strong>rutas de página(page routes)</strong>, lo que significa que las páginas se sirven al navegador como páginas web, Next.js puede crear <strong>rutas API(API routes)</strong>.</p><p>Esta es una característica muy interesante porque significa que Next.js puede utilizarse para crear un frontend para datos que son almacenados y recuperados por el propio Next.js, transfiriendo JSON a través de peticiones fetch.</p><p>Las rutas API viven bajo la carpeta <code>/pages/api/</code> y están mapeadas al endpoint <code>/api</code>.</p><p>Esta característica es muy útil a la hora de crear aplicaciones.</p><p>En esas rutas, escribimos código Node.js (en lugar de código React). Es un cambio de paradigma, pasas del frontend al backend, pero muy fluido.</p><p>Imagina que tienes un archivo <code>/pages/api/comments.js</code>, cuyo objetivo es devolver los comentarios de una entrada de blog como JSON.</p><p>Digamos que tienes una lista de comentarios almacenados en un archivo <code>comments.json</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-json">[
  {
    "comment": "First"
  },
  {
    "comment": "Nice post"
  }
]
</code></pre><figcaption>JSON de artículos</figcaption></figure><p>He aquí un ejemplo de código, que devuelve al cliente la lista de comentarios:</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import comments from './comments.json'

export default (req, res) =&gt; {
  res.status(200).json(comments)
}
</code></pre><figcaption>Retornar comentarios en JSON</figcaption></figure><p>Esto escuchará en la URL <code>/api/comments</code> para peticiones GET, puedes intentar llamarlo usando tu navegador:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-07-at-11.14.42.png" class="kg-image" alt="JSON retornado del servidor" width="600" height="400" loading="lazy"><figcaption>JSON retornado del servidor</figcaption></figure><p>Las rutas del API pueden utilizar <strong>enrutamiento dinámico</strong> como las páginas, use la sintaxis <code>[]</code> para crear una ruta de API dinámica, como <code>/pages/api/comments/[id].js</code> que recuperará los comentarios específicos de un <code>id</code> de entrada.</p><p>Dentro de <code>[id].js</code> puedes recuperar el valor del <code>id</code> buscándolo dentro del objeto <code>req.query</code>:</p><pre><code class="language-js">import comments from '../comments.json'

export default (req, res) =&gt; {
  res.status(200).json({ post: req.query.id, comments })
}
</code></pre><p>Aquí puedes ver el código anterior en acción:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-07-at-11.59.53.png" class="kg-image" alt="SId de los artículos" width="600" height="400" loading="lazy"><figcaption>Id de los artículos</figcaption></figure><p>En páginas dinámicas, tendrías que importar <code>useRouter</code> de <code>next/router</code>, luego obtener el objeto router usando <code>const router = useRouter()</code>, luego podríamos obtener el valor <code>id</code> usando <code>router.query.id</code>.</p><p>En el lado del servidor todo es más fácil, ya que la consulta se adjunta al objeto de solicitud.</p><p>Si haces una petición POST, todo funciona de la misma manera - todo va a través de esa exportación por defecto.</p><p>Para separar POST de GET y otros métodos HTTP (PUT, DELETE), busca el valor <code>req.method</code>:</p><pre><code class="language-js">export default (req, res) =&gt; {
  switch (req.method) {
    case 'GET':
      //...
      break
    case 'POST':
      //...
      break
    default:
      res.status(405).end() //Method Not Allowed
      break
  }
}
</code></pre><p>Además de <code>req.query</code> y <code>req.method</code> que ya vimos, tenemos acceso a las cookies haciendo referencia a <code>req.cookies</code>, el cuerpo de la petición en <code>req.body</code>.</p><p>Bajo el capó, todo esto es impulsado por <a href="https://github.com/zeit/micro">Micro</a>, una biblioteca que impulsa microservicios HTTP asíncronos, hecha por el mismo equipo que construyó Next.js.</p><p>Puedes hacer uso de cualquier middleware Micro en nuestras rutas API para añadir más funcionalidad.</p><!--kg-card-begin: html--><h2 id="server">Ejecutar código sólo en el lado del servidor o en el lado del cliente</h2><!--kg-card-end: html--><p>En tus componentes de página, puedes ejecutar código sólo en el lado del servidor o en el lado del cliente, comprobando la propiedad <code>window</code>.</p><p>Esta propiedad sólo existe dentro del navegador, puedes comprobar</p><pre><code class="language-js">if (typeof window === 'undefined') {

}
</code></pre><p>y añadir el código del lado del servidor en ese bloque.</p><p>Del mismo modo, puede ejecutar código del lado del cliente sólo comprobando</p><pre><code class="language-js">if (typeof window !== 'undefined') {

}
</code></pre><p>Consejo JS: Usamos el operador <code>typeof</code> aquí porque no podemos detectar que un valor sea undefined de otra forma. No podemos hacer <code>if (window === undefined)</code> porque obtendríamos un error de ejecución "window is not defined".</p><p>Next.js, como optimización en tiempo de compilación, también elimina de los paquetes el código que utiliza esas comprobaciones. Un paquete del lado del cliente no incluirá el contenido envuelto en un bloque <code>if (typeof window === 'undefined') {}</code>.</p><!--kg-card-begin: html--><h2 id="despliegue">Despliegue de la versión de producción</h2><!--kg-card-end: html--><p>El despliegue de una aplicación siempre se deja para el final en los tutoriales.</p><p>Aquí quiero introducirlo antes, sólo porque es tan fácil desplegar una aplicación Next.js que podemos sumergirnos en ello ahora, y luego pasar a otros temas más complejos más adelante.</p><p>Recuerda que en el capítulo "Cómo instalar Next.js" te dije que añadieras esas 3 líneas a la sección del <code>script package.json</code>:</p><pre><code class="language-json">"scripts": {
  "dev": "next",
  "build": "next build",
  "start": "next start"
}
</code></pre><p>Hasta ahora usábamos <code>npm run dev</code>, para llamar al comando <code>next</code> instalado localmente en <code>node_modules/next/dist/bin/next</code>. Esto inició el servidor de desarrollo, que nos proporcionó <strong>mapas de código fuente(sourcemaps)</strong> y <strong>recarga de código en caliente(hot code reloading)</strong>, dos características muy útiles durante la depuración.</p><p>El mismo comando puede ser invocado para construir el sitio web pasando la bandera build, ejecutando <code>npm run build</code>. A continuación, el mismo comando se puede utilizar para iniciar la aplicación de producción pasando la bandera <code>start</code>, ejecutando <code>npm run start</code>.</p><p>Esos 2 comandos son los que debemos invocar para desplegar con éxito la versión de producción de nuestro sitio localmente. La versión de producción está altamente optimizada y no viene con <strong>mapas de fuentes(sourcemaps)</strong> y otras cosas como la <strong>recarga de código en caliente(hot code reloading)</strong> que no sería beneficioso para nuestros usuarios finales.</p><p>Por lo tanto, vamos a crear un despliegue de producción de nuestra aplicación. Construirlo usando:</p><pre><code class="language-bash">npm run build
</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-13.46.31.png" class="kg-image" alt="Construir paquete de aplicaciones(app bundle)" width="600" height="400" loading="lazy"><figcaption>Construir paquete de aplicaciones(app bundle)</figcaption></figure><p>La salida del comando nos dice que algunas rutas (<code>/</code> y <code>/blog</code> están ahora prerenderizadas como HTML estático, mientras que <code>/blog/[id]</code> será servido por el backend Node.js.</p><p>A continuación, puede ejecutar <code>npm run start</code> para iniciar el servidor de producción localmente:</p><pre><code class="language-bash">npm run start
</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-13.47.01.png" class="kg-image" alt="npm run start" width="600" height="400" loading="lazy"><figcaption>npm run start</figcaption></figure><p>Visitar <a href="http://localhost:3000">http://localhost:3000</a> nos muestra la versión de producción de la aplicación, localmente.</p><!--kg-card-begin: html--><h2 id="now">Despliegue en Now</h2>
<!--kg-card-end: html--><p>En el capítulo anterior desplegamos la aplicación Next.js localmente.</p><p>Cómo la desplegamos en un servidor web real, para que otras personas puedan acceder a ella?</p><p>Una de las formas más sencillas de desplegar una aplicación Next es a través de la plataforma <strong>Now</strong> creada por <a href="https://zeit.co">Zeit</a>, la misma empresa que creó el proyecto Open Source Next.js. Puedes utilizar Now para desplegar aplicaciones Node.js, sitios web estáticos y mucho más.</p><p>Ahora hace que el paso de despliegue y distribución de una aplicación sea muy, muy sencillo y rápido, y además de aplicaciones Node.js, también admite el despliegue de Go, PHP, Python y otros lenguajes.</p><p>Puedes pensar en ella como en la "nube", ya que no sabes realmente dónde se desplegará tu aplicación, pero sabes que tendrás una URL a la que podrás acceder.</p><p>Now es gratuito para empezar a usarlo, con un generoso plan gratuito que actualmente incluye 100 GB de alojamiento, 1000 invocaciones de funciones <a href="https://www.freecodecamp.org/news/serverless/">serverless</a>, 1000 invocaciones al mes, 100 GB de ancho de banda al mes y una ubicación <a href="https://www.freecodecamp.org/news/cdn/">CDN</a>. La <a href="https://zeit.co/pricing">página de precios</a> ayuda a hacerse una idea de los costes si necesita más.</p><p>La mejor manera de empezar a usar Now es utilizando la CLI oficial de Now:</p><pre><code class="language-bash">npm install -g now
</code></pre><p>Una vez que el comando esté disponible, ejecute</p><pre><code class="language-bash">now login
</code></pre><p>La aplicación te pide el correo electrónico.</p><p>Si aún no se ha registrado, cree una cuenta en <a href="https://zeit.co/signup">https://zeit.co/signup</a> antes de continuar y, a continuación, añada su dirección de correo electrónico al cliente CLI.</p><p>Una vez hecho esto, desde la carpeta raíz del proyecto Next.js ejecuta</p><pre><code class="language-bash">now
</code></pre><p>y la aplicación se desplegará instantáneamente en la nube de Now y se le proporcionará la URL única de la aplicación:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-14.21.09.png" class="kg-image" alt="Screen-Shot-2019-11-06-at-14.21.09" width="600" height="400" loading="lazy"></figure><p>Una vez ejecutado el programa <code>now</code>, la aplicación se despliega en una URL aleatoria bajo el dominio <code>now.sh</code>.</p><p>Podemos ver 3 URLs diferentes en la salida dada en la imagen:</p><ul><li><a href="https://firstproject-2pv7khwwr.now.sh">https://firstproject-2pv7khwwr.now.sh</a></li><li><a href="https://firstproject-sepia-ten.now.sh">https://firstproject-sepia-ten.now.sh</a></li><li><a href="https://firstproject.flaviocopes.now.sh">https://firstproject.flaviocopes.now.sh</a></li></ul><p>¿Por qué tantos?<br>La primera es la URL que identifica el despliegue. Cada vez que despleguemos la aplicación, esta URL cambiará.</p><p>Usted puede probar inmediatamente cambiando algo en el código del proyecto y ejecutar de nuevo el comando <code>now</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-15.08.11.png" class="kg-image" alt="Proyecto desplegado en now" width="600" height="400" loading="lazy"><figcaption>Proyecto desplegado en now</figcaption></figure><p>Las otras 2 URLs no cambiarán. La primera es aleatoria, la segunda es el nombre de tu proyecto (que por defecto es la carpeta del proyecto actual, tu nombre de cuenta y luego <code>now.sh</code>.</p><p>Si visitas la URL, verás la aplicación desplegada en producción.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-14.21.43.png" class="kg-image" alt="Aplicación en producción" width="600" height="400" loading="lazy"><figcaption>Aplicación en producción</figcaption></figure><p>Usted puede configurar Now para servir el sitio a su propio dominio personalizado o subdominio, pero no voy a adentrarme en eso ahora.</p><p>El subdominio <code>now.sh</code> es suficiente para nuestras pruebas.</p><!--kg-card-begin: html--><h2 id="paquetes">Análisis de los paquetes de aplicaciones</h2>
<!--kg-card-end: html--><p>Next nos proporciona una forma de analizar los paquetes de código que se generan.</p><p>Abre el archivo package.json de la app y en la sección scripts añade estos 3 nuevos comandos:</p><figure class="kg-card kg-code-card"><pre><code class="language-json">"analyze": "cross-env ANALYZE=true next build",
"analyze:server": "cross-env BUNDLE_ANALYZE=server next build",
"analyze:browser": "cross-env BUNDLE_ANALYZE=browser next build"
</code></pre><figcaption>Comandos para analizar paquetes</figcaption></figure><p>Asi:</p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  "name": "firstproject",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start",
    "analyze": "cross-env ANALYZE=true next build",
    "analyze:server": "cross-env BUNDLE_ANALYZE=server next build",
    "analyze:browser": "cross-env BUNDLE_ANALYZE=browser next build"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "next": "^9.1.2",
    "react": "^16.11.0",
    "react-dom": "^16.11.0"
  }
}
</code></pre><figcaption>package.json</figcaption></figure><p>y luego instale esos 2 paquetes:</p><pre><code class="language-bash">npm install --dev cross-env @next/bundle-analyzer
</code></pre><p>Crea un archivo <code>next.config.js</code> en la raíz del proyecto, con este contenido:</p><pre><code class="language-js">const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true'
})

module.exports = withBundleAnalyzer({})
</code></pre><p>Ahora ejecute el comando</p><pre><code class="language-bash">npm run analyze
</code></pre><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-16.12.40.png" class="kg-image" alt="Screen-Shot-2019-11-06-at-16.12.40" width="600" height="400" loading="lazy"></figure><p>Esto debería abrir 2 páginas en el navegador. Una para los paquetes cliente y otra para los paquetes servidor:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-16.11.14.png" class="kg-image" alt="Análisis de paquetes del cliente" width="600" height="400" loading="lazy"><figcaption>Análisis de paquetes del cliente</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-16.11.23.png" class="kg-image" alt="Análisis de paquetes del servidor" width="600" height="400" loading="lazy"><figcaption>Análisis de paquetes del servidor</figcaption></figure><p>Esto es increíblemente útil. Puedes inspeccionar lo que está ocupando más espacio en los paquetes, y también puedes utilizar la barra lateral para excluir paquetes, para una visualización más fácil de los más pequeños:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-16.14.12.png" class="kg-image" alt="Filtro de resultados de análisis paquetes" width="600" height="400" loading="lazy"><figcaption>Filtro de resultados de análisis paquetes</figcaption></figure><!--kg-card-begin: html--><h2 id="carga">Módulos de carga diferida</h2>
<!--kg-card-end: html--><p>Poder analizar visualmente un bundle es genial, porque podemos optimizar nuestra aplicación de una manera adecuada.</p><p>Digamos que necesitamos cargar la librería Moment en nuestro blog posts. Ejecuta:</p><pre><code class="language-bash">npm install moment
</code></pre><p>para incluirlo en el proyecto.</p><p>Ahora vamos a simular que lo necesitamos en dos rutas diferentes: <code>/blog</code> y <code>/blog/[id]</code>.</p><p>Lo importamos en <code>pages/blog/[id].js</code>:</p><pre><code class="language-jsx">import moment from 'moment'

...

const Post = props =&gt; {
  return (
    &lt;div&gt;
      &lt;h1&gt;{props.post.title}&lt;/h1&gt;
      &lt;p&gt;Published on {moment().format('dddd D MMMM YYYY')}&lt;/p&gt;
      &lt;p&gt;{props.post.content}&lt;/p&gt;
    &lt;/div&gt;
  )
}
</code></pre><p>Sólo estoy añadiendo la fecha de hoy, como ejemplo.</p><p>Esto incluirá Moment.js en el paquete de la página de la entrada del blog, como puedes ver ejecutando <code>npm run analyze</code>:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-17.56.14.png" class="kg-image" alt="Screen-Shot-2019-11-06-at-17.56.14" width="600" height="400" loading="lazy"></figure><p>Observa que ahora tenemos una entrada roja en <code>/blog/[id]</code>, ¡la ruta a la que añadimos Moment.js!</p><p>Ha pasado de ~1kB a 350kB, una gran cosa. Y esto se debe a que la propia biblioteca Moment.js ocupa 349kB.</p><p>La visualización de bundles del cliente nos muestra ahora que el bundle más grande es el de la página, que antes era muy poco. Y el 99% de su código es Moment.js.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-17.55.50.png" class="kg-image" alt="Screen-Shot-2019-11-06-at-17.55.50" width="600" height="400" loading="lazy"></figure><p>Cada vez que cargamos una entrada de blog vamos a tener todo este código transferido al cliente. Lo cual no es lo ideal.</p><p>Una solución sería buscar una biblioteca con un tamaño más pequeño, como Moment.js no es conocido por ser ligero (especialmente fuera de la caja con todos los locales incluidos), pero vamos a suponer por el bien del ejemplo que debemos usarlo.</p><p>Lo que podemos hacer en su lugar es separar todo el código de Moment en un <strong>paquete separado.</strong></p><p>¿Cómo? En lugar de importar Moment a nivel de componente, realizamos una importación asíncrona dentro de <code>getInitialProps</code> y calculamos el valor a enviar al componente.</p><p>Recuerda que no podemos devolver objetos complejos dentro del objeto devuelto por <code>getInitialProps()</code>, así que calculamos la fecha dentro de él:</p><pre><code class="language-js">import posts from '../../posts.json'

const Post = props =&gt; {
  return (
    &lt;div&gt;
      &lt;h1&gt;{props.post.title}&lt;/h1&gt;
      &lt;p&gt;Published on {props.date}&lt;/p&gt;
      &lt;p&gt;{props.post.content}&lt;/p&gt;
    &lt;/div&gt;
  )
}

Post.getInitialProps = async ({ query }) =&gt; {
  const moment = (await import('moment')).default()
  return {
    date: moment.format('dddd D MMMM YYYY'),
    post: posts[query.id]
  }
}

export default Post
</code></pre><p>¿Ves esa llamada especial a <code>.default()</code> después de <code>await import</code>? Es necesaria para hacer referencia a la exportación por defecto en una importación dinámica (véase <a href="https://v8.dev/features/dynamic-import">https://v8.dev/features/dynamic-import</a>)</p><p>Ahora si ejecutamos <code>npm run analyze</code> de nuevo, podemos ver esto:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2019/11/Screen-Shot-2019-11-06-at-18.00.22.png" class="kg-image" alt="Screen-Shot-2019-11-06-at-18.00.22" width="600" height="400" loading="lazy"></figure><p>Nuestro bundle <code>/blog/[id]</code> vuelve a ser muy pequeño, ya que Moment se ha trasladado a su propio archivo bundle, cargado por separado por el navegador.</p><!--kg-card-begin: html--><h2 id="ahora">¿Qué hacer a partir de ahora?</h2>
<!--kg-card-end: html--><p>Hay mucho más que saber sobre Next.js. No he hablado de la gestión de sesiones de usuario con login, serverless, gestión de bases de datos, etc.</p><p>El objetivo de este Manual no es enseñártelo todo, sino introducirte, poco a poco, el potencial de Next.js.</p><p>El siguiente paso que recomiendo es leer detenidamente la <a href="https://nextjs.org/docs">documentación oficial de Next.js</a> para obtener más información sobre todas las características y funcionalidades de las que no he hablado y echar un vistazo a todas las funcionalidades adicionales introducidas por los <a href="https://github.com/zeit/next-plugins">plugins de Next.js</a>, algunas de las cuales son bastante sorprendentes.</p><p>Puedes ponerte en contacto conmigo en Twitter <a href="https://twitter.com/flaviocopes">@flaviocopes.</a></p><p>Visite también mi sitio web, <a href="https://flaviocopes.com/">flaviocopes.com</a>.</p><p><a href="https://flaviocopes.com/page/nextjs-handbook/">Nota: puede descargar una versión PDF / ePub / Mobi de este tutorial para poder leerlo sin conexión.</a></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Aprende Next.js desde Cero ]]>
                </title>
                <description>
                    <![CDATA[ Next.js [https://nextjs.org/] es un framework de JavaScript que nos permite crear fácilmente sitios web de React listos para salir a producción. En este artículo profundizaremos en la documentación oficial, desglosando los conceptos básicos, funciones y particularidades de Next.js. Cubriremos los siguientes temas:  * ¿Por qué usar Next.js?  * ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/aprende-next-js-desde-cero/</link>
                <guid isPermaLink="false">5fede0108c7cd154bb98225a</guid>
                
                    <category>
                        <![CDATA[ NextJS ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kelvin Sanchez ]]>
                </dc:creator>
                <pubDate>Wed, 20 Jan 2021 14:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/01/next-js-logo1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a href="https://nextjs.org/">Next.js</a> es un framework de JavaScript que nos permite crear fácilmente sitios web de React listos para salir a producción.</p><p>En este artículo profundizaremos en la documentación oficial, desglosando los conceptos básicos, funciones y particularidades de Next.js. Cubriremos los siguientes temas:</p><ul><li><a href="#-por-qu-usar-next-js">¿Por qué usar Next.js?</a></li><li><a href="#creando-nuestra-primera-aplicaci-n-con-next-js">Creando nuestra primera aplicación con Next.js</a></li><li><a href="#p-ginas-y-rutas">Páginas y Rutas</a></li><li><a href="#enlazando-p-ginas">Enlazando páginas</a></li><li><a href="#css-en-next-js">CSS en Next.js</a></li><li><a href="#recursos-est-ticos">Recursos estáticos</a></li><li><a href="#ssg-vs-ssr">SSG vs SSR</a></li><li><a href="#rutas-api">Rutas API</a></li><li><a href="#palabras-finales">Palabras finales</a></li></ul><h2 id="-por-qu-usar-next-js">¿Por qué usar Next.js?</h2><p>Next.js ofrece la mejor de las experiencias para el desarrollador, con múltiples funcionalidades incorporadas que garantizan la creación de proyectos sólidos listos para producción, estas son algunas de las razones para su uso:</p><ol><li>Facilidad para aprender y sin complejas configuraciones.</li><li>Optimizado para brindar mejoras de SEO y rendimiento.</li><li>Enrutamiento basado en páginas con soporte de rutas dinámicas.</li><li>Rutas API desplegadas en funciones Serverless.</li><li>Capacidad para generar sitios estáticos (SSG), usar server-side rendering (SSR) o una combinación de ambos según la necesidad de cada página.</li><li>Compatibilidad incorporada con CSS y SASS. Además de soporte para múltiples librerías de CSS en JS.</li></ol><h2 id="creando-nuestra-primera-aplicaci-n-con-next-js">Creando nuestra primera aplicación con Next.js</h2><h3 id="requisitos-previos">Requisitos Previos</h3><p>Antes que nada debes asegurarte de que tienes instalado <strong>Node.js </strong>en tu ordenador (v10.13 en adelante). Para ello, ejecutamos el siguiente comando desde el terminal:</p><pre><code class="language-bash">node -v</code></pre><p>Este comando te devolverá la versión de Node que tienes instalada actualmente.</p><h3 id="usando-create-next-app">Usando create-next-app</h3><p>La manera fácil y recomendada de crear nuevas aplicaciones de Next.JS es usando <code>create-next-app</code>, este se encargará de hacer todas las configuraciones básicas necesarias para empezar nuestro proyecto de inmediato. Ejecuta en tu terminal:</p><pre><code class="language-bash">npx create-next-app &lt;nombre-de-aplicacion&gt;</code></pre><p>Aquí <code>&lt;nombre-de-aplicacion&gt;</code> es el nombre que tendrá la carpeta que alojará los archivos de nuestro proyecto, por lo que puedes darle el nombre de tu preferencia.</p><p>Luego de que se complete la instalación, podemos iniciar el servidor de desarrollo ejecutando los siguientes comandos:</p><pre><code class="language-bash">cd &lt;nombre-de-aplicacion&gt;
npm run dev</code></pre><p>Si visitas <a href="http://localhost:3000/">localhost:3000</a> podrás ver en vivo tu nueva aplicación de Next.js.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2020/12/image-11.png" class="kg-image" alt="image-11" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2020/12/image-11.png 600w, https://www.freecodecamp.org/espanol/news/content/images/2020/12/image-11.png 968w" sizes="(min-width: 720px) 720px" width="968" height="744" loading="lazy"></figure><h3 id="manualmente">Manualmente</h3><p>También puedes utilizar Next.js instalando manualmente los paquetes: <code>next</code>, <code>react</code> y <code>react-dom</code>:</p><pre><code class="language-bash">npm install next react react-dom</code></pre><p>Luego abrimos el archivo <code>package.json</code> y añadimos los siguientes <code>scripts</code>: </p><pre><code class="language-json">"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start"
}</code></pre><ul><li><code>dev</code> inicia Next.js en modo desarrollo.</li><li><code>start</code> inicia Next.js en modo producción.</li><li><code>build</code> construye tu aplicación de Next.js para producción.</li></ul><h2 id="p-ginas-y-rutas">Páginas y Rutas</h2><p>Una de las particularidades de Next.js es que esta construido alrededor del concepto de páginas.</p><p>Una página es un componente de React exportado desde la carpeta <code>pages</code>.</p><p>Las páginas están asociadas con una ruta basada en el nombre del archivo. Por ejemplo <code>pages/perfil.js</code> resultará en la ruta <code>/perfil</code>. </p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">export default function Perfil() {
  return &lt;div&gt;¡Bienvenido a mi perfil!&lt;/div&gt;;
}</code></pre><figcaption>pages/perfil.js</figcaption></figure><p>Prueba el código anterior por tu cuenta y visita <a href="http://localhost:3000/perfil">localhost:3000/perfil</a> para ver los resultados.</p><h3 id="rutas-index">Rutas Index</h3><p>Los archivos con nombre <code>index</code> dirigen hacia la raíz del directorio que lo contiene.</p><ul><li><code>pages<em>/</em>index.js</code> → <code>/</code></li><li><code>pages/blog/index.js</code> → <code>/blog</code></li></ul><h3 id="rutas-anidadas">Rutas Anidadas</h3><p>Supongamos que queremos acceder a la siguiente ruta: <code>/blog/post/:id</code></p><p>Necesitaremos anidar las carpetas de la siguiente manera:</p><pre><code class="language-bash">|- pages
  |- index.js
  |- blog
    |- post
      |- [id].js # id dinámico para cada post</code></pre><h3 id="p-ginas-con-rutas-din-micas">Páginas con Rutas Dinámicas</h3><p>También podemos utilizar rutas dinámicas si agregamos corchetes al nombre del archivo. Por ejemplo, si creamos un archivo llamado <code>pages/post/[id].js</code> podremos acceder a el en las rutas <code>post/1</code>, <code>post/2</code>, y así sucesivamente.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">import { useRouter } from "next/router";

export default function Post() {
  const router = useRouter();
  const { id } = router.query;

  return &lt;p&gt;Post: {id}&lt;/p&gt;;
}</code></pre><figcaption>pages/post/[id].js</figcaption></figure><p>Como puedes observar, en el código anterior utilizamos el hook <code>useRouter</code> de Next.js para acceder al objeto <code>router</code>, dicho objeto contiene propiedades muy útiles, las partes dinámicas de cada ruta se almacenan en <code>router.query</code>.</p><h2 id="enlazando-p-ginas">Enlazando páginas</h2><p>Para obtener una navegación fluida entre las páginas de nuestra aplicación, necesitamos importar el componente <code>Link</code> y usarlo de la siguiente manera:</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">import Link from "next/link";

export default function Home() {
  return (
    &lt;ul&gt;
      &lt;li&gt;
        &lt;Link href="/"&gt;
          &lt;a&gt;Home&lt;/a&gt;
        &lt;/Link&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;Link href="/perfil"&gt;
          &lt;a&gt;Mi perfil&lt;/a&gt;
        &lt;/Link&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;Link href="/blog/post/hola-mundo"&gt;
          &lt;a&gt;Post&lt;/a&gt;
        &lt;/Link&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  );
}</code></pre><figcaption>pages/index.js</figcaption></figure><p>En el ejemplo anterior podemos observar que hay múltiples enlaces, cada uno cuenta con un componente <code>Link</code> que recibe una propiedad <code>href</code> indicando la ruta a la que dirige. <code>Link</code> envuelve un elemento Anchor <code>a</code> que contiene el texto de nuestro enlace.</p><h3 id="enlazando-rutas-din-micas">Enlazando Rutas Dinámicas</h3><p>También puedes utilizar interpolación para crear la ruta, lo que resulta útil para los segmentos de ruta dinámicos. Por ejemplo, para mostrar una lista de posts que se han pasado al componente como propiedad:</p><pre><code class="language-jsx">import Link from "next/link";

export default function Posts({ posts }) {
  return (
    &lt;ul&gt;
      {posts.map((post) =&gt; (
        &lt;li key={post.id}&gt;
          &lt;Link href={`/blog/post/${post.id}`}&gt;
            &lt;a&gt;{post.titulo}&lt;/a&gt;
          &lt;/Link&gt;
        &lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
}</code></pre><p>O usando un objeto URL:</p><pre><code class="language-jsx">import Link from "next/link";

export default function Posts({ posts }) {
  return (
    &lt;ul&gt;
      {posts.map((post) =&gt; (
        &lt;li key={post.id}&gt;
          &lt;Link
            href={{
              pathname: "/blog/post/[id]",
              query: { id: post.id },
            }}
          &gt;
            &lt;a&gt;{post.titulo}&lt;/a&gt;
          &lt;/Link&gt;
        &lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
}</code></pre><h2 id="css-en-next-js">CSS en Next.js</h2><p>Existen muchas formas de darle estilo a tu aplicación en Next.js, puedes importar archivos de hojas de estilo directamente gracias a la compatibilidad con los Módulos de CSS. Para ello el archivo debe nombrarse de la siguiente manera: <code>[nombre].module.css</code>.</p><p>Los Módulos de CSS mantienen un ámbito local creando clases únicas automáticamente, por lo que te permite usar los mismos nombres de clases en diferentes archivos sin que tengas que preocuparte por colisiones.</p><p>Por ejemplo, para crear un componente botón reusable, primero creamos <code>componentes/Boton.module.css</code> con el siguiente contenido:</p><figure class="kg-card kg-code-card"><pre><code class="language-css">.peligro {
  color: white;
  background-color: red;
}</code></pre><figcaption>componentes/Boton.module.css</figcaption></figure><p>Y un archivo <code>componentes/Boton.js</code> donde importar y usar el módulo CSS antes creado.</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">import estilos from "./Boton.module.css";

export default function Boton() {
  return (
    &lt;button type="button" className={estilos.peligro}&gt;
      Borrar
    &lt;/button&gt;
  );
}</code></pre><figcaption>componentes/Boton.js</figcaption></figure><blockquote>Nota: La clase <code>peligro</code> es una propiedad del objeto <code>estilos</code> importado.</blockquote><p>Así de fácil es usar los Módulos de CSS en Next.js, recuerda que también tenemos más opciones de estilo a nuestra disposición, tales como <a href="https://nextjs.org/docs/basic-features/built-in-css-support#sass-support">Sass</a>, <a href="https://nextjs.org/docs/basic-features/built-in-css-support#less-and-stylus-support">Less</a> o <a href="https://nextjs.org/docs/basic-features/built-in-css-support#css-in-js">CSS en JavaScript</a>. </p><h3 id="recursos-est-ticos">Recursos estáticos</h3><p>La carpeta <code>public</code> es utilizada en Next.js para servir todos nuestros recursos estáticos (imágenes, iconos, robots, entre otros). Puedes importar archivos dentro de la carpeta <code>public</code> &nbsp;usando (<code>/</code>) como URL base.</p><p>Por ejemplo, para acceder a una imagen guardada en <code>public/hero.jpg</code> escribimos un código como el siguiente:</p><figure class="kg-card kg-code-card"><pre><code class="language-jsx">export default function Home() {
  return (
    &lt;div&gt;
      &lt;img src="/hero.jpg" /&gt;
    &lt;/div&gt;
  );
}</code></pre><figcaption>pages/index.js</figcaption></figure><blockquote>Nota: No cambies el nombre de la carpeta <code>public</code> por ningún otro, es la única que puede servir recursos estáticos.</blockquote><h2 id="ssg-vs-ssr">SSG vs SSR</h2><h3 id="pre-renderizado">Pre-renderizado</h3><p>Next.js pre-renderiza cada página por defecto. Generando el HTML por adelantado en lugar de dejarle todo el trabajo al JavaScript del cliente. Esto se traduce en importantes mejoras de rendimiento y SEO.</p><p>Cada HTML generado se asocia con un mínimo de código de JavaScript requerido para esa página. Cuando una página es cargada por el navegador, su código JavaScript se ejecuta y hace la página plenamente interactiva. Este proceso es llamado hidratación.</p><h3 id="tipos-de-pre-renderizado">Tipos de Pre-renderizado</h3><p>Existen dos formas de pre-renderizado en Next.js:<strong> Static Site Generation</strong> y<strong> Server-side Rendering</strong>. La diferencia principal radica en <strong>cuando</strong> se genera el HTML para la página.</p><ul><li><strong>SSG</strong> (Static Site Generation): El HTML se genera <em>antes</em> de cada petición, como al momento de crear la build.</li><li><strong>SSR</strong> (Server-side Rendering): El HTML se genera en el servidor <em>durante</em> cada petición.</li></ul><h3 id="static-site-generation">Static Site Generation</h3><p>Si nuestra página no requiere datos de una fuente externa, Next.js se encargará de generarla de forma estática al crear la build. Por ejemplo:</p><pre><code class="language-jsx">export default function Perfil() {
  return &lt;div&gt;Perfil&lt;/div&gt;;
}</code></pre><p>En cambio, si el contenido o rutas de la página dependen de una fuente externa, necesitaremos usar dos funciones especiales de Next.js: <code>getStaticProps</code> y <code>getStaticPaths</code>.</p><p><strong>Ejemplo 1:</strong> Digamos que tu página necesita una lista de posts publicados en tu blog desde un CMS.</p><pre><code class="language-jsx">// TODO: Hacer fetch a los `posts` antes de que se pre-renderice la página
export default function Blog({ posts }) {
  return (
    &lt;ul&gt;
      {posts.map((post) =&gt; (
        &lt;li key={post.id}&gt;{post.titulo}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
}</code></pre><p>En el mismo archivo tenemos que exportar la función asíncrona <code>getStaticProps</code>, esta función es llamada al momento de crear la build y te permite pasar los datos recopilados a la página en forma de <code>props</code>.</p><pre><code class="language-jsx">export async function getStaticProps() {
  // Hacer fetch al endpoint que contiene los `posts`
  const res = await fetch("https://.../posts");
  const posts = await res.json();

  return { props: { posts } };
}

export default function Blog({ posts }) {
  // Renderizar posts...
}</code></pre><p><strong>Ejemplo 2: </strong>Queremos pre-renderizar posts individuales usando rutas dinámicas.</p><p>Empezamos creando un archivo con ruta dinámica llamado <code>pages/posts/[id].js</code>, este nos permitirá acceder a nuestros posts según su <code>id</code>, con enlaces como: <code>/posts/1</code>, <code>/posts/2</code>, etc.</p><pre><code class="language-jsx">export default function Post({ post }) {
  return (
    &lt;div&gt;
      &lt;h1&gt;{post.titulo}&lt;/h1&gt;
      &lt;p&gt;{post.contenido}&lt;/p&gt;
    &lt;/div&gt;
  );
}</code></pre><p>Podemos indicar a Next.js las rutas dinámicas que queremos pre-renderizar usando la función <code>getStaticPaths</code>.</p><pre><code class="language-jsx">export async function getStaticPaths() {
  // Hacer fetch al endpoint que contiene los `posts`
  const res = await fetch("https://.../posts");
  const posts = await res.json();

  // Obtener rutas a pre-renderizar basado en el `id` de los posts
  const rutas = posts.map((post) =&gt; `/posts/${post.id}`);

  return { paths: rutas, fallback: false };
}
</code></pre><blockquote>Nota: <code>{ fallback: false }</code> hace que las rutas no incluidas devuelvan una página 404.</blockquote><p>Finalmente, utilizamos <code>getStaticProps</code> para conseguir los datos del post según el <code>id</code> proporcionado en el objeto <code>params</code>.</p><pre><code class="language-jsx">export async function getStaticPaths() {
  // ...
}

export async function getStaticProps({ params }) {
  // params contiene el `id` del post.
  const res = await fetch(`https://.../posts/${params.id}`);
  const post = await res.json();

  // Pasar datos del post hacia la página en forma de props
  return { props: { post } };
}

export default function Post({ post }) {
  // Renderizar post...
}</code></pre><h3 id="server-side-rendering">Server-side Rendering</h3><p>Muchas veces los datos de nuestra página deben ser constantemente actualizados o tal vez necesitemos interactuar con una API haciendo consultas variadas y complejas. Para casos como estos, Next.js nos permite usar <strong>Server-side Rendering</strong> (SSR) en nuestras aplicaciones de React.</p><p>Cuando una página utiliza Server-side rendering, el HTML de la misma se genera en el servidor durante cada petición. Para ello, necesitamos exportar la función asíncrona <code>getServerSideProps</code>, la cual recopila los datos y los pasa a la página.</p><pre><code class="language-jsx">// Esta función es llamada durante cada petición
export async function getServerSideProps() {
  // Recopilar datos desde una API externa
  const res = await fetch(`https://.../datos`);
  const datos = await res.json();

  // Pasar datos hacia la pagina en forma de props
  return { props: { datos } };
}

export default function Pagina({ datos }) {
  // Renderizar datos...
}</code></pre><p>Como puedes observar, <code>getServerSideProps</code> y <code>getStaticProp</code> cuentan con una sintaxis y funcionamiento similar, pero se diferencian principalmente por el momento en que son ejecutadas.</p><h2 id="rutas-api">Rutas API</h2><p>Next.js provee una solución para construir APIs fácilmente en un entorno Serverless (Sin servidor), por lo que no tendremos que preocuparnos de pagar alojamiento de servidores para el back-end de nuestra aplicación.</p><p>Todos los archivos dentro de la carpeta <code>pages/api</code> serán tratados como endpoints de nuestra API en lugar de páginas. </p><p>Por ejemplo, si creamos un archivo <code>pages/api/hola.js</code> podremos acceder al mismo en la ruta: <code>/api/hola</code> y nos devolverá como respuesta un objeto json.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">export default function manejador(req, res) {
  res.status(200).json({ texto: "Hola" });
}</code></pre><figcaption>pages/api/hola.js</figcaption></figure><p>Como puedes observar, para que este archivo funcione correctamente como API endpoint es necesario exportar una función manejador (handler) con los parámetros <code>req</code> y <code>res</code>.</p><p>Si queremos tener acceso a los diferentes métodos HTTP en nuestro manejador podemos usar <code>req.method</code> dentro del mismo, por ejemplo:</p><pre><code class="language-js">export default function manejador(req, res) {
  switch (req.method) {
    case "GET":
      // Nuestra lógica de código para el método GET...
      break;
    case "PATCH":
      // Nuestra lógica de código para el método PATCH...
      break;
    case "DELETE":
      // Nuestra lógica de código para el método DELETE...
      break;
    default:
      res.status(405).json({
        mensaje: `El método HTTP ${req.method} no esta disponible en esta ruta`,
      });
      break;
  }
}</code></pre><p>Si ya estás familiarizado con Express.js probablemente encuentres muchas similitudes en cuanto a sintaxis.</p><h2 id="palabras-finales">Palabras finales</h2><p>En este artículo pudimos explorar algunas de las funcionalidades principales de Next.js, mostrando una visión general de sus características, herramientas y ventajas tanto para el desarrollador como para el usuario final.</p><p>Espero que esta lectura haya sido de tu agrado y te animes a probar este framework por tu cuenta. Pienso más adelante crear contenido de Next.js tocando temas más específicos, tales como: middlewares, opciones de despliegues, enrutamiento internacionalizado (<strong>i18n</strong>), entres otros. </p><hr><p>¿Tienes alguna duda o quieres mantenerte al día con mis publicaciones? <a href="https://twitter.com/kelvin_sanchez">Sígueme en Twitter.</a></p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
