codelynx.dev
🇫🇷🇬🇧

Retour 21/10/2024

Comment planifier ses articles en utilisant NextJS ?

Écris par Melvyn Malherbe le 21/10/2024


Tu as un article de blog et tu souhaites planifier tes postes en utilisant NextJS et Vercel ?

Tu souhaites juste mettre une date dans tes articles comme publishedAt et qu'ensuite, ton application s'occupe de venir build dès que la date est passée ?

J'ai une solution simple et efficace pour toi que j'ai implémentée.

Pour résumer, ce qu'on va faire :

  1. Avoir des articles de blog avec une date
  2. Créer une API routes statique qui retourne nos articles
  3. Créer une URL pour déclencher un déploiement sur NextJS
  4. Créer un CRON jobs NextJS qui appelle ce déclencheur s'il y a de nouveaux articles

1. Setup des articles de blog

Alors pour commencer, je pars du principe que tu utilises NextJS avec le app router. Tu utilises front-matter pour créer tes articles et tu as ce genre de données :

MDX
---
title: "Some title",
date: 2024-10-15
published: true
---

Mon article...

Si tu as ça, c'est parfait.

Ce qu'on va faire c'est commencer par créer une logique pour ne pas afficher les articles qui ont une date dans le passé.

Moi j'ai fait ce genre de code :

TS
const currentDate = new Date();
// Si l'article est publié mais que sa date est dans le passé,
// je considère l'article comme pas publié
const isPublished = data.published && isBefore(data.date, currentDate);

if (
  // I only want to hide articles that are not published in production
  process.env.NODE_ENV === 'production' &&
  !isPublished &&
  !opts.enableNotPublishedPost
) {
  continue;
}

return ...

Comme tu peux le voir, la logique est simple et permet de ne pas retourner et afficher des articles qui ne seraient pas encore publiés.

2. Créer une API route

Maintenant on va créer une API Route statique qui va retourner les articles.

TS
// api/posts/route.ts

import { NextResponse } from 'next/server';
import { getPosts } from '../../(main)/(posts)/posts-helpers';

export const GET = async () => {
  const post = await getPosts({
    limit: 3,
    order: 'desc',
  });

  return NextResponse.json(post);
};

Voici le code de mon application, tu peux voir qu'on vient juste retourner les 3 derniers articles.

Cette route va être statique car on n'utilise pas de headers ou cookies. Elle va être définie quand on build l'application et plus jamais changer.

C'est cette fonctionnalité qu'on va utiliser pour voir s'il y a de nouveaux articles.

3. Créer une URL pour déclencher un déploiement

Il va déjà falloir faire en sorte de pouvoir créer un déploiement sur Vercel très simplement.

Pour ça tu peux aller dans tes projets "Settings", ensuite tu peux aller dans le sous-menu "Git" et scroller jusqu'à trouver "Deploy Hooks".

Une fois fait, tu peux créer un nouveau hook et mettre l'URL dans tes variables d'environnement.

Accède au déploiement de Vercel
// .env

VERCEL_DEPLOY_WEBHOOKS="XXX"

4. Créer un CRON jobs NextJS

On va maintenant créer un CRON Job pour ça on commence par créer un fichier vercel.json dans la racine de ton projet.

JSON
// vercel.json
{
  "crons": [
    {
      "path": "/api/cron/deploy",
      "schedule": "0 */4 * * *"
    }
  ]
}

Ici je dis que je veux appeler l'API Route /api/cron/deploy toutes les 4 heures. N'hésite pas à changer le schedule selon ton besoin.

Ensuite, on va créer un fichier api/cron/deploy/route.ts :

TS
export const GET = route.handler(async (request) => {
  // Vérifie que c'est bien les CRON jobs qui appellent la méthode
  const authHeader = request.headers.get('authorization');
  if (authHeader !== `Bearer ${env.CRON_SECRET}`) {
    return new Response('Unauthorized', {
      status: 401,
    });
  }

  // Récupère le dernier post de production
  const prodPosts = await fetch('https://codelynx.dev/api/posts').then(
    async (res) => res.json() as unknown as Post[]
  );
  const latestProdPost = prodPosts[0];

  // Récupère le vrai dernier post
  const currentPosts = await getPosts({
    limit: 3,
    order: 'desc',
  });
  const latestPost = currentPosts[0];

  if (latestPost.id === latestProdPost.id) {
    logger.info("No new post, don't deploy");
    return Response.json({ success: true });
  }

  // Deploy via webhooks
  const result = await fetch(env.VERCEL_DEPLOY_WEBHOOKS).then(async (res) =>
    res.json()
  );

  return Response.json({ success: true });
});

Ce code est intéressant car on utilise le fait que, étant donné qu'on consomme la requête avec headers, NextJS va automatiquement transformer cette route en dynamique.

Donc cette route va récupérer les VRAIS derniers postes, alors que l'autre route retourne toujours les mêmes postes entre les builds.

Ce code va donc faire en sorte que tout soit correctement déployé comme ça :

Tu peux admirer les déploiements maintenant

Si tu veux mieux comprendre tous ces sujets à propos de NextJS, je t'invite à regarder ma formation NextJS.

Conclusion

Je ne pensais pas que ce serait "si facile" mais cette méthode me permet enfin de ne pas être stressé et de voir tous mes articles se publier sans effort de ma part.

Tu peux avoir des meilleurs routes en utilisant next-zod-route une petite librairie que j'ai faite ou next-safe-action dont j'ai fait un guide complet.

Ou tu peux juste t'inscrire à mes cours NextJS :

Le meilleur moyen d'apprendre NextJS !

Rejoins par développeurs, cette formation reçoit une note de 4.7 / 5 🚀

Reçois la formation gratuitement dans ta boîte mail :

NextReact

Cours NextJS gratuit

Accède à des exercices, des vidéos et bien plus sur NextJS dans la formation "NextReact" 👇