بهینهسازی سئو در Next.js: راهنمای کامل برای کسب رتبهٔ بالاتر
سئو برای موفقیت هر وبسایتی حیاتی است. 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