Heim >Web-Frontend >js-Tutorial >Integration mehrerer Blog-APIs in eine Astro-Site: Dev.to und Hashnode
Wenn Sie wie ich sind, schreiben Sie wahrscheinlich auf mehreren Blogging-Plattformen. In meinem Fall verwende ich sowohl Dev.to als auch Hashnode, um unterschiedliche Zielgruppen zu erreichen. Aber was passiert, wenn Sie alle Ihre Beiträge auf Ihrer persönlichen Website anzeigen möchten? Heute zeige ich Ihnen, wie ich beide APIs in mein mit Astro erstelltes Portfolio integriert habe.
Die größte Herausforderung war:
Zuerst definieren wir die Schnittstellen zur Eingabe unserer Daten:
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; }; }
Die Dev.to-API ist RESTful und ziemlich unkompliziert. So habe ich es umgesetzt:
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 []; } }
Hashnode verwendet GraphQL, was einen etwas anderen Ansatz erfordert:
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 []; } }
Die Magie entsteht beim Kombinieren und Ordnen der Beiträge:
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());
Um mit Ratenbegrenzungen und Fehlern umzugehen, habe ich die folgenden Strategien implementiert:
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; }
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)); } } }
Zuletzt rendern wir die Beiträge in unserer Astro-Komponente:
--- const allBlogPosts = waiting getAllPosts(); --- <div> <p>Diese Integration ermöglicht uns:</p>
Der vollständige Code ist auf meinem GitHub verfügbar.
Haben Sie andere Blogging-Plattformen in Ihre Website integriert? Teilen Sie Ihre Erfahrungen in den Kommentaren! ?
Das obige ist der detaillierte Inhalt vonIntegration mehrerer Blog-APIs in eine Astro-Site: Dev.to und Hashnode. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!