당신도 나와 같다면 아마도 여러 블로그 플랫폼에 글을 쓸 것입니다. 제 경우에는 Dev.to와 Hashnode를 모두 사용하여 다양한 청중에게 다가갑니다. 하지만 개인 사이트에 모든 게시물을 표시하려면 어떻게 해야 할까요? 오늘은 Astro로 구축한 포트폴리오에 두 API를 어떻게 통합했는지 보여드리겠습니다.
주요 과제는 다음과 같습니다.
먼저 데이터를 입력하기 위한 인터페이스를 정의합니다.
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; }; }
Dev.to API는 RESTful하고 매우 간단합니다. 구현 방법은 다음과 같습니다.
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는 GraphQL을 사용하며 약간 다른 접근 방식이 필요합니다.
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 []; } }
게시물을 결합하고 정렬할 때 마법이 일어납니다.
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());
속도 제한 및 오류를 처리하기 위해 다음 전략을 구현했습니다.
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)); } } }
마지막으로 Astro 구성 요소에서 게시물을 렌더링합니다.
--- const allBlogPosts = getAllPosts()를 기다립니다. --- <div> <p>이 통합을 통해 우리는 다음을 수행할 수 있습니다.</p>
전체 코드는 내 GitHub에서 확인할 수 있습니다.
다른 블로그 플랫폼을 귀하의 사이트에 통합하셨나요? 댓글로 여러분의 경험을 공유해주세요! ?
위 내용은 여러 블로그 API를 Astro 사이트에 통합: Dev.to 및 Hashnode의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!