nextjs站点地图sitemap添加
app/sitemap.xml/route.ts (主站点地图索引)
sitemap.xml 为文件夹名称
route.ts代码如下:
import { NextResponse } from 'next/server';
import { url } from '@/config/navigation';
export async function GET() {// const entries = generateMonthlyEntries();const xmlContent = `<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><sitemap><loc>${url}/sitemap/static.xml</loc><lastmod>${new Date().toISOString()}</lastmod></sitemap><sitemap><loc>${url}/sitemap/clubes.xml</loc><lastmod>${new Date().toISOString()}</lastmod></sitemap><sitemap><loc>${url}/sitemap/galleries.xml</loc><lastmod>${new Date().toISOString()}</lastmod></sitemap><sitemap><loc>${url}/sitemap/articles.xml</loc><lastmod>${new Date().toISOString()}</lastmod></sitemap></sitemapindex>`;return new NextResponse(xmlContent, {headers: {'Content-Type': 'text/xml; charset=utf-8',},});
}
访问 http://localhost/sitemap.xml 得到 下面效果
app\sitemap\static.xml\route.ts (静态站点地图)
代码如下:
import { NextResponse } from 'next/server';
import { url } from '@/config/navigation';let listStatic: { id: number | string; slug: string; updated: Date }[] = [];
listStatic = [{ id: 1, slug: 'latest-news', updated: new Date() }];const staticHtml = ['en/about-us.html','en/contact-us.html','en/cookies-policy.html','en/privacy-policy.html','sobre-nos.html','contate-nos.html','politica-de-cookies.html','politica-de-privacidade.html',
];staticHtml.forEach((html, index) => {listStatic.push({ id: index, slug: html, updated: new Date() });
});export async function GET() {const xmlContent = `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${listStatic.map((item) => `<url><loc>${url}/${item.slug}</loc><lastmod>${item.updated.toISOString()}</lastmod><changefreq>monthly</changefreq><priority>0.8</priority></url>`).join('')}</urlset>`;return new NextResponse(xmlContent, {headers: {'Content-Type': 'text/xml; charset=utf-8',},});
}
访问 http://localhost/sitemap/static.xml 得到 下面效果
动态接口请求
app\sitemap\[dynamic]\route.ts
代码如下:
// src/app/sitemap/[dynamic]/route.ts
import { NextResponse } from 'next/server';import { seoApi } from '@/lib/http/api/seo';function convertDate(inputDate: any) {// 创建一个 Date 对象const date = new Date(inputDate);// 获取年、月、日、时、分、秒const year = date.getUTCFullYear();const month = String(date.getUTCMonth() + 1).padStart(2, '0'); // 月份从 0 开始,需要加 1const day = String(date.getUTCDate()).padStart(2, '0');const hours = String(date.getUTCHours()).padStart(2, '0');const minutes = String(date.getUTCMinutes()).padStart(2, '0');const seconds = String(date.getUTCSeconds()).padStart(2, '0');// 获取时区偏移量(以分钟为单位)const offset = date.getTimezoneOffset();const offsetSign = offset > 0 ? '-' : '+';const offsetHours = String(Math.floor(Math.abs(offset) / 60)).padStart(2, '0');const offsetMinutes = String(Math.abs(offset) % 60).padStart(2, '0');// 构造目标格式的日期字符串const formattedDate = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}${offsetSign}${offsetHours}:${offsetMinutes}`;return formattedDate;
}export async function GET(request: Request, { params }: { params: { dynamic: string } }) {// 解析动态路径参数const pattern = /sitemap-articles-(\d{4})-(\d{2})\.xml/;const match = params.dynamic.match(pattern);if (!match) {return new NextResponse('Invalid sitemap format', {status: 400,headers: { 'Content-Type': 'text/plain' },});}const [, year, month] = match;let start_date = `${year}-${month}-01`;let end_date = `${year}-${month}-31`;if (month === '02') {end_date = `${year}-${month}-28`; // 假设不是闰年}if (month === '04' || month === '06' || month === '09' || month === '11') {end_date = `${year}-${month}-30`; // 30天的月份}const response = await seoApi.getsitemap({start_date: start_date,end_date: end_date,});// 获取当月数据(示例数据)const articles = response.list;const xmlContent = `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${articles.map((article) => `<url><loc>https://example.com/articles/${article.jump_url}</loc><lastmod>${convertDate(article.publish_time)}</lastmod><changefreq>daily</changefreq><priority>0.8</priority></url>`).join('')}</urlset>`;return new NextResponse(xmlContent, {headers: {'Content-Type': 'text/xml; charset=utf-8','Cache-Control': 'public, max-age=86400',},});
}
效果如下