بهینهسازی سئو در Next.js: راهنمای کامل برای کسب رتبهٔ بالاتر
سئو برای موفقیت هر وبسایتی حیاتی است. Next.js ابزارهای قدرتمندی برای ساخت اپلیکیشنهای سازگار با سئو در اختیارتان میگذارد. این راهنما همهچیز را — از متادیتای پایه تا تکنیکهای پیشرفتهٔ بهینهسازی — پوشش میدهد.
Metadata API در Next.js 15
متادیتای استاتیک
// app/page.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Home | My Website',
description: 'Welcome to my website. We offer the best products and services.',
keywords: ['products', 'services', 'quality'],
authors: [{ name: 'John Doe', url: 'https://johndoe.com' }],
creator: 'John Doe',
publisher: 'My Company',
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
openGraph: {
type: 'website',
locale: 'en_US',
url: 'https://mywebsite.com',
siteName: 'My Website',
title: 'Home | My Website',
description: 'Welcome to my website',
images: [
{
url: 'https://mywebsite.com/og-image.jpg',
width: 1200,
height: 630,
alt: 'My Website',
},
],
},
twitter: {
card: 'summary_large_image',
title: 'Home | My Website',
description: 'Welcome to my website',
creator: '@johndoe',
images: ['https://mywebsite.com/twitter-image.jpg'],
},
alternates: {
canonical: 'https://mywebsite.com',
languages: {
'en-US': 'https://mywebsite.com/en',
'fa-IR': 'https://mywebsite.com/fa',
},
},
};
export default function HomePage() {
return <main>...</main>;
}<Callout type="info"> برای اینکه پیشنمایش بهتری هنگام اشتراکگذاری در شبکههای اجتماعی داشته باشید، همیشه متادیتای Open Graph و Twitter Card را اضافه کنید. </Callout>
متادیتای داینامیک
// app/blog/[slug]/page.tsx
import type { Metadata } from 'next';
import { getPostBySlug } from '@/lib/posts';
interface Props {
params: { slug: string };
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const post = await getPostBySlug(params.slug);
if (!post) {
return {
title: 'Post Not Found',
};
}
return {
title: `${post.title} | My Blog`,
description: post.excerpt,
authors: [{ name: post.author.name }],
openGraph: {
type: 'article',
title: post.title,
description: post.excerpt,
url: `https://mywebsite.com/blog/${params.slug}`,
publishedTime: post.publishedAt,
modifiedTime: post.updatedAt,
authors: [post.author.name],
images: [
{
url: post.coverImage,
width: 1200,
height: 630,
alt: post.title,
},
],
tags: post.tags,
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.excerpt,
images: [post.coverImage],
},
};
}قالب متادیتا
// app/layout.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
metadataBase: new URL('https://mywebsite.com'),
title: {
default: 'My Website',
template: '%s | My Website', // Dynamic pages will use this template
},
description: 'Default description for my website',
openGraph: {
type: 'website',
siteName: 'My Website',
},
};دادهٔ ساختیافته (JSON-LD)
اسکیمای Organization
// components/StructuredData.tsx
export function OrganizationSchema() {
const schema = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'My Company',
url: 'https://mywebsite.com',
logo: 'https://mywebsite.com/logo.png',
sameAs: [
'https://twitter.com/mycompany',
'https://linkedin.com/company/mycompany',
'https://github.com/mycompany',
],
contactPoint: {
'@type': 'ContactPoint',
telephone: '+1-555-555-5555',
contactType: 'customer service',
availableLanguage: ['English', 'Persian'],
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}اسکیمای Article
// components/ArticleSchema.tsx
interface ArticleSchemaProps {
title: string;
description: string;
image: string;
datePublished: string;
dateModified: string;
author: {
name: string;
url: string;
};
url: string;
}
export function ArticleSchema({
title,
description,
image,
datePublished,
dateModified,
author,
url,
}: ArticleSchemaProps) {
const schema = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: title,
description: description,
image: image,
datePublished: datePublished,
dateModified: dateModified,
author: {
'@type': 'Person',
name: author.name,
url: author.url,
},
publisher: {
'@type': 'Organization',
name: 'My Website',
logo: {
'@type': 'ImageObject',
url: 'https://mywebsite.com/logo.png',
},
},
mainEntityOfPage: {
'@type': 'WebPage',
'@id': url,
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}<Note title="نکتهٔ اسکیما"> برای اعتبارسنجی دادهٔ ساختیافتهٔ خود از ابزار Rich Results Test گوگل استفاده کنید: https://search.google.com/test/rich-results </Note>
اسکیمای Product برای فروشگاه اینترنتی
export function ProductSchema({ product }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
description: product.description,
image: product.images,
sku: product.sku,
brand: {
'@type': 'Brand',
name: product.brand,
},
offers: {
'@type': 'Offer',
url: `https://mywebsite.com/products/${product.slug}`,
priceCurrency: 'USD',
price: product.price,
availability: product.inStock
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
seller: {
'@type': 'Organization',
name: 'My Store',
},
},
aggregateRating: product.reviews.length > 0 ? {
'@type': 'AggregateRating',
ratingValue: product.averageRating,
reviewCount: product.reviews.length,
} : undefined,
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}تولید نقشهٔ سایت (Sitemap)
نقشهٔ سایت داینامیک
// app/sitemap.ts
import { MetadataRoute } from 'next';
import { getAllPosts } from '@/lib/posts';
import { getAllProducts } from '@/lib/products';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = 'https://mywebsite.com';
// Static pages
const staticPages = [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: 'daily' as const,
priority: 1,
},
{
url: `${baseUrl}/about`,
lastModified: new Date(),
changeFrequency: 'monthly' as const,
priority: 0.8,
},
{
url: `${baseUrl}/contact`,
lastModified: new Date(),
changeFrequency: 'monthly' as const,
priority: 0.8,
},
];
// Blog posts
const posts = await getAllPosts();
const blogPages = posts.map((post) => ({
url: `${baseUrl}/blog/${post.slug}`,
lastModified: new Date(post.updatedAt),
changeFrequency: 'weekly' as const,
priority: 0.7,
}));
// Products
const products = await getAllProducts();
const productPages = products.map((product) => ({
url: `${baseUrl}/products/${product.slug}`,
lastModified: new Date(product.updatedAt),
changeFrequency: 'daily' as const,
priority: 0.9,
}));
return [...staticPages, ...blogPages, ...productPages];
}Robots.txt
// app/robots.ts
import { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: ['/api/', '/admin/', '/private/'],
},
{
userAgent: 'Googlebot',
allow: '/',
disallow: '/api/',
},
],
sitemap: 'https://mywebsite.com/sitemap.xml',
};
}بهینهسازی Core Web Vitals
بهینهسازی تصاویر
import Image from 'next/image';
// Optimized image component
export function OptimizedImage({ src, alt, priority = false }) {
return (
<Image
src={src}
alt={alt}
width={800}
height={600}
priority={priority} // Set true for above-the-fold images
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
className="object-cover"
/>
);
}
// Hero image with priority loading
export function HeroSection() {
return (
<section>
<Image
src="/hero.jpg"
alt="Hero image"
fill
priority // Critical for LCP
sizes="100vw"
className="object-cover"
/>
</section>
);
}بهینهسازی فونتها
// app/layout.tsx
import { Inter, Vazirmatn } from 'next/font/google';
const inter = Inter({
subsets: ['latin'],
display: 'swap',
variable: '--font-inter',
});
const vazirmatn = Vazirmatn({
subsets: ['arabic'],
display: 'swap',
variable: '--font-vazirmatn',
});
export default function RootLayout({ children }) {
return (
<html className={`${inter.variable} ${vazirmatn.variable}`}>
<body>{children}</body>
</html>
);
}بهینهسازی اسکریپتها
import Script from 'next/script';
export function Analytics() {
return (
<>
{/* Load after page is interactive */}
<Script
src="https://www.googletagmanager.com/gtag/js?id=GA_ID"
strategy="afterInteractive"
/>
<Script id="google-analytics" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'GA_ID');
`}
</Script>
{/* Load when browser is idle */}
<Script
src="https://third-party-script.js"
strategy="lazyOnload"
/>
</>
);
}سئو برای سایتهای چندزبانه
تگهای Hreflang
// app/[locale]/layout.tsx
import type { Metadata } from 'next';
export async function generateMetadata({ params }): Promise<Metadata> {
const { locale } = params;
return {
alternates: {
canonical: `https://mywebsite.com/${locale}`,
languages: {
'en': 'https://mywebsite.com/en',
'fa': 'https://mywebsite.com/fa',
'x-default': 'https://mywebsite.com/en',
},
},
};
}نقشهٔ سایت بومیسازیشده
// app/sitemap.ts
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const locales = ['en', 'fa'];
const baseUrl = 'https://mywebsite.com';
const pages = ['', '/about', '/contact', '/blog'];
return pages.flatMap((page) =>
locales.map((locale) => ({
url: `${baseUrl}/${locale}${page}`,
lastModified: new Date(),
alternates: {
languages: Object.fromEntries(
locales.map((l) => [l, `${baseUrl}/${l}${page}`])
),
},
}))
);
}مانیتورینگ عملکرد
ردیابی Web Vitals
// app/components/WebVitals.tsx
'use client';
import { useReportWebVitals } from 'next/web-vitals';
export function WebVitals() {
useReportWebVitals((metric) => {
// Send to analytics
const body = JSON.stringify({
name: metric.name,
value: metric.value,
rating: metric.rating,
delta: metric.delta,
id: metric.id,
});
// Use sendBeacon for reliability
if (navigator.sendBeacon) {
navigator.sendBeacon('/api/analytics/vitals', body);
} else {
fetch('/api/analytics/vitals', {
body,
method: 'POST',
keepalive: true,
});
}
});
return null;
}جمعبندی
سئو در Next.js یعنی ترکیب بهینهسازی فنی با محتوای باکیفیت. با پیادهسازی درست متادیتا، دادهٔ ساختیافته، نقشهٔ سایت و بهینهسازی Core Web Vitals میتوانید رتبهٔ خود را در موتورهای جستجو بهشکل چشمگیری بهبود دهید.
نکات کلیدی:
- برای داشتن متاتگهای جامع از Metadata API استفاده کنید
- برای نمایش نتایج غنی در جستجو، دادهٔ ساختیافته پیادهسازی کنید
- برای همهٔ محتوا نقشهٔ سایت داینامیک تولید کنید
- تصاویر، فونتها و اسکریپتها را برای Core Web Vitals بهینه کنید
- چندزبانگی را با تگهای hreflang صحیح مدیریت کنید
این یادداشت ترجمهٔ فارسی نوشتهٔ خودم است — نسخهٔ اصلی (انگلیسی) در dev.to