Maison > interface Web > js tutoriel > Intégration de plusieurs API de blog dans un site Astro : Dev.to et Hashnode

Intégration de plusieurs API de blog dans un site Astro : Dev.to et Hashnode

Patricia Arquette
Libérer: 2024-12-08 04:59:15
original
891 Les gens l'ont consulté

Integrando Múltiples APIs de Blog en un Sitio Astro: Dev.to y Hashnode

Si vous êtes comme moi, vous écrivez probablement sur plusieurs plateformes de blogs. Dans mon cas, j'utilise à la fois Dev.to et Hashnode pour toucher différents publics. Mais que se passe-t-il lorsque vous souhaitez afficher tous vos posts sur votre site personnel ? Aujourd'hui, je vais vous montrer comment j'ai intégré les deux API dans mon portefeuille construit avec Astro.

Le défi

Le principal défi était :

  1. Recevoir des messages de deux API différentes
  2. Unifier le format des données
  3. Classez-les par ordre chronologique
  4. Gérer les erreurs et la limitation du débit
  5. Saisie sécurisée avec TypeScript

Configuration initiale

Tout d'abord, nous définissons les interfaces pour saisir nos données :

interface BlogPost {
  title: string;
  brief: string;
  slug: string;
  dateAdded: string;
  rawDate: string;
  coverImage: string;
  url: string;
  source: string;
}

interface HashnodeEdge {
  node: {
    title: string;
    brief: string;
    slug: string;
    dateAdded: string;
    coverImage?: {
      url: string;
    };
    url: string;
  };
}
Copier après la connexion

Intégration de Dev.to

L'API Dev.to est RESTful et assez simple. Voici comment je l'ai implémenté :

async function getDevToPosts() {
  try {
    const params = new URLSearchParams({
      username: 'tuUsuario',
      per_page: '20',
      state: 'all',
      sort: 'published_at',
      order: 'desc'
    });

    const headers = {
      'Accept': 'application/vnd.forem.api-v1+json'
    };

    // Agregar API key si está disponible
    if (import.meta.env.DEV_TO_API_KEY) {
      headers['api-key'] = import.meta.env.DEV_TO_API_KEY;
    }

    const response = await fetch(`https://dev.to/api/articles?${params}`, { headers });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    const posts = await response.json();

    return posts.map((post: any) => ({
      title: post.title,
      brief: post.description,
      slug: post.slug,
      dateAdded: formatDate(post.published_timestamp),
      rawDate: post.published_timestamp,
      coverImage: post.cover_image || '/images/default-post.png',
      url: post.url,
      source: 'devto'
    }));
  } catch (error) {
    console.error('Error al obtener posts de Dev.to:', error);
    return [];
  }
}
Copier après la connexion

Intégration de Hashnode

Hashnode utilise GraphQL, ce qui nécessite une approche légèrement différente :

async function getHashnodePosts() {
  try {
    const query = `
      query {
        publication(host: "tuBlog.hashnode.dev") {
          posts(first: 20) {
            edges {
              node {
                title
                brief
                slug
                dateAdded: publishedAt
                coverImage {
                  url
                }
                url
              }
            }
          }
        }
      }
    `;

    const response = await fetch('https://gql.hashnode.com', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ query })
    });

    const { data } = await response.json();

    return data.publication.posts.edges.map((edge: HashnodeEdge) => ({
      title: edge.node.title,
      brief: edge.node.brief,
      slug: edge.node.slug,
      dateAdded: formatDate(edge.node.dateAdded),
      rawDate: edge.node.dateAdded,
      coverImage: edge.node.coverImage?.url || '/images/default-post.png',
      url: edge.node.url,
      source: 'hashnode'
    }));
  } catch (error) {
    console.error('Error al obtener posts de Hashnode:', error);
    return [];
  }
}
Copier après la connexion

Combiner les résultats

La magie opère lors de la combinaison et de l'ordre des publications :

const hashnodePosts = await getHashnodePosts();
const devtoPosts = await getDevToPosts();

const allBlogPosts = [...hashnodePosts, ...devtoPosts]
  .sort((a, b) => new Date(b.rawDate).getTime() - new Date(a.rawDate).getTime());
Copier après la connexion

Gestion des erreurs et limitation du débit

Pour gérer la limitation de débit et les erreurs, j'ai mis en œuvre ces stratégies :

Cache côté client :

const CACHE_DURATION = 5 * 60 * 1000; // 5 minutos
let postsCache = {
  data: null,
  timestamp: 0
};

async function getAllPosts() {
  const now = Date.now();
  if (postsCache.data && (now - postsCache.timestamp) < CACHE_DURATION) {
    return postsCache.data;
  }

  // Obtener y combinar posts...

  postsCache = {
    data: allBlogPosts,
    timestamp: now
  };
  return allBlogPosts;
}
Copier après la connexion

Nouvelles tentatives avec interruption exponentielle :

async function fetchWithRetry(url: string, options: any, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, options);
      if (response.status === 429) { // Rate limit
        const retryAfter = response.headers.get('Retry-After') || '60';
        await new Promise(resolve => setTimeout(resolve, parseInt(retryAfter) * 1000));
        continue;
      }
      return response;
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
    }
  }
}
Copier après la connexion

Rendu en Astro

Enfin, nous rendons les publications dans notre composant Astro :

---
const allBlogPosts = attendre getAllPosts();
---

<div>



<p>Cette intégration nous permet de :</p>

Copier après la connexion
  • Maintenir une source unique de vérité pour nos publications
  • Afficher le contenu de plusieurs plates-formes
  • Gérer les erreurs avec élégance
  • Maintenir un code tapé et sécurisé

Le code complet est disponible sur mon GitHub.

Avez-vous intégré d'autres plateformes de blogs dans votre site ? Partagez vos expériences dans les commentaires ! ?

webdev #astro #typescript #api

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal