Pesquisa de site

Como criar um blog Markdown Next.js usando react-markdown


Coloque um blog básico em funcionamento rapidamente com este guia passo a passo.

Ferramentas de baixo código como o WordPress simplificam o processo de criação de blogs. Você pode usar um tema predefinido e começar a escrever postagens em questão de horas. Se você deseja mais controle sobre seu código e tem algum tempo disponível, é melhor construir seu blog do zero. Você pode até usar uma estrutura como Next.js para simplificar o processo.

Aprenda como construir um blog Next.js simples que renderiza postagens de markdown.

Criando um projeto Next.js

Next.js é uma estrutura React que simplifica a forma como você constrói aplicativos. Ele fornece muitas ferramentas e configurações prontas para uso, permitindo que você comece a escrever código imediatamente após instalá-lo.

A maneira mais simples de começar a usar Next.js é executando o comando create-next-app em um terminal:

npx create-next-app markdown-blog

Este comando cria um projeto Next.js contendo todos os arquivos necessários para iniciar.

Primeiramente, limpe o arquivo index.js para ficar assim:

import Head from 'next/head'
import styles from '../styles/Home.module.css'
 
export default function Home() {
  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
    </div>
  )
}

Crie postagens de blog Markdown

O blog renderizará arquivos markdown armazenados localmente na pasta do projeto. Então, crie uma nova pasta na raiz chamada content para armazenar os arquivos. Nesta pasta, crie um novo arquivo chamado create-active-link-nextjs.md e adicione o seguinte:

---
title: How To create an active link in Nextjs
description: Customizing active links using useRouter()
isPublished: true
publishedDate: 2022/07/22
tags:
  - next
---
## Main content

O nome do arquivo markdown fará parte do URL da postagem, portanto, certifique-se de que seja um bom nome. Além disso, observe o conteúdo entre os travessões. Esses são os metadados da postagem e são chamados de assunto inicial.

Analisando arquivos Markdown

Para cada postagem do blog, você deve analisar o conteúdo do markdown e o assunto inicial. Para Markdown, use react-markdown e para os dados iniciais, use gray-matter.

React-markdown é um componente React baseado em observação que converte markdown com segurança em HTML. A biblioteca de substância cinzenta analisa a matéria inicial e converte YAML em um objeto.

Execute o seguinte comando no terminal para instalar react-markdown e gray-matter.

npm install react-markdown gray-matter

Em uma nova pasta chamada utils, crie um novo arquivo chamado md.js. Você criará funções auxiliares que retornam o conteúdo da postagem do blog neste arquivo.

Obtenha todas as postagens publicadas

Em md.js, adicione o código a seguir para retornar todas as postagens na pasta de conteúdo.

import fs from "fs";
import path from "path";
import matter from "gray-matter";
 
export const getPath = (folder:string) => {
    return path.join(process.cwd(), `/${folder}`); // Get full path 
}
 
export const getFileContent = (filename:string, folder:string) => {
    const POSTS_PATH = getPath(folder)
    return fs.readFileSync(path.join(POSTS_PATH, filename), "utf8");
};
 
export const getAllPosts = (folder:string) => {
  const POSTS_PATH = getPath(folder)
 
  return fs
    .readdirSync(POSTS_PATH) // get files in directory
    .filter((path) => /\\.md?$/.test(path)) // only .md files
    .map((fileName) => { // map over each file
      const source = getFileContent(fileName, folder); // retrieve the file contents
      const slug = fileName.replace(/\\.md?$/, ""); // get the slug from the filename
      const { data } = matter(source); // extract frontmatter
      return {
        frontmatter: data,
        slug: slug,
      };
    });
};

Na função getAllPosts():

  • Obtenha o caminho completo para a pasta de conteúdo usando o módulo path.
  • Obtenha os arquivos na pasta de conteúdo usando o método fs.readdirSync().
  • Filtre os arquivos para incluir apenas arquivos com extensão .md.
  • Recupere o conteúdo de cada arquivo, incluindo o assunto inicial, usando o método map.
  • Retorna um array contendo o assunto inicial e o slug (o nome do arquivo sem a extensão .md) de cada arquivo.

Para obter apenas as postagens publicadas, você pode filtrar todas as postagens e retornar apenas aquelas cuja chave isPublished no cabeçalho está definida como verdadeira.

export const getAllPublished = (folder:string) => {
    const posts = getAllPosts(folder)
 
    const published = posts.filter((post) => {
      return post.frontmatter.isPublished === true
    })
 
    return published
  }

Em md.js, adicione a função getSinglePost() para recuperar o conteúdo de uma única postagem.

export const getSinglePost = (slug:string, folder:string) => {
  const source = getFileContent(`${slug}.md`, folder);
  const { data: frontmatter, content } = matter(source);
 
  return {
    frontmatter,
    content,
  };
};

Esta função chama a função getFileContent() para obter o conteúdo de cada arquivo. Em seguida, usando o pacote gray-matter, a função recupera o conteúdo inicial e o conteúdo do markdown.

Exibir todas as postagens do blog

Next.js oferece diferentes opções de renderização, sendo uma delas a geração estática. A geração estática é um tipo de pré-renderização onde Next.js gera todas as páginas HTML durante o tempo de construção. Você o usa para criar páginas estáticas rápidas.

Confira a documentação oficial do Nextjs para mais informações sobre renderização.

Next.js irá pré-renderizar uma página em tempo de construção usando os adereços retornados pela função getStaticProps. Nesse caso, os adereços serão uma série de postagens publicadas.

export const getStaticProps = async () => {
  const posts = getAllPublished("posts");
 
  return {
    props: { posts },
  };
};

Modifique o arquivo index.js para exibir uma lista de postagens do blog.

import Head from "next/head";
import Link from "next/link";
import { getAllPublished } from "../utils/md";
 
function Home({ posts }) {
  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <div>
        {posts.map((post) => (
          <article key={post.slug}>
            <p>[ {post.frontmatter.tags.join(", ")} ]</p>
            <Link href={`posts/${post.slug}`}>
              <a>{post.frontmatter.title}</a>
            </Link>{" "}
            <p>{post.frontmatter.description}</p>
          </article>
        ))}
      </div>
    </div>
  );
}
 
export const getStaticProps = async () => {
  const posts = getAllPublished("content");
 
  return {
    props: { posts },
  };
};
 
export default Home;

O componente Home usa as postagens retornadas por getStaticProps. Ele itera sobre eles usando a função de mapa e, para cada postagem, exibe um título, um link para a postagem completa e uma descrição.

Exibir uma postagem no blog

Conforme mencionado, os nomes dos arquivos das postagens serão usados como caminhos de URL. Esses caminhos também são dinâmicos, então você precisa gerá-los durante o tempo de construção. Next.js permite que você faça isso usando a função getStaticPaths().

Por exemplo, neste código, os caminhos são gerados a partir dos nomes dos arquivos markdown.

export const getStaticPaths = async () => {
  const paths = getAllPublished("posts").map(({ slug }) => ({ params: { slug } }));
 
  return {
    paths,
    fallback: false,
  };
};

Observe que você está usando os dados de postagens retornados pela função auxiliar getAllPublished() que você criou antes.

Você também está definindo fallback como false, o que retorna um erro 404 para caminhos que não existem.

getStaticPaths() geralmente é usado com getStaticProps() que recupera o conteúdo de cada postagem com base nos parâmetros.

export const getStaticProps = async ({ params }) => {
  const post = await getSinglePost(params.slug, "posts");
 
  return {
    props: { ...post },
  };
};

Para renderizar o markdown em HTML, use react-markdown.

import ReactMarkdown from 'react-markdown'
import { getAllPosts, getSinglePost } from "../../utils/md";
 
const Post = ({ content, frontmatter }) => {
  return (
    <div> 
        <p>{frontmatter.tags.join(', ')}</p>
        <h2>{frontmatter.title}</h2>
        <span>{frontmatter.publishedDate}</span>
        <ReactMarkdown>{content}</ReactMarkdown>
    </div>
  );
};

Este componente renderizará o conteúdo de cada postagem do blog e sua URL correspondente.

Ao criar um blog de desenvolvedor, você pode adicionar recurso de destaque de sintaxe para cada componente.

Estilizando o blog Markdown Next.js

Até agora, você criou um blog markdown Next.js que exibe uma lista de postagens do blog e renderiza o conteúdo dessa postagem. Para deixar o blog mais bonito, você deve adicionar estilos CSS.

Next.js tem um bom suporte CSS e você pode optar por usar bibliotecas CSS-in-JS como componentes estilizados. Se preferir separar CSS de JS, você pode usar módulos CSS.

Artigos relacionados: