Next.js 13基于GNews API生成新闻详情静态页的实现求助
实现Next.js 13新闻详情页方案
步骤1:封装新闻数据获取逻辑
先创建公共工具函数统一处理GNews数据与slug生成:
// lib/news.ts import slugify from 'slugify'; // 定义文章类型,规范数据结构 export interface NewsArticle { title: string; description: string; content: string; url: string; image: string; publishedAt: string; source: { name: string; url: string; }; slug: string; } // 获取新闻列表并生成唯一slug export async function getNewsArticles(): Promise<NewsArticle[]> { const API_KEY = process.env.GNEWS_API_KEY; // 可根据需求调整GNews API参数(如语言、分类、国家等) const response = await fetch(`https://gnews.io/api/v4/top-headlines?token=${API_KEY}&lang=zh`); const data = await response.json(); return data.articles.map(article => ({ ...article, // 生成小写、无特殊字符的slug slug: slugify(article.title, { lower: true, strict: true }) })); }
步骤2:完成详情页组件(articles/[slug]/page.tsx)
实现静态参数生成与详情页渲染逻辑:
// articles/[slug]/page.tsx import { getNewsArticles, NewsArticle } from '@/lib/news'; import { notFound } from 'next/navigation'; // 生成静态路由参数,预渲染所有详情页 export async function generateStaticParams() { const articles = await getNewsArticles(); return articles.map(article => ({ slug: article.slug, })); } // 详情页核心组件 export default async function ArticleDetailPage({ params }: { params: { slug: string } }) { // 获取新闻列表(Next.js会自动缓存fetch请求,避免重复调用API) const articles = await getNewsArticles(); // 通过slug匹配对应文章 const article = articles.find(art => art.slug === params.slug); // 无效slug返回404 if (!article) { notFound(); } return ( <div className="max-w-4xl mx-auto p-6"> {/* 来源与发布时间 */} <div className="mb-6 text-sm text-gray-500"> 来源: <a href={article.source.url} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline ml-1" > {article.source.name} </a> <span className="mx-2">|</span> {new Date(article.publishedAt).toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })} </div> {/* 文章标题 */} <h1 className="text-3xl font-bold mb-6">{article.title}</h1> {/* 文章封面图(判断存在性避免错误) */} {article.image && ( <img src={article.image} alt={article.title} className="w-full h-64 object-cover rounded-lg mb-6" /> )} {/* 文章内容区域 */} <div className="prose prose-lg max-w-none"> <p className="text-lg text-gray-700 mb-4">{article.description}</p> <div className="text-gray-800 whitespace-pre-line"> {article.content} </div> </div> {/* 原文跳转链接 */} <div className="mt-8"> <a href={article.url} target="_blank" rel="noopener noreferrer" className="inline-flex items-center text-blue-600 hover:underline" > 查看原文 → </a> </div> </div> ); }
关键注意事项
- 环境变量配置:在
.env.local中添加GNEWS_API_KEY=你的GNews密钥,防止密钥泄露。 - 缓存机制:Next.js会自动缓存静态生成阶段的
fetch请求,不会重复调用GNews API,降低请求成本。 - 样式适配:示例使用Tailwind CSS,若你使用其他样式方案,替换对应的
className即可。 - 异常处理:通过
notFound()处理无效slug场景,返回标准404页面。
内容的提问来源于stack exchange,提问作者betterLateThanNever
相关产品推荐
相关产品推荐

