Introduction
Dans le cadre de mon défi de codage de 100 jours cette année, j’ai décidé de créer un blog Next.js avec Hygraph alimentant mon backend et de documenter également le processus dans cet article.
Dans cet article, je vais vous apprendre à créer un blog entièrement réactif en deux étapes simples.
Voici un aperçu du blog que vous allez créer.
Recommandé: Ce didacticiel nécessite Noeud v16 ou supérieur et Hygraphe.
Qu’est-ce que Next.js ?
Next.js est un framework de réaction pour la création d’applications Web. Next.js est livré avec des fonctionnalités telles que le rendu côté serveur, la génération de site statique et la régénération statique incrémentielle qui font abstraction d’une grande partie du travail du développeur afin que vous puissiez vous concentrer sur l’interface utilisateur.
Qu’est-ce que GraphQL ?
Graphql est essentiellement un langage de requête permettant d’effectuer des opérations CRUD sur une API.
Hygraph, qu’est-ce que c’est ?
Hygraph est un cms sans tête qui peut alimenter le backend de vos applications Web. Contrairement à d’autres cms sans tête, Hygraph utilise graphql pour effectuer des opérations CRUD simples, vous permettant de demander des données spécifiques à partir d’une seule API.
C’est quoi Vercel ?
Vercel est essentiellement une plate-forme pour héberger votre application monopage.
Sans plus tarder, plongeons dedans.
ÉTAPE 1 : CONFIGURATION DU BACKEND GRAPHCMS.
Dans votre navigateur, rendez-vous sur https://hygraph.com/ et créez un compte si vous n’en avez pas déjà un.
Maintenant, cliquez Ajouter un projet pour créer un nouveau projet. Donnez au projet un nom, une description et sélectionnez une région à partir de laquelle vous souhaitez diffuser votre contenu.
Recommandé: Sélectionnez une région la plus proche de votre public cible.
– AJOUTER DES SCHEMA DE CONTENU
Ajoutons maintenant deux modèles à notre schéma, l’un pour les articles de blog et l’autre pour les informations sur l’auteur.
Les modèles dans Hygraph définissent la structure pour ajouter des données. Les champs d’un modèle peuvent être ajoutés à partir de Ajouter le champ section sur le côté droit.
Depuis votre tableau de bord Hygraph, cliquez sur Schema et cliquez ensuite sur + Add
. Maintenant, saisissez “Auteur” comme nom d’affichage et cliquez sur Ajouter un modèle.
Pour le modèle d’auteur, ajoutez deux champs, le champ Nom de l’auteur et le champ Description de l’auteur.
Nom de l’auteur : Ajouter un Champ à une seule ligne dans la barre latérale droite et définissez-le comme requis sous l’onglet Avancé.
Description de l’auteur : Ajouter un Champ multiligne dans la barre latérale droite et définissez-le comme requis sous l’onglet Avancé.
Hourra! vous avez créé votre premier modèle.
Ajoutons maintenant le modèle Blogpost, ce modèle comprend un champ Titre, un champ Extrait, un champ Slug, un champ d’actif pour l’image en vedette de la publication, un champ de format de texte enrichi pour le contenu de la publication et un champ de référence pour lier le modèle d’auteur à Modèle de poste.
Titre : ajouter un Champ à une seule lignedéfini selon les besoins.
Extrait : ajouter un Champ multilignedéfini selon les besoins.
Slug : ajoutez un champ Slug. Pour le champ Slug, vous devrez vérifier Générer un slug à partir d’un modèle sous les options de slug et entrez {title}
dans le champ du modèle de slug. Cela permet au slug d’être généré automatiquement à l’aide du champ de titre.
Sous l’onglet validations, cochez Rendre le champ obligatoire, Définir le champ comme unique, Faites correspondre un modèle spécifique, et insensible à la casse.
Image en vedette : ajouter un Champ de sélection d’élémentsutilisez coverPhoto comme nom d’affichage et définissez-le selon vos besoins.
Contenu : ajoutez un champ de texte enrichi à partir de la barre latérale droite et définissez ait s required.
Référence de l’auteur : ajoutez un champ de référence au modèle BlogPost.
Dans l’onglet Définir la relation, sélectionnez Autoriser le référencement d’un seul modèle, Référence bidirectionnelle et Autoriser plusieurs articles de blog par auteur.
Passez maintenant à la configuration de la référence et donnez-lui le nom d’affichage de l’auteur.
Sous l’onglet de champ inversé, donnez-lui un nom d’affichage de Blogposts.
Eh bien, c’est tout ce dont nous aurons besoin pour le modèle de poste.
Ajoutons encore une chose à la champ d’actifaller à Actif sur la gauche et ajoutez un champ à une seule ligne pour l’attribut alt de l’image.
N’hésitez pas à ajouter d’autres champs aux modèles. Cependant, pour ce tutoriel, cette configuration devrait convenir.
Recommandé: Remplissez votre modèle Post avant de continuer avec le reste de l’article.
ÉTAPE 2 : CONSTRUIRE LE FRONTEND
– Configuration de Next.js
Passons maintenant à l’action pour développer notre front de blog avec Next.js.
Pour démarrer une application Next.js, exécutez npx create-next-app@latest
dans votre borne.
La commande create-next-app crée automatiquement un répertoire et configure tout pour vous.
Remarque : Les dernières versions de create-next-app vous demanderont si vous souhaitez utiliser /src
ou l’expérimentation /app
répertoire, pour ce tutoriel optez pour /src
annuaire.
Après l’installation réussie de Next.js, exécutez cd project_name
dans le terminal, et lancez code .
pour ouvrir le code visuel.
Avant de démarrer l’exécution de votre serveur de développement npm install next-mdx-remote graphql-request graphql
pour installer quelques dépendances dont nous aurons besoin, puis exécutez npm dev pour démarrer le serveur de développement sur le port 3000.
Votre application doit fonctionner sur http://localhost:3000.
Avant de continuer, structurez votre répertoire /src pour qu’il ressemble à ceci.
|--/src
| |--/Components
| | |--Layout.js
| |--/pages
| | |--/api
| | |--_app.js
| | |--_document.js
| | |--index.js
| | |--[slug].js
| |--/styles
| | |--global.css
| | |--Home.module.css
| | |--Layout.module.css
| | |--SinglePost.module.css
Le /Composant répertoire contiendra des composants que votre projet réutilisera. Par exemple, le composant de mise en page.
Le /pages Le répertoire contient des fichiers qui définissent les routes de notre application.
Le /modes Le répertoire contient les fichiers CSS pour styliser nos composants.
– Réalisation de composants partagés.
1. Création du composant Layout.js.
Dans le répertoire du composant, créez un fichier Layout.js contenant le code ci-dessous :
import Link from "next/link";
import styles from "../styles/Layout.module.css";
function Layout({ children }) {
return (
<>
<nav className={styles.nav}>
<div>
<Link href="https://dev.to/">
<h1>NextBlog 0.1</h1>
</Link>
</div>
</nav>
{children}
</>
);
}
export default Layout;
Le bloc de code exporte une fonction qui accepte '{children}'
props comme argument et renvoie un logo texte simple et les accessoires enfants enveloppés dans un fragment.
2. Ajout de CSS.
Remarque : Dans ce didacticiel, nous n’aborderons pas le style, j’ai donc créé des fichiers CSS que nous ajouterons au code à un moment donné.
Créez un fichier Layout.module.css contenant le code suivant dans le répertoire /styles.
.nav {
overflow: hidden;
padding: 0 50px;
}
.nav div {
max-width: 80%;
margin: auto;
border-bottom: 2px solid #3f3f3f67;
}
.nav h1 {
color: #202020;
text-align: center;
padding: 20px 26px;
text-decoration: none;
font-size: 3rem;
}
/* CSS for tablets and small laptops */
@media (min-width: 701px) and (max-width: 1120px) {
.nav {
overflow: hidden;
padding: 0 50px;
}
.nav div {
max-width: 95%;
margin: auto;
border-bottom: 2px solid #3f3f3f67;
}
.nav h1 {
color: #202020;
text-align: center;
padding: 20px 26px;
text-decoration: none;
font-size: 2.5rem;
}
}
/* CSS for mobiles */
@media (max-width: 700px) {
.nav {
overflow: hidden;
padding: 0 50px;
}
.nav div {
max-width: 95%;
margin: auto;
border-bottom: 2px solid #3f3f3f67;
}
.nav h1 {
color: #202020;
text-align: center;
padding: 20px 26px;
text-decoration: none;
font-size: 1.9rem;
}
}
Vous devrez également remplacer le fichier global.css par défaut par le code ci-dessous.
:root {
--max-width: 1100px;
--border-radius: 12px;
--font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
"Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
"Fira Mono", "Droid Sans Mono", "Courier New", monospace;
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
--primary-glow: conic-gradient(
from 180deg at 50% 50%,
#16abff33 0deg,
#0885ff33 55deg,
#54d6ff33 120deg,
#0071ff33 160deg,
transparent 360deg
);
--secondary-glow: radial-gradient(
rgba(255, 255, 255, 1),
rgba(255, 255, 255, 0)
);
--tile-start-rgb: 239, 245, 249;
--tile-end-rgb: 228, 232, 233;
--tile-border: conic-gradient(
#00000080,
#00000040,
#00000030,
#00000020,
#00000010,
#00000010,
#00000080
);
--callout-rgb: 238, 240, 241;
--callout-border-rgb: 172, 175, 176;
--card-rgb: 180, 185, 188;
--card-border-rgb: 131, 134, 135;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
--primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
--secondary-glow: linear-gradient(
to bottom right,
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0.3)
);
--tile-start-rgb: 2, 13, 46;
--tile-end-rgb: 2, 5, 19;
--tile-border: conic-gradient(
#ffffff80,
#ffffff40,
#ffffff30,
#ffffff20,
#ffffff10,
#ffffff10,
#ffffff80
);
--callout-rgb: 20, 20, 20;
--callout-border-rgb: 108, 108, 108;
--card-rgb: 100, 100, 100;
--card-border-rgb: 200, 200, 200;
}
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
max-width: 100vw;
overflow-x: hidden;
}
a {
color: inherit;
text-decoration: none;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
}
3. Rendre notre composant partagé mondial.
Dans pages/_app.js, remplacez le contenu par le code ci-dessous :
import '@/styles/globals.css'
import Layout from '../Components/Layout'
export default function App({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
Le bloc de code importe le composant de mise en page que vous avez créé et l’enroule autour de ”. Le _app.js sert de point d’entrée pour toutes les routes dans le répertoire des pages.
– Récupération des données de Hygraph.
1. La page Index
Vous pouvez voir que le dossier pages contient un fichier index.js. Remplaçons-le en ajoutant un nouveau fichier index.js contenant le code suivant.
import Head from "next/head";
import Style from "../styles/Home.module.css";
import Image from "next/image";
import { GraphQLClient, gql } from "graphql-request";
import Link from "next/link";
const url =
"https://api-us-east-1-shared-usea1-02.hygraph.com/v2/cld3i52fm0lpi01up5mpk5v3i/master";
const graphConnect = new GraphQLClient(url);
const query = gql`
query {
blogposts {
title
slug
coverPhoto {
url
}
excerpt
id
author {
authorName
}
}
}
`;
export async function getServerSideProps() {
const { blogposts } = await graphConnect.request(query);
return { props: { blogposts } };
}
function Homepage({ blogposts }) {
return (
<>
<Head>
<title>Blog Tutorial</title>
</Head>
<div className={Style.postcontainer}>
{blogposts.map((blogposts) => {
return (
<div key={blogposts.id}>
<div className={Style.inside}>
<div className={Style.img}>
<Image
src={blogposts.coverPhoto.url}
alt="featured text"
fill
/>
</div>
<div className={Style.container}>
<Link href={blogposts.slug}>
<h2>{blogposts.title}</h2>
</Link>
<p>{blogposts.excerpt}</p>
<p>By {blogposts.author.authorName}</p>
<Link href={blogposts.slug}>
<button className={Style.readButton}>Read More</button>{" "}
</Link>
</div>
</div>
</div>
);
})}
;
</div>
</>
);
}
export default Homepage;
Pour obtenir votre point de terminaison API, accédez à votre projet Hygraph, accédez à Paramètres du projet > Accès API, copiez le point de terminaison API sous Content API et attribuez-le à la variable URL.
Maintenant, faites défiler jusqu’à API de contenu public et basculez read all...
sous les autorisations de contenu.
La variable de requête const se voit attribuer une chaîne de requête graphql, qui est utilisée pour interroger les données de Hygraph.
Le **new GraphQLClient()**
La méthode instancie un nouveau GraphQLClient et prend notre point de terminaison API comme argument et crée une connexion avec notre projet dans Hygraph.
Vous pouvez également remarquer que le bloc de code contient deux fonctions getServerSideProps
fonction et la fonction Accueil.
Le async
getServerSideProps
La fonction s’exécute sur une base par demande et nous permet de faire une demande d’hygraphe pour les données, elle renvoie ensuite un tableau de données (blogposts) en tant qu’accessoires qui est transmis à la fonction Home en tant qu’argument.
La fonction Accueil accepte les accessoires de getServerSideProps
fonction comme argument, parcourt le tableau et renvoie les données à l’interface utilisateur.
2. La page SinglePost.
Maintenant, créons une seule page pour chacun de nos articles de blog.
Créer un nouveau fichier ‘[slug].js’ contenant le code suivant.
import { GraphQLClient, gql } from "graphql-request";
import Head from "next/head";
import Style from "../styles/SinglePost.module.css";
import Image from "next/image";
import { serialize } from "next-mdx-remote/serialize";
import { MDXRemote } from "next-mdx-remote";
const url =
"https://api-us-east-1-shared-usea1-02.hygraph.com/v2/cld3i52fm0lpi01up5mpk5v3i/master";
const graphConnect = new GraphQLClient(url);
const query = gql`
query MyQuery($slug: String!) {
blogpost(where: { slug: $slug }) {
title
author {
authorName
}
content {
markdown
}
coverPhoto {
alt
url
}
}
}
`;
export async function getStaticPaths() {
const { blogposts } = await graphConnect.request(gql`
query {
blogposts {
slug
}
}
`);
return {
paths: blogposts.map(({ slug }) => ({
params: {
slug,
},
})),
fallback: "blocking",
};
}
export async function getStaticProps({ params }) {
const { blogpost } = await graphConnect.request(query, { slug: params.slug });
const content = blogpost.content.markdown;
const MdxSource = await serialize(content);
return { props: { post: blogpost, source: MdxSource } };
}
function SinglePost({ post, source }) {
return (
<>
<Head>
<title>Blog</title>
</Head>
<div className={Style.main}>
<div className={Style.header}>
<h1>{post.title}</h1>
<h3>Author: {post.author.authorName}</h3>
</div>
<div className={Style.img}>
<Image src={post.coverPhoto.url} alt={post.coverPhoto.alt} fill />
</div>
<div className={Style.mdxs}>
<MDXRemote {...source} />
</div>
</div>
</>
);
}
export default SinglePost;
Le bloc de code ci-dessus a trois fonctions, getStaticPath
, getStaticProps,
et un composant de fonction.
getStaticPaths
La fonction fait une requête à notre API et renvoie les chemins (slug) en tant que props à getStaticProps.
Le getStaticProps
la fonction prend les accessoires renvoyés par getStaticPaths
et l’utilise comme variable pour interroger un message qui correspond au slug.
Il utilise également le next-mdx-remote pour sérialiser le contenu de démarquage dans un format lisible. et renvoie la publication et le contenu sérialisé au composant de fonction pour le rendu.
**
4. Ajout de la prise en charge des images externes.
Pour pouvoir utiliser des images externes de notre Hygraph, nous aurions besoin d’ajouter un peu de configuration au fichier next.config.
Remplaçons le fichier next.config avec ce code.
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'media.graphassets.com',
port: '',
pathname: '/**',
},
],
},
}
module.exports = nextConfig
Ajout de quelques CSS.
Maintenant, stylisons notre composant. Créez trois fichiers de module CSS avec les codes suivants.
Créez un Home.module.css pour contenir ce code.
.postcontainer {
max-width: 800px;
margin: auto;
margin-top: 30px;
margin-bottom: 30px;
padding: 0 5px;
}
.inside {
margin-bottom: 30px;
padding: 10px 20px;
box-shadow: 2px 3px 2px rgb(218, 218, 218);
display: flex;
flex-direction: row;
}
.inside div:last-child {
margin-left: 25px;
}
.inside h2 {
text-align: justify;
margin-bottom: 15px;
font-size: 1.5rem;
font-weight: 600;
}
.inside p {
margin-bottom: 15px;
font-size: 0.9rem;
}
.readButton {
padding: 10px 16px;
background-color: aliceblue;
font-weight: 500;
cursor: pointer;
}
.img {
width: 260px;
height: 200px;
position: relative;
}
.container {
width: 555px;
}
/* Tablet and Smaller Desktop */
@media (min-width: 701px) and (max-width: 1120px) {
.postcontainer {
max-width: 80%;
margin: auto;
margin-top: 30px;
margin-bottom: 30px;
}
.inside {
margin-bottom: 30px;
padding: 10px 20px;
box-shadow: 2px 3px 2px rgb(218, 218, 218);
display: flex;
flex-direction: row;
}
.postcontainer h2 {
text-align: justify;
margin-bottom: 10px;
font-size: 1.9rem;
font-weight: 600;
}
.inside p {
margin-bottom: 10px;
font-size: 0.9rem;
}
.readButton {
padding: 10px 16px;
background-color: aliceblue;
font-weight: 500;
}
.img {
width: 250px;
height: 200px;
position: relative;
}
.container {
width: 65%;
}
}
/* Mobile */
@media (max-width: 700px) {
.postcontainer {
max-width: 90%;
margin: auto;
margin-top: 30px;
margin-bottom: 30px;
}
.inside {
margin-bottom: 30px;
padding: 10px 20px;
box-shadow: 2px 3px 2px rgb(218, 218, 218);
display: flex;
flex-direction: column;
}
.inside div:last-child {
margin-left: 0;
}
.postcontainer h2 {
text-align: justify;
margin-bottom: 10px;
font-size: 1.5rem;
font-weight: 600;
}
.inside p {
margin-bottom: 10px;
font-size: 0.9rem;
}
.readButton {
padding: 10px 16px;
background-color: aliceblue;
font-weight: 500;
cursor: pointer;
}
.img {
width: 100%;
height: 200px;
position: relative;
}
.container {
width: 100%;
}
}
Maintenant, créez un SinglePost.module.css pour contenir ce code.
.main {
max-width: 700px;
margin: auto;
}
.header {
margin-top: 40px;
}
.header h1,
.header h3 {
margin-top: 10px;
}
.header h1 {
font-size: 2rem;
}
.header h3 {
color: #777777;
}
.img {
margin-top: 20px;
width: 100%;
height: 500px;
position: relative;
}
.mdxs {
padding: 60px 0;
font-size: 1.4rem;
line-height: 1.5;
}
/* CSS for tablets and small laptops */
@media (min-width: 701px) and (max-width: 1120px) {
.main {
max-width: 90%;
margin: auto;
}
.header {
margin-top: 40px;
}
.header h1,
.header h3 {
margin-top: 10px;
}
.header h1 {
font-size: 2rem;
}
.header h3 {
color: #777777;
}
.img {
margin-top: 20px;
width: 100%;
height: 470px;
position: relative;
}
.mdxs {
padding: 60px 0;
font-size: 1.4rem;
line-height: 1.5;
}
}
/* CSS for mobiles */
@media (max-width: 700px) {
.main {
max-width: 85%;
margin: auto;
}
.header {
margin-top: 40px;
}
.header h1,
.header h3 {
margin-top: 10px;
}
.header h1 {
font-size: 2rem;
}
.header h3 {
color: #777777;
}
.img {
margin-top: 20px;
width: 100%;
height: 280px;
position: relative;
}
.mdxs {
padding: 60px 0;
font-size: 1.4rem;
line-height: 1.5;
}
}
c’est ça! vos composants ont été stylés.
Déploiement du projet.
1. Hébergement sur GitHub
Si vous êtes arrivé jusqu’ici, je suppose qu’il n’y a pas d’erreur, mais faisons quelques vérifications supplémentaires avant de le déployer sur Vercel.
- Première exécution
npm run lint
dans le terminal de votre répertoire de projet.
Le code exécute eslint pour vérifier les erreurs javascript potentielles.
Si aucune erreur n’est trouvée, vous obtiendrez un message “Aucun avertissement ou erreur Eslint” dans votre terminal
- Courir
git init
pour transformer notre environnement local en référentiel. - Maintenant, continuez et connectez-vous à votre compte GitHub et créez un nouveau référentiel.
- De retour dans votre terminal, connectons le référentiel local à GitHub, exécutez
git remote add origin <url to your GitHub repository>
. - Modifiez votre branche pour qu’elle corresponde à la branche sur GitHub en exécutant
git branch -M main
- Courir
git add -all
pour mettre en scène vos fichiers. - Courir
git commit -m "<message>"
pour valider vos fichiers. - Enfin, courez
git push -u origin main
pour pousser vers GitHub.
2. Déploiement à Vercel.
Tout d’abord, inscrivez-vous sur https://vercel.com/signup si vous n’avez pas encore de compte chez eux.
Recommandé : Inscrivez-vous avec votre compte GitHub.
- Connectez-vous et créez un nouveau projet.
- Importez votre référentiel de projets sur Vercel.
- Une fois l’importation réussie, cliquez sur déployer pour déployer votre projet avec les paramètres par défaut de Vercel.
- Une fois le déploiement réussi, vous obtenez des URL de déploiement que vous pouvez afficher et partager avec vos amis.
Emballer.
Vous avez terminé avec succès ce didacticiel et déployé votre première application monopage. J’espère que vous avez apprécié le voyage.
PS : N’hésitez pas à jouer avec le code et à le déployer. Si vous souhaitez partager votre travail avec moi, partagez-le sur Twitter et taguez-moi @FineyKempt.
Trouver le code source sur GitHub
*Ressource: *
Pour en savoir plus sur graphql, rendez-vous sur https://graphql.org/.
En savoir plus sur Hygraphe.
Vous pouvez également en savoir plus sur Next.js ici.