Next JS

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.

Nos permite crear páginas estáticas a partir de las páginas generadas dinámicamente por React.

Instalación y ejecución

npx create-next-app .

Para ejecutar el proyecto:

npm run dev

Generación de los HTML

NextJS utiliza por defecto un módulo llamado next/image para exportar las imágenes. Este módulo necesita ser configurado en el fichero next.config.js. Si queremos evitarnos esta configuración, podemos importar las imagenes directamente con import. Así lo haremos en esta guía.

Ejecutamos el siguiente comando para hacer una compilación tradicional como la que hacíamos en React:

npm run build

Finalmente, este comando genera los HTML a partir del build que hemos hecho:

next export

Ejecutar ambos comandos, consecutivamente, desde npm

Para poder ejecutar el siguiente comando directamente desde npm, añadiremos un script al package.json para facilitar la generación de los html:

"scripts": {
    ...
    "export": "next build && next export",
  },
npm run export

Enlaces y Páginas

Los componentes vinculados a urls (páginas) deben estar dentro de la carpeta app. En nextjs la carpeta app se utiliza para el enrutamiento.

En general, tendremos una carpeta por cada página. Para que se genere una url correspondiente al nombre de la carpeta, dicha carpeta debe contener un documento llamado page, que contendrá el componente que queremos cargar.

Para cargar la home, usaremos un documento llamdo page.js que estará en la raíz de la carpeta app.

Para cargar estas páginas sin refrescar la página actual, usaremos el módulo Link:

import Link from 'next/link';

export default () => (
  <div>
    <h1>Home</h1>
    <nav>
      <Link href="/page2">Help page</Link>
    </nav>
  </div>
);

Para cargar dinámicamente una url, sin pulsar sobre un botón de Link.

import { useRouter } from 'next/router';
...
const router = useRouter()
...
router.push('/dashboard');

usePathname

Este hook permite recuperar la url en la que estamos. Con ello, podremos, por ejemplo, resaltar el link correspondiente a la página en la que estamos. Podemos ver un ejemplo aquí:

const name = usePathname();
...
<Link className={name == '/suplementos.html' && 'active'} href="/suplementos.html">Suplementos</Link>

Rutas funcionando en producción

Cuando subamos la aplicación de nextJS a internet es recomendable utilizar el siguiente fichero de .htaccess para que las rutas que no utilizan extensión .html carguen documentos .html:

# Esta configuración hace que aunque no ponga la extension .html, cargue el html
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*)$ $1.html [L]

use client

Los componente que tengan Javascript y sus padres deberán tener la directiva «use client» al principio. Si no lo hacemos, recibiremos un error de este tipo:

Error: ... only works in Client Components. Add the "use client" directive at the top of the file to use it.

Cargar una imagen

La dejaremos en una carpeta diferente de la carpeta pages (por ejemplo, en la carpeta public), la importaremos en nuestro componente y la usaremos usando .src:

<img src={e.src} />

/next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    unoptimized: true,
  },
};

export default nextConfig;

Configurar el proyecto de NextJS para poder usar styled-components

/src/app/registry.tsx

"use client";

import React, { useState } from "react";
import { useServerInsertedHTML } from "next/navigation";
import { ServerStyleSheet, StyleSheetManager } from "styled-components";

export default function StyledComponentsRegistry({
  children,
}: {
  children: React.ReactNode;
}) {
  // Only create stylesheet once with lazy initial state
  // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
  const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet());

  useServerInsertedHTML(() => {
    const styles = styledComponentsStyleSheet.getStyleElement();
    styledComponentsStyleSheet.instance.clearTag();
    return <>{styles}</>;
  });

  if (typeof window !== "undefined") return <>{children}</>;

  return (
    <StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
      {children}
    </StyleSheetManager>
  );
}

/src/app/layout.js

import "./globals.css";
import Layout from "../common/components/Layout/Layout";
import StyledComponentsRegistry from "../app/registry";

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <StyledComponentsRegistry>
          <Layout>{children}</Layout>
        </StyledComponentsRegistry>
      </body>
    </html>
  );
}

/jsconfig.json

{
  "compilerOptions": {
    "jsx": "preserve",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Exportar a producción

/next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: "export",
  basePath: "/ruta-final",
};

export default nextConfig;

Cambiar dinámicamente el title de la página en la que estamos

Necesitaremos instalar react-helmet. Esta librería permite cargar en el head de la página cualquier tipo de etiqueta.

npm i react-helmet

Para usarla, debemos cargar el módulo correspondiente en cada página:

import Helmet from 'react-helmet';

export default () => (
    <>
        <Helmet>
            <title>Sillas de bebé para coche</title>
        </Helmet>

Cargar Google Analytics en NextJS

npm i react-ga
/application/tracking.js
import { useEffect } from 'react';
import ReactGA from 'react-ga';
import { useRouter } from 'next/router';

export default () => {
    const { pathname } = useRouter();

    useEffect(() => {
        ReactGA.initialize('UA-19791121-2');
    }, []);

    useEffect(() => {
        ReactGA.pageview(pathname);
    }, [pathname]);

    return null;
};

Debemos cargar este componente en _app.js:

/pages/_apps.js
import { GlobalStyle } from '../application/styled';
import NavBar from '../components/navbar';
import Tracking from '../application/tracking';

function MyApp({ Component, pageProps }) {
  return <>
    <GlobalStyle />
    <Tracking />
    <NavBar />
    <Component {...pageProps} />
  </>
}

export default MyApp

Problema con el underscore en github

Github no accede correctamente a carpetas que empiezan por guión bajo (_). Para evitar este problema, debemos añadir un fichero llamado .nojekyll dentro de la carpeta donde estamos compilando (dist o docs según el caso). Esto es necesario en nextJS ya que nextJS utiliza una carpeta llamada _next.

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.