Next JS

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

Añadiremos un script al package.json para facilitar la generación de los html:

"scripts": {
    ...
    "export": "next export",
  },

Para generar los HTML ejecutaremos:

npm run build
npm run export

Links

Cada carpeta ubicada dentro de la carpeta /pages corresonderá a una url. Por ejemplo:

/pages/page2/index.js

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');

Añadir loaders a NextJS

npm i next-compose-plugins
npm i next-fonts
npm i next-images
next.config.js
const withPlugins = require('next-compose-plugins');
const withFonts = require('next-fonts');
const withImages = require('next-images');

const plugins = config => withPlugins([withFonts, withImages], config);

module.exports = plugins({
    fileExtensions: ["jpg", "jpeg", "png", "gif"],  // withImages
    enableSvg: true,                                // withFonts
    webpack(config) {
        return config;
    }
});

Problema con la carga de fuentes en producción

Para que las tipografías carguen correctamente en producción, será necesario especificar la ruta absoluta de su ubicación.

styled.js
import getConfig from 'next/config'
const { publicRuntimeConfig } = getConfig();
const fontPrefix = publicRuntimeConfig.basePath ? publicRuntimeConfig.basePath + '/' : '';

export const GlobalStyle = createGlobalStyle`
    @font-face {
        font-family: font ;
        src: url(${fontPrefix}${font});
    }
`;
next.config.js
const isDevelopment = process.env.NODE_ENV === 'development';

const basePath = isDevelopment ? '' : '/ruta-en-produccion';

const plugins = config => withPlugins([withFonts, withImages], {
    ...config,
    publicRuntimeConfig: {
        basePath,
    },
    basePath,
});

Configurar el proyecto de NextJS para poder usar styled-components

Vamos a indicar a next.js que los ficheros terminados en page.js contienen páginas. De esta forma next.js no va a intentar compilar como página otros ficheros que no sea páginas, como por ejemplo, archivos de estilos.

module.exports = plugins({
    pageExtensions: ['page.js'],
    ...
});

Tras poner esta regla, tendremos que renombrar las páginas, _app.page.js, _document.page.js….

Next JS 1

Los ficheros que comienzan por barra baja ( _ ), son ficheros que nextJS reconoce y carga automáticamente. Esos ficheros con underscore dan problemas en github.com, para evitarlos, puedes leer esto.

./pages/_document.page.js
import Document from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export const extractStyles = async (ctx) => {
  const sheet = new ServerStyleSheet();
  const originalRenderPage = ctx.renderPage;

  try {
    ctx.renderPage = () => originalRenderPage({
      enhanceApp: App => props => sheet.collectStyles(<App {...props} />),
    });

    const initialProps = await Document.getInitialProps(ctx);
    return {
      ...initialProps,
      styles: (
        <>
          {initialProps.styles}
          {sheet.getStyleElement()}
        </>
      ),
    };
  } finally {
    sheet.seal();
  }
};
/application/render.js
import Document from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export const extractStyles = async (ctx) => {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
        ctx.renderPage = () => originalRenderPage({
            enhanceApp: App => props => sheet.collectStyles(<App {...props} />),
        });

        const initialProps = await Document.getInitialProps(ctx);
        return {
            ...initialProps,
            styles: (
                <>
                    {initialProps.styles}
                    {sheet.getStyleElement()}
                </>
            ),
        };
    } finally {
        sheet.seal();
    }
};

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.

← Firebase (versión 9)
Extras de React →

Aviso Legal | Política de privacidad