
Como sabes, no puedes llegar muy lejos en algunas repeticiones solo, por lo que debes profundizar en cualquier tecnología para aprender a escribir algo que valga la pena. Este artículo analiza los detalles de Gatsby.js , cuyo conocimiento le permitirá crear y mantener sitios web y blogs complejos.
Artículo anterior sobre cómo crear y publicar un blog personal utilizando JAM-stack
Temas discutidos a continuación:
Preparación
Instalar Gatsby en PCyarn global add gatsby-cli
Clonando un Proyecto Mínimo npx gatsby new gatsby-tutorial https://github.com/gatsbyjs/gatsby-starter-hello-world cd gatsby-tutorial
Inicialización de repositorio git init git add . git commit -m "init commit"
Control de salud yarn start
Si no hay errores en la consola y en el navegador a lo largo de la ruta http: // localhost: 8000, verá "¡Hola, mundo!" significa que todo funciona correctamente. Puede intentar cambiar el contenido del archivo /src/pages/index.js para verificar la recarga en caliente.
Estructura de la página y enrutamiento
Para crear una página en Gatsby, simplemente coloque el nuevo archivo en la carpeta / src / pages y se compilará en una página HTML separada. Es importante tener en cuenta que la ruta a esta página corresponderá a la ruta real con el nombre . Por ejemplo, agregue algunas páginas más:
src └── pages ├── about.js ├── index.js └── tutorial ├── part-four.js ├── part-one.js ├── part-three.js ├── part-two.js └── part-zero.js
El contenido aún no es importante, por lo que cualquier texto puede usarse para distinguir entre páginas.
import React from "react"; export default () => <div>Welcome to tutorial/part-one</div>;
Comprobar en el navegador:
De esta manera, al estructurar archivos, puede resolver inmediatamente los problemas de enrutamiento.
También hay una API createPage especial con la que puede controlar de manera más flexible las rutas y los nombres de las páginas, pero para trabajar con ella necesitamos comprender el funcionamiento de los datos en Gatsby, por lo que lo consideraremos un poco más adelante en el artículo.
Combina las páginas creadas usando los enlaces, para esto usamos el componente <Link />
del paquete Gatsby, que fue creado específicamente para la navegación interna. Para todos los enlaces externos, use la etiqueta <a>
normal.
/src/pages/index.js
import React from "react"; import { Link } from "gatsby"; export default () => ( <div> <ul> <li> <Link to="/about">about</Link> </li> <li> <Link to="/tutorial/part-zero">Part #0</Link> </li> <li> <Link to="/tutorial/part-one">Part #1</Link> </li> <li> <Link to="/tutorial/part-two">Part #2</Link> </li> <li> <Link to="/tutorial/part-three">Part #3</Link> </li> <li> <Link to="/tutorial/part-four">Part #4</Link> </li> </ul> </div> );
<Link>
debajo del capó tiene un mecanismo muy complicado para optimizar la carga de la página y, por lo tanto, se utiliza en lugar de <a>
para navegar por el sitio. Más detalles se pueden encontrar aquí .

Se crean páginas, se agregan enlaces, resulta que la navegación ha finalizado.
Componentes, plantillas y su interacción
Como sabes, en cualquier proyecto siempre hay elementos repetitivos, para sitios web es un encabezado, pie de página, barra de navegación. Además, las páginas, independientemente del contenido, se crean de acuerdo con una determinada estructura, y dado que Gatsby es un compilador de React , se utiliza el mismo enfoque de componentes para resolver estos problemas.
Cree los componentes para el encabezado y el panel de navegación:
/src/components/header.js
import React from "react"; import { Link } from "gatsby"; /** * * , React-. * , * " ". * "" GraphQL gatsby- */ import logoSrc from "../images/logo.png"; export default () => ( <header> <Link to="/"> <img src={logoSrc} alt="logo" width="60px" height="60px" /> </Link> That is header </header> );
/src/components/sidebar.js
import React from "react"; import { Link } from "gatsby"; export default () => ( <div> <ul> <li> <Link to="/about">about</Link> </li> <li> <Link to="/tutorial/part-zero">Part #0</Link> </li> <li> <Link to="/tutorial/part-one">Part #1</Link> </li> <li> <Link to="/tutorial/part-two">Part #2</Link> </li> <li> <Link to="/tutorial/part-three">Part #3</Link> </li> <li> <Link to="/tutorial/part-four">Part #4</Link> </li> </ul> </div> );
y agregarlos a /src/pages/index.js
import React from "react"; import Header from "../components/header"; import Sidebar from "../components/sidebar"; export default () => ( <div> <Header /> <Sidebar /> <h1>Index page</h1> </div> );
Comprobamos:

Todo funciona, pero necesitamos importar el encabezado y la barra lateral en cada página por separado, lo que no es muy conveniente, y para resolver este problema es suficiente crear un componente de diseño y envolver cada página con él.
Diseño Gatsby == contenedor de reacción
sí, no es igualdad estricta, porque es "casi" lo mismo
/src/components/layout.js
import React from "react"; import Header from "./header"; import Sidebar from "./sidebar"; export default ({ children }) => ( <> <Header /> <div style={{ margin: `0 auto`, maxWidth: 650, backgroundColor: `#eeeeee` }} > <Sidebar /> {children} </div> </> );
/src/pages/index.js (y todas las demás páginas)
import React from "react"; import Layout from "../components/layout"; export default () => ( <Layout> <h1>Index page</h1> </Layout> );
Hecho, mira el navegador:

¿Por qué el proyecto contiene todos los nombres de archivo con una letra minúscula? Para empezar, determinemos que el espacio de nombres para React proviene del hecho de que "cada archivo es una clase, y la clase siempre está en mayúscula". En Gatsby, los archivos aún contienen clases, pero hay un "pero": "cada archivo es una página potencial y su nombre es la URL de esta página". La comunidad llegó a la conclusión de que enlaces como http://domain.com/User/Settings
no son comme-il-faut y kebab-case aprobado para nombres de archivos.
Estructura de archivo src ├── components │ ├── header.js │ ├── layout.js │ └── sidebar.js ├── images │ └── logo.png └── pages ├── about.js ├── index.js └── tutorial ├── part-eight.js ├── part-five.js ├── part-four.js ├── part-one.js ├── part-seven.js ├── part-six.js ├── part-three.js ├── part-two.js └── part-zero.js
Trabajar con datos
Ahora que la estructura del sitio está lista, puede continuar con el llenado de contenido. El enfoque clásico de "código duro" no se adaptaba a los creadores de la pila JAM, así como al "contenido de procesamiento de solicitudes AJAX" y, por lo tanto, sugirieron llenar los sitios con contenido en tiempo de compilación. En el caso de Gatsby , GraphQL es responsable de esto, lo que le permite trabajar convenientemente con flujos de datos de cualquier fuente.
Es imposible hablar de GraphQL en pocas palabras, por lo que es recomendable estudiarlo usted mismo o esperar mi próximo artículo. Puede leer más sobre trabajar con GraphQL aquí .
Para trabajar con GraphQL , desde la segunda versión, el paquete gatsby
tiene un componente gatsby
que se puede usar tanto en páginas como en componentes simples, y esta es su principal diferencia con respecto a su consulta de página predecesora. Hasta ahora, nuestro sitio no está conectado a ninguna fuente de datos, así que tratemos de mostrar los metadatos de la página, por ejemplo, y luego pasemos a cosas más complejas.
Para crear una query
debe abrir http: // localhost: 8000 / ___ graphql , y usar la barra lateral con la documentación para encontrar los datos disponibles sobre el sitio, y no se olvide de la finalización automática.

/src/components/sidebar.js
import React from "react"; import { Link, StaticQuery, graphql } from "gatsby"; export default () => ( <StaticQuery query={graphql` { allSitePage { edges { node { id path } } } } `} render={({ allSitePage: { edges } }) => ( <ul> {edges.map(({ node: { id, path } }) => ( <li key={id}> <Link to={path}>{id}</Link> </li> ))} </ul> )} /> );
Ahora, mediante la query
obtenemos datos sobre las páginas que mostramos en el panel de navegación, y no tenemos que preocuparnos por el hecho de que el enlace no coincidirá con el nombre, porque todos los datos se recopilan automáticamente.

De hecho, estos son todos los datos que pueden estar en nuestro sitio sin usar complementos de terceros y sin el viejo "código duro", así que pasamos al siguiente tema de nuestro artículo: los complementos.
Complementos
En esencia, Gatsby es un compilador con un montón de cosas, que son complementos. Utilizándolos, puede personalizar el procesamiento de ciertos archivos, tipos de datos y varios formatos.
Cree el archivo /gatsby-config.js en el nivel raíz de la aplicación. que es responsable de la configuración del compilador en su conjunto e intenta configurar el primer complemento para trabajar con archivos:
Instalación del complemento:
yarn add gatsby-source-filesystem
Configuración en el archivo /gatsby-config.js:
module.exports = { plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/`, } } ], }
Más detalles sobre el archivo de arriba /** * gatsby-config.js * JS * */ module.exports = { /** * 'plugins' pipeline * , */ plugins: [ /** * , * */ `gatsby-example-plugin`, { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/`, } } ], }
¿Recuerdas que hablamos sobre la importación de imágenes "correctas" en Gatsby ?
/src/components/header.js
import React from "react"; import { Link, StaticQuery, graphql } from "gatsby"; export default () => ( <StaticQuery query={graphql` { allFile(filter: { name: { eq: "logo" } }) { edges { node { publicURL } } } } `} render={({ allFile: { edges: [ { node: { publicURL } } ] } }) => ( <header> <Link to="/"> <img src={publicURL} alt="logo" width="60px" height="60px" /> </Link> That is header </header> )} /> );
Nada ha cambiado en el sitio, pero ahora la imagen se sustituye con GraphQL, en lugar de una simple importación de paquete web. A primera vista, puede parecer que los diseños son demasiado complejos y fueron gestos innecesarios, pero no nos apresuremos a sacar conclusiones, porque la cosa está en los mismos complementos. Por ejemplo, si decidimos publicar miles de fotos en el sitio, en cualquier caso, tuvimos que pensar en optimizar la carga de todo el contenido, y para no construir nuestro proceso de carga diferida desde cero, simplemente agregaríamos un complemento gatsby-image que optimizaría la carga de todos imágenes importadas usando la query
.
Instalación de complementos para diseñar:
yarn add gatsby-plugin-typography react-typography typography typography-theme-noriega node-sass gatsby-plugin-sass gatsby-plugin-styled-components styled-components babel-plugin-styled-components
gatsby-config.js
module.exports = { plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/` } }, // add style plugins below `gatsby-plugin-typography`, `gatsby-plugin-sass`, `gatsby-plugin-styled-components` ] };
En el sitio web oficial puede encontrar un complemento para todos los gustos.
Estilo de aplicación
Comencemos a diseñar la aplicación usando varios enfoques. En el paso anterior, ya instalamos complementos para trabajar con SASS , styled-components y la biblioteca typography.js , aunque es importante tener en cuenta que css.modules son compatibles desde el primer momento.
Comencemos con los estilos globales, que, como otras cosas relacionadas con todo el sitio, deben configurarse en el archivo /gatsby-browser.js :
import "./src/styles/global.scss";
Más acerca de gatsby-browser.js
/src/styles/global.scss
body { background-color: lavenderblush; }
Por varias razones, las tendencias de los últimos años se están inclinando hacia el enfoque "CSS en JS", por lo que no debe abusar de los estilos globales y es mejor limitarse a indicar la fuente y las clases reutilizadas. Este proyecto en particular planea usar Typography.js para estos fines, por lo que los estilos globales permanecerán vacíos.
Es posible que haya notado cambios en la apariencia del sitio después de agregar gatsby-plugin-typography
a la configuración; esto se debe a que se aplicó su valor predeterminado predeterminado y ahora lo configuraremos nosotros mismos.
/src/utils/typography.js
import Typography from "typography"; import theme from "typography-theme-noriega"; const typography = new Typography(theme); export default typography;
Puede seleccionar cualquier otro ajuste preestablecido de la lista o crear uno propio utilizando la API del paquete ( ejemplo de la configuración del sitio web oficial de Gatsby)
/gatsby-config.js
module.exports = { plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/` } }, { resolve: `gatsby-plugin-typography`, options: { pathToConfigModule: `src/utils/typography` } }, `gatsby-plugin-sass`, `gatsby-plugin-styled-components` ] };
Y dependiendo del preajuste seleccionado, el estilo global del sitio cambiará. Decide qué enfoque establecer para ti estilos globales, es una cuestión de preferencias y diferencias personales desde un punto de vista técnico, pero pasamos a los componentes de estilo usando componentes con estilo :
Agregue un archivo con variables globales /src/utils/vars.js
export const colors = { main: `#663399`, second: `#fbfafc`, main50: `rgba(102, 51, 153, 0.5)`, second50: `rgba(251, 250, 252, 0.5)`, textMain: `#000000`, textSecond: `#ffffff`, textBody: `#222222` };
/src/components/header.js import React from "react"; import { Link, StaticQuery, graphql } from "gatsby"; import styled from "styled-components"; import { colors } from "../utils/vars"; const Header = styled.header` width: 100%; height: 3em; display: flex; justify-content: space-between; align-items: center; background-color: ${colors.main}; color: ${colors.textSecond}; padding: 0.5em; `; const Logo = styled.img` border-radius: 50%; height: 100%; `; const logoLink = `height: 100%;`; export default () => ( <StaticQuery query={graphql` { allFile(filter: { name: { eq: "logo" } }) { edges { node { publicURL } } } } `} render={({ allFile: { edges: [ { node: { publicURL } } ] } }) => ( <Header> That is header <Link to="/" css={logoLink}> <Logo src={publicURL} alt="logo" /> </Link> </Header> )} /> );
/src/components/sidebar.js import React from "react" import { Link, StaticQuery, graphql } from "gatsby" import styled from "styled-components" import { colors } from "../utils/vars" const Sidebar = styled.section` position: fixed; left: 0; width: 20%; height: 100%; display: flex; flex-direction: column; justify-content: center; background-color: ${colors.second}; color: ${colors.textMain}; ` const navItem = ` display: flex; align-items: center; margin: 0 1em 0 2em; padding: 0.5em 0; border-bottom: 0.05em solid ${colors.mainHalf}; postion: relative; color: ${colors.textBody}; text-decoration: none; &:before { content: ''; transition: 0.5s; width: 0.5em; height: 0.5em; position: absolute; left: 0.8em; border-radius: 50%; display: block; background-color: ${colors.main}; transform: scale(0); } &:last-child { border-bottom: none; } &:hover { &:before { transform: scale(1); } } ` export default () => ( <StaticQuery query={graphql` { allSitePage { edges { node { id, path } } } } `} render={({ allSitePage: { edges } }) => ( <Sidebar> { edges.map(({ node: { id, path } }) => ( <Link to={path} key={id} css={navItem} >{id}</Link> )) } </Sidebar> )} /> )

Los elementos ya existentes están estilizados y es hora de asociar contenido con Contentful , conectar el complemento de margen y generar páginas usando la API createPages .
Lea más sobre cómo vincular Gatsby y Contentful en un artículo anterior.
Estructura de mis datos con Contentful [ { "id": "title", "type": "Symbol" }, { "id": "content", "type": "Text", }, { "id": "link", "type": "Symbol", }, { "id": "orderNumber", "type": "Integer", } ]
Instalación del paquete:
yarn add dotenv gatsby-source-contentful gatsby-transformer-remark
/gatsby-config.js
if (process.env.NODE_ENV === "development") { require("dotenv").config(); } module.exports = { plugins: [ `gatsby-transformer-remark`, { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/`, } }, { resolve: `gatsby-plugin-typography`, options: { pathToConfigModule: `src/utils/typography`, }, }, { resolve: `gatsby-source-contentful`, options: { spaceId: process.env.CONTENTFUL_SPACE_ID, accessToken: process.env.CONTENTFUL_ACCESS_TOKEN, }, }, `gatsby-plugin-sass`, `gatsby-plugin-styled-components`, ], }
Elimine la carpeta / src / pages con todos los archivos dentro y cree un nuevo archivo para administrar los nodos en Gatsby:
/gatsby-node.js
const path = require(`path`); /** * , * */ exports.createPages = ({ graphql, actions }) => { /** * * * */ const { createPage } = actions; return graphql(` { allContentfulArticle { edges { node { title link content { childMarkdownRemark { html } } } } } } `).then(({ data: { allContentfulArticle: { edges } } }) => { /** * * createPage() * */ edges.forEach(({ node }) => { createPage({ path: node.link, component: path.resolve(`./src/templates/index.js`), context: { slug: node.link } }); }); }); };
Más acerca de gatsby-node.js
Cree un archivo de plantilla que será la base de las páginas generadas.
/src/templates/index.js
import React from "react"; import { graphql } from "gatsby"; import Layout from "../components/layout"; export default ({ data: { allContentfulArticle: { edges: [ { node: { content: { childMarkdownRemark: { html } } } } ] } } }) => { return ( <Layout> <div dangerouslySetInnerHTML={{ __html: html }} /> </Layout> ); }; export const query = graphql` query($slug: String!) { allContentfulArticle(filter: { link: { eq: $slug } }) { edges { node { title link content { childMarkdownRemark { html } } } } } } `;
¿Por qué el <StaticQuery />
no se usa aquí? Lo que pasa es que no admite variables para construir una solicitud, pero necesitamos usar la variable $slug
desde el contexto de la página.
Actualizando la lógica en la barra de navegación import React from "react"; import { Link, StaticQuery, graphql } from "gatsby"; import styled from "styled-components"; import { colors } from "../utils/vars"; const Sidebar = styled.section` position: fixed; left: 0; width: 20%; height: 100%; display: flex; flex-direction: column; justify-content: center; background-color: ${colors.second}; color: ${colors.textMain}; `; const navItem = ` display: flex; align-items: center; margin: 0 1em 0 2em; padding: 0.5em 0; border-bottom: 0.05em solid ${colors.main50}; postion: relative; color: ${colors.textBody}; text-decoration: none; &:before { content: ''; transition: 0.5s; width: 0.5em; height: 0.5em; position: absolute; left: 0.8em; border-radius: 50%; display: block; background-color: ${colors.main}; transform: scale(0); } &:last-child { border-bottom: none; } &:hover { &:before { transform: scale(1); } } `; export default () => ( <StaticQuery query={graphql` { allContentfulArticle(sort: { order: ASC, fields: orderNumber }) { edges { node { title link orderNumber } } } } `} render={({ allContentfulArticle: { edges } }) => ( <Sidebar> {edges.map(({ node: { title, link, orderNumber } }) => ( <Link to={link} key={link} css={navItem}> {orderNumber}. {title} </Link> ))} </Sidebar> )} /> );

Optimización SEO
En el aspecto técnico, el sitio puede considerarse listo, así que trabajemos con sus metadatos. Para hacer esto, necesitamos los siguientes complementos:
yarn add gatsby-plugin-react-helmet react-helmet
react-helmet genera <head>...</head>
para páginas HTML y, junto con el renderizado de Gatsby, es una herramienta poderosa y conveniente para trabajar con SEO.
/src/templates/index.js
import React from "react"; import { graphql } from "gatsby"; import { Helmet } from "react-helmet"; import Layout from "../components/layout"; export default ({ data: { allContentfulArticle: { edges: [ { node: { title, content: { childMarkdownRemark: { html } } } } ] } } }) => { return ( <Layout> <Helmet> <meta charSet="utf-8" /> <title>{title}</title> </Helmet> <div dangerouslySetInnerHTML={{ __html: html }} /> </Layout> ); }; export const query = graphql` query($slug: String!) { allContentfulArticle(filter: { link: { eq: $slug } }) { edges { node { title link content { childMarkdownRemark { html } } } } } } `;
Ahora el title
sitio siempre coincidirá con el título del artículo, lo que afectará significativamente la publicación del sitio en los resultados de búsqueda específicamente para este problema. Aquí puede agregar fácilmente <meta name="description" content=" ">
con una descripción de cada artículo por separado, lo que permite al usuario comprender de qué se trata el artículo en la página de búsqueda, en general, todas las funciones de SEO ahora están disponibles y son manejables Un lugar

Configuración PWA
Gatsby está diseñado para ofrecer un rendimiento de primera clase listo para usar. Se ocupa de los problemas de separación y minimización de código, así como la optimización en forma de precarga en segundo plano, procesamiento de imágenes, etc., para que el sitio que cree tenga un alto rendimiento sin ninguna configuración manual. Estas características de rendimiento son una parte importante del soporte de un enfoque progresivo de aplicaciones web.
Pero además de todo lo anterior, hay tres criterios básicos para un sitio que lo definen como PWA :
Gatsby no puede resolver el primer punto, ya que el dominio , el alojamiento y el protocolo son problemas de implementación y no de desarrollo, pero puedo recomendar Netlify , que resuelve el problema https de forma predeterminada.
Pasamos a los elementos restantes, para esto instalaremos dos complementos:
yarn add gatsby-plugin-manifest gatsby-plugin-offline
y configúrelos /src/gatsby-config.js
if (process.env.NODE_ENV === "development") { require("dotenv").config(); } module.exports = { plugins: [ { resolve: `gatsby-plugin-manifest`, options: { name: `GatsbyJS translated tutorial`, short_name: `GatsbyJS tutorial`, start_url: `/`, background_color: `#f7f0eb`, theme_color: `#a2466c`, display: `standalone`, icon: `public/favicon.ico`, include_favicon: true } }, `gatsby-plugin-offline`, `gatsby-transformer-remark`, { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images/` } }, { resolve: `gatsby-plugin-typography`, options: { pathToConfigModule: `src/utils/typography` } }, { resolve: `gatsby-source-contentful`, options: { spaceId: process.env.CONTENTFUL_SPACE_ID, accessToken: process.env.CONTENTFUL_ACCESS_TOKEN } }, `gatsby-plugin-sass`, `gatsby-plugin-styled-components`, `gatsby-plugin-react-helmet` ] };
Puede personalizar su manifiesto utilizando la documentación , así como personalizar la estrategia de los trabajadores del servicio sobrescribiendo la configuración del complemento .
No notará ningún cambio en el modo de desarrollo, pero el sitio ya cumple con los últimos requisitos del mundo web, y cuando esté alojado en https: // dominio no será igual.
Conclusión
Hace un par de años, cuando encontré por primera vez los problemas de poner las aplicaciones React en Internet, su soporte y actualización de contenido, no podía imaginar que ya existía un enfoque JAM-stack en el mercado que simplifica todos estos procesos, y ahora no me sorprenderé. simplicidad Gatsby resuelve la mayoría de los problemas que afectan el rendimiento del sitio simplemente "fuera de la caja", y si comprende un poco más sobre las complejidades de personalizarlo según sus necesidades, puede obtener indicadores del 100% para todos los elementos en Lighthouse , lo que afecta significativamente la entrega del sitio en los motores de búsqueda (por al menos en Google).
Repositorio con proyecto