You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 23:25:13