Créer un blog avec Next.js

Next.js est peut-être le meilleur framework React pour créer votre blog. Parmi les avantages figurent les performances, la taille du bundle et le référencement. Construisons-en un !
Next.js est devenu l'un des frameworks les plus importants pour les applications React. Il aide les développeurs à créer de meilleures applications React de rendu côté serveur sans modèle standard. , prise en charge de TypeScript, référencement, etc.
Créer un blog à l'aide de Next.js est la meilleure option aujourd'hui pour ceux qui souhaitent avoir un blog simple mais puissant, sans se retrouver avec beaucoup de code et tout en augmentant notre classement SEO.
SEO (optimisation des moteurs de recherche) est le processus d'amélioration de votre application pour mieux se positionner sur les moteurs de recherche. C'est très important pour tout blog qui souhaite être mieux classé sur les moteurs de recherche et générer plus de trafic. Une bonne application avec un mauvais classement SEO ne sera pas productive, efficace ou réussie.
Nous allons utiliser Next.js dans cet article pour créer un blog généré de manière statique et prêt pour la production. Nous allons découvrir le fonctionnement de SSG (génération de site statique) et aboutir à un très bon blog avec un référencement efficace.
Prise en main
Nous allons créer une nouvelle application Next.js à l'aide de l'outil CLI Create Next App. Cela nous aide à démarrer facilement avec Next.js et à créer une nouvelle application. Pour commencer, nous allons utiliser la commande suivante :
npx create-next-app blog-with-next-js --example --with-typescript
Nous avons utilisé l'option --example
pour créer une nouvelle application Next.js en utilisant l'exemple de nom pour le référentiel Next.js. Nous avons utilisé l'option --with-typescript
pour créer une nouvelle application Next.js avec TypeScript.
Maintenant que nous avons notre nouvelle application Next.js, nous allons créer notre structure de dossiers.[19659003]Voici à quoi ressemblera notre structure de dossiers :
-- src
-- pages
-- Composants
-- des articles
--lib
Nous allons supprimer tous les dossiers provenant de l'interface de ligne de commande Create Next App et créer un nouveau dossier appelé src
. Dans le dossier src
nous allons créer tous les dossiers dont nous aurons besoin pour créer notre blog.
Maintenant, nous allons installer toutes les dépendances dont nous aurons besoin.
fil ajouter @emotion/styled @next/mdx date-fns matière grise mdx-prism next-mdx-remote next-seo read-time rehype remark-autolink-headings remark-capitalize remark-code-titles remark-external -liens remarque-images remarque-slug
Création de nos fichiers
Après avoir installé toutes nos dépendances, nous allons dans notre dossier de pages et créons un nouveau fichier appelé _app.tsx
.
Voici comment notre Le fichier _app.tsx
va chercher :
function MyApp({ Component, pageProps } : tout) {
retour <Composant {...pageProps} />[19659022];
}
export default MonApp
Maintenant, dans notre dossier articles
nous allons créer un nouveau fichier appelé introducing-blog-with-nextjs.mdx
. Tous les articles de blog de notre blog seront écrits à l'aide de Markdown et devraient avoir un contenu décrit par --
qui est connu sous le nom de matière première. Le premier article contient toutes les informations de notre article de blog.
Voici à quoi ressemblera notre premier article de blog :
---
title : « Présentation du blog avec Next.js »
description: "Un nouveau blog utilisant Next.js et Markdown"
date : "14 avril 2021"
slug: "présentation-blog-avec-nextjs"
ogImage :
URL : "/images/articles/introducing-blog-with-nextjs.jpeg"
---
Nulla tortor orci, porttitor dans pulvinar sit amet, ultricies sit amet sem. Nullam et posuere felis, sit amet convallis urna. Pellentesque vel ipsum dolor.
Maintenant que nous avons écrit notre premier article de blog, nous allons dans notre dossier lib
et créons des fonctions d'aide dont nous aurons besoin.
Nous allons créer un fichier appelé lib.ts
et y mettre le code suivant :
import fs from "fs";[19659045]import { join } from "path";
import matière from "gray-matter"[19659022];
import readingTime from "reading-time";
import { API, BlogArticleType } de "src/types";
const articlesRépertoire = join(process.cwd[19659022](), "src/articles");
fonction getRawArticleBySlug(slug: chaîne): matière.GrayMatterFile<chaîne> {[19659026]const fullPath = join(articlesDirectory, `${slug}.mdx` );
const fileContents = fs.readFileSync(fullPath, "utf8");
return matter(fileContents);
}
function getAllSlugs (): Array<string> {
return fs.readdirSync(répertoire articles);
}
fonction getArticleBySlug(
slug: string,
champs: string[] = [],
): BlogArticleType {[19659026]const realSlug = slug.replace(/.mdx$/, "")[19659022];
const { data, contenu } = getRawArticleBySlug(realSlug) ;
const timeReading: any = readingTime(content);
const items:BlogArticleType = {};
champs.pourChaque((champ) => {
if (champ = == "limace") {
items[field] = realSlug;
}
if (field === "contenu") {
éléments[champ] = contenu;
}
if (champ === "lecture du temps") {
items[field] = timeReading;
}
if (data[field]) {
éléments[champ] = données[champ];
}
})[19659022];
return items;
}
function getAllArticles(fields: string[ ] = []): Array<BlogArticleType> {
return getAllSlugs[19659022]()
.map((slug) => getArticleBySlug(slug, champs))
.tri((article1, article2) = > (article1.date > article2.date ? -1 :[19659225]1)[1 9659022]);
}
fonction getArticlesByTag(
balise: chaîne,
champs: string[] = [],
): Array<BlogArticleType> {
return getAllArticles(fields)..filter(( article) => {
const tags = article.tags ?? [];
balises de retour.comprend(tag);
})[19659022];
}
function getAllTags(): Array<string> {
const articles = getAllArticles(["tags"]);;
const allTags = nouveau[19659289]Set<string>();
articles.forEach((article) => {
const tags = article .balises as Array<string>;
tags.forEach((tag) => allTags.add(tag ));
});
retour Array.de(tous les tags);
}
export const api: API = {
getRawArticleBySlug,
getAllSlugs,
obtenirTous lesarticles,
getArticlesByTag,
getArticleBySlug,
getAllTags,
};
Une petite explication de ce qui se passe dans ce fichier et de ce que font toutes les fonctions :
- La fonction appelée
getRawArticleBySlug
est chargée de récupérer tous nos articles de blog par slug. Il va dans notre dossier d'articles et récupère tous les fichiers par slug et renvoie nos données et le contenu de notre article de blog. - La fonction appelée
getArticleBySlug
est responsable de la réception d'un slug et d'un tableau de champs comme arguments et renvoyer un article de blog. - La fonction appelée
getAllArticles
est chargée de récupérer tous nos articles de blog et de renvoyer un tableau d'articles de blog.
Dans notre dossier src
nous allons créer un fichier types.ts
où nous allons créer toutes nos interfaces et types TypeScript. Dans le fichier, collez le code suivant :
import matière from "gray-matter";
export interface AuthorType {
nom: chaîne;
image: chaîne;
}
export interface ArticleType {
slug: chaîne;
titre: chaîne;
description: chaîne;
date: chaîne;
coverImage: chaîne;
auteur: AuthorType;
extrait: chaîne;
lecture de l'heure : {
texte: chaîne;
};
ogImage: {
URL: chaîne;
};
content: string;
}
export interface BlogArticleType {
[key: string]: chaîne | Tableau<chaîne>;
}
export interface API {
getRawArticleBySlug: (slug: chaîne) => matière.GrayMatterFile<chaîne >;
getAllSlugs: () => Tableau<string>;
getAllArticles: (fields: string[]) => Array<BlogArticleType >;
getArticlesByTag: (tag: chaîne, champs: chaîne[])[19659027]=> Tableau<BlogArticleType>;
getArticleBySlug: (slug: chaîne, champs: chaîne[])[19659027]=> BlogArticleType;
getAllTags: () => Array<string>;
}
Création de nos composants[19659008]Dans notre dossier components
nous allons créer deux nouveaux dossiers.
Nous allons créer un dossier appelé ArticleItem
où nous allons créer le composant pour le rendu d'un article en tant qu'aperçu.
Nous allons créer un dossier appelé Article
où nous allons créer notre composant pour le rendu d'un article spécifique.
Nous allons commencer par notre dossier ArticleItem
. Dans le dossier, créez un fichier nommé ArticleItem.tsx
et un fichier nommé ArticleItem.styles.ts
.
Dans notre ArticleItem.styles.ts
nous allons créer un style simple pour notre composant en utilisant Emotion. Mettez-y le code suivant :
import styled from "@emotion/styled";
export const ArticleItemContainer = style.article`
largeur : 100 % ;
largeur maximale : 800 px ;
hauteur : fit-contenu ;
affichage : grille ;
grille-modèle-colonnes : 1fr ;
grid-template-rows : 250px repeat(auto-fill, max-content);
grille-ligne-écart : 20px ;
align-items: center;
@media screen et (min-width : 1000px) {
grille-modèle-colonnes : 340px 1fr ;
grille-modèle-lignes : 1fr ;
grille-colonne-écart : 20px ;
align-items: center;
}
`;
Maintenant, dans notre fichier ArticleItem.tsx
nous allons coller le code suivant :
import React from "react";[19659045]import NextLink from "next/link";
import { ArticleItemContainer } from "./ArticleItem .styles";
import { ArticleType } de "src/types";
interface Accessoires {
article: ArticleType;
};
const ArticleItem = ({ article }[19659022]: Accessoires) => (
<ArticleItemContainer>
<img
src={article.ogImage.url}
alt="Image de l'article"
style={{ largeur: "100%", hauteur: 250, borderRadius: 5, objectFit: "cover" }}
lazy="loading"
/>
<div style={{ display:[19659043]"flex", direction: "column", alignItems: "center", justifierItems:"center" }}>
<NextLink as={`/blog/ ${article.slug}`} href="/blog/[slug] ">
<a href="/blog">
{article.titre}[19659475]</a>
</NextLink>
<p style={[19659022]{ color: "#6F6F6F, fontSize: 16, fontWeight: 300 }}>
{article. description}
</p>
<div style={{ afficher : "flex", direction: "column", alignItems: "center", justifierItems :"centre" }}>
<p style={{ couleur : "#6F6F6F, fontSize: 16, fontWeight: 300 }} >
{article.timeReading.text}
</p>
<p style={{ couleur: "#6F6F6F, fontSize: 16, fontWeight: 300 }[19659022]}>
•
</p>
<p style={{ couleur: "# 6F6F6F, fontSize: 16, fontWeight: 300 }}>
{article.date}
</p>
</div>
<NextLink as={`/blog/${article.slug}[19659085]`} href="/blog/[slug]">
<a href="/ blog" couleur="#6f6f6f">
Lire l'article
</a>
</NextLink>
</div>[19659435]</ArticleItemContainer>
);
export default ArticleItem;
Ensuite, dans notre dossier Article
nous allons créer un fichier appelé Article.tsx
et deux autres dossiers appelés Header
et Content
.
Dans le dossier Header
nous allons créer un fichier appelé Header.tsx
et y coller le code suivant :
import React from "réagir";
interface Accessoires {
Temps de lecture: {
texte: chaîne;
};
titre: chaîne;
description: chaîne;
date: chaîne;
ogImage: {
url: chaîne;
};
}
const En-tête = ({ titre, description, date, ogImage }: Accessoires) => ([19659435]<div style={{ display: "flex", direction: "colonne ", alignItems: "center", justifierItems:"center" }}>[19659436]<p style={{ couleur: "#6F6F6F", fontWeight: "300", textAlign: "center" }}>
Publié le {date}
</p>
<h1 style={ { color: "#101010", fontWeight: "600", textAlign: " center" }}>
{title}
</h1>
<p style={{ couleur: "#6F6F6F", fontWeight: "300" textAlign: "center" }}>
{description}
</p >
<img
src={ogImage.url}
alt="Poster l'image"
style={{ largeur: "100%", hauteur: 400, borderRadius: 5, objectFit: "cover" }}
lazy="loading"
/>
</div>
);
export par défaut En-tête;
À l'intérieur du Dossier de contenu
nous allons créer un fichier appelé Content.tsx
et y coller le code suivant :
import React from[19659043]"réagir";
interface Accessoires {
content: React.ReactNode;
};
const Content = ({ contenu }: Accessoires) => (
<div style={{ display: "flex", direction: "column", alignItems: "center"[19659022], justifierItems:"center" }}>
{content}
</div>
);
export default Contenu;
Maintenant, dans notre fichier Article.tsx
collez le code suivant :
import React from "react";
import En-tête de "./En-tête/En-tête";
import Contenu de "./Content/Content";
interface Accessoires {
Temps de lecture: {
texte: chaîne;
};
titre: chaîne;
description: chaîne;
date: chaîne;
ogImage: {
URL: chaîne;
};
contenu: React.ReactNode;
slug: string;
};
const Article = ({
Temps de lecture,
titre,
description,
date,
ogImage,
contenu,
}: Accessoires) => (
<div style={ { display: "flex", direction: "column", alignItems: "center ", justifierItems:"center" }}>
<En-tête
Heure de lecture={Heure de lecture}
titre={titre}
description={description}
date={date}
ogImage={ogImage}
/>
<Contenu content={content} />
<hr />
</div>
);[19659033]export default Article;
Rendu de nos articles de blog
Maintenant que nous avons créé nos composants et les fonctions d'assistance dont nous allons avoir besoin, nous allons réellement créer les pages pour afficher nos articles de blog.
Dans notre dossier pages
nous allons avoir un fichier appelé index.tsx
où nous afficherons tous nos articles de blog.
Dans le fichier index.tsx
nous allons importer le composant ArticleItem
que nous avons créé. Après cela, nous allons importer l'API depuis notre fichier lib.ts
pour renvoyer tous nos articles de blog.
import React from "react"[19659022];
import ArticleItem from "src/components/ArticleItem/ArticleItem";
import { api } from "src/lib/lib";
import { BlogArticleType, ArticleType } de "src/types" ;
interface Accessoires {
articles: Array<ArticleType>;
};
const Index = ([19659022]{ articles }: Accessoires) => (
<div style={[19659022]{ display: "flex", direction: "column", alignItems: "center", justifierItems:"center" }}>
{articles.map[19659022]((article: ArticleType) => (
<ArticleItem key={article.slug} article={article} />
) )}
<[19659028]/div>
);
Pour chaque article de blog que nous avons, nous allons rendre un composant ArticleItem
. Nous recevons nos articles en tant qu'accessoire, mais nous devons les récupérer.
Nous allons utiliser la fonction getStaticProps
de Next.js pour récupérer tous nos articles de blog et transmettre nos articles en tant que un accessoire à notre composant.
export const getStaticProps = async () => {
const articles: Array<BlogArticleType> = api.getAllArticles([
"slug ",
"titre",
"description",
"date",
"coverImage",
"extrait ",
"timeReading",
"ogImage",
"content",
]);
retour {
accessoires: { articles },
};
};
Nous affichons désormais correctement tous nos articles de blog. Maintenant, dans notre dossier pages
nous allons créer un dossier appelé blog
et à l'intérieur de ce dossier créer un fichier appelé [slug].tsx
.
Inside this file, we're going to render a specific blog post. We’re going to import a few dependencies that we’re going to need and again the API from our lib.ts
file.
import React from "react";
import readingTime from "reading-time";
import mdxPrism from "mdx-prism";
import renderToString from "next-mdx-remote/render-to-string";
import hydrate from "next-mdx-remote/hydrate";
import { NextSeo } from "next-seo";
import MDXComponents from "src/components/MDXComponents/MDXComponents";
import Article from "src/components/Article/Article";
import { api } from "src/lib/lib" ;
import { BlogArticleType } from "src/types";
interface Props {
readingTime: {
text: string;
};
frontMatter: {
title: string;
description: string;
date: string;
content: string;
ogImage: {
url: string;
};
};
slug: string;
source: any;
tags: Array<string>;
};
const Index = ({ readingTime, frontMatter, slug, source }: Props) => {
const content = hydrate(source);
return (
<div>
<NextSeo
title={frontMatter.title}
description={frontMatter.description}
/>
<Article
readingTime={readingTime}
title={frontMatter.title}
description={frontMatter.description}
date={frontMatter.date}
content={content}
ogImage={frontMatter.ogImage}
slug={slug}
/>
</div>
);
};
We’re going to use the getStaticPaths
from Next.js and pass a list of paths that have to be pre-rendered at build time. We’re also going to use the renderToString
function from next-mdx-remote to turn our content into a string and use some plugins for our Markdown text.
type Params = {
params: {
slug: string;
timeReading: {
text: string;
};
};
};
export async function getStaticProps({ params }: Params) {
const { content, data } = api.getRawArticleBySlug(params.slug);
const mdxSource = await renderToString(content, {
components: MDXComponents,
mdxOptions: {
remarkPlugins: [
require("remark-autolink-headings"),
require("remark-slug"),
require("remark-code-titles"),
require("remark-autolink-headings"),
require("remark-capitalize"),
require("remark-code-titles"),
require("remark-external-links"),
require("remark-images"),
require("remark-slug"),
],
rehypePlugins: [mdxPrism],
},
});
const tags = data.tags ?? [];
return {
props: {
slug: params.slug,
readingTime: readingTime(content),
source: mdxSource,
frontMatter: data,
tags,
},
};
}
export async function getStaticPaths() {
const articles: Array<BlogArticleType> = api.getAllArticles(["slug"]);
return {
paths: articles.map((articles) => {
return {
params: {
slug: articles.slug,
},
};
}),
fallback: false,
};
};
We now have a fully production-ready and statically generated blog using Next.js.
Conclusion
Creating a blog using Next.js is very easy and straightforward. The benefits of Next.js, especially for blogs, are huge. Your blog application will have a very good performance, a small bundle and a good SEO score.
Source link