Next.js Sitemap Oluşturma
Next.js'de daha iyi SEO için otomatik sitemap oluşturucu nasıl yapılır?
cFyt tarafından
yazıldı.3786 görüntülenmeNext.js bir full stack react framework'ü olarak oldukça popüler. Şahsen en çok kullandığım ve bence en iyisi. Peki sizce de sitemap oluşturmak için eklentisi olması gerekmiyor mu ? Aslında sitemap.xml oluşturmak için yöntemler var fakat bunlar otomatik olarak yapmıyor. Tabi ki benim de kullandığım otomatik olarak oluşturulan dinamik yöntemi sizlerle paylaşıcam.
Paketler
Kullanacağımız bir paket olacak öncelikle bunu indirmemiz gerekiyor.
- next-sitemap
npm
$ npm i next-sitemap
yarn
$ yarn add next-sitemap
Sayfamızı oluşturalım
pages
klasörü altına sitemap.xml.js
veya sitemap.xml
adlı klasör açıp içerisine index.js
dosyamızı oluşturalım.
import { getServerSideSitemap } from 'next-sitemap' import fs from 'fs' import path from 'path'
Bize gerekli olan import işlemleri bu şekilde.
İçerisinde bir şey olmayan default bir function oluşturalım.
export default function SitemapIndex() { }
Yapacağımız işlemler server-side olacağı için bu fonksiyonun bir şey döndürmesine gerek yok.
export const getServerSideProps = async (ctx) => {}
Sayfa render olmadan bu fonksiyon içerisinde bir return işlemi yapacağız. Fakat önce ne yaptığımızı anlayalım.
export const getServerSideProps = async (ctx) => { return getServerSideSitemap(ctx, [{ loc: 'https://cfyt.me', lastmod: new Date().toISOString() }]) }
Bu işlemin sonucunda sayfamız böyle gözükecek
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"> <url> <loc>https://cfyt.me</loc> <lastmod>2022-10-10T12:17:43.162Z</lastmod> </url> </urlset>
Anlayacağınız verdiğimiz array içerisindeki değerleri xml formatında bir çıktı veriyor. https://example.com/sitemap.xml
adresinde oluştuğu için static bir dosyaymış gibi her istekte işlenecek. Şimdi ise tüm sayfalarımızı otomatik olarak ekleyelim.
let pagePath = "" if (process.env.NODE_ENV === 'production') { pagePath = path.join(process.cwd(), '.next', 'server', 'pages-manifest.json') } else { pagePath = path.join(process.cwd(), 'pages') }
pages
klasörü altındaki dosyalarımıza erişmek istiyoruz. Vercel'de yayınlarken ise bu dosyalar oluşmuyor ve var olan sayfaları tespit etmek zorlaşıyor. Build işlemi sornası oluşan pages-manifest.json
dosyası tüm oluşturulan sayfaların bilgisini içeriyor.
{ "/_app": "pages/_app.js", "/_error": "pages/_error.js", "/_document": "pages/_document.js", "/about": "pages/about.html", "/contact": "pages/contact.html", "/": "pages/index.html", "/portfolio": "pages/portfolio.html", "/projects": "pages/projects.html", "/support": "pages/support.html", "/blog": "pages/blog.js", "/profile": "pages/profile.js", "/blog/[id]": "pages/blog/[id].js", "/sitemap.xml": "pages/sitemap.xml.js", "/404": "pages/404.html" }
let urls = [] if (process.env.NODE_ENV === 'production') { const routes = JSON.parse(fs.readFileSync(pagePath, 'utf8')) let keys = Object.keys(routes) console.log(fs.statSync(pagePath)) console.log(routes) let date = new Date() keys.forEach((route) => { if (route !== '/sitemap.xml' && !route.includes('dashboard') && !route.includes('api') && !route.includes('_') && !route.includes('[') && !route.includes('404')) { urls.push({ loc: `https://cfyt.me${route}`, lastmod: date.toISOString(), priority: route === '/' ? 1 : 0.5, }) } }) }
Projemiz production
ortamındayken bu verileri array içerisinde tutuyoruz. Dosyasımızı açıp bazı filtrelemelerden geçiriyoruz. Dosyada oluşan bazı yolları eklemememiz gerek. Bunları kendiniz de belirleyebilirsiniz. Array içerisine loc
lastmod
priority
gibi değerler ile ekliyoruz. loc değeri urlyi belirtiyor. lastmod son değiştirilme tarihini. Burada son değiştirilme tarihini bulamadığımız için şuanki zamanı giriyoruz. priority ise öncelik değeridir. 0 ile 1 arasında değer alır ve sayfaların önceliğini belirler.
} else { urls = fs.readdirSync(pagePath).filter(x => !x.includes('_') && !x.includes('sitemap') && !x.includes('index') && !x.includes('api') && !x.includes('dashboard')).map(f => ({ loc: `https://cfyt.me/${f.split('.')[0]}`, lastmod: new Date(fs.statSync(`${pagePath}/${f}`).mtime).toISOString(), })) urls = [{ loc: 'https://cfyt.me', lastmod: new Date(fs.statSync(`${pagePath}/index.js`).mtime).toISOString(), priority: 1, }, ...urls] }
Burada ise benzer işlemi development ortamı için yapıyoruz. (Ben development ortamında bunu oluşturmayacağım diyorsanız esgeçebilirsiniz). Buradaki mantık ise oldukça basit. Tüm pages klasörü altındaki dosyalarımı alıp array içerisine ekliyoruz. Buradaki tek fark dosyaların en son ne zaman değiştirildiğini görebilmek. (fs.statSync
)
Eğer farklı klasörleme yapısı kullanıyorsanız klasör içerisindeki dosyalarınızı da eklemeniz gerek. Bunu yapmak ise basit size bırakıyorum :)
Şimdi ise fikir olması amacıyla dinamik url yollarını ekleyelim.
let client = await clientPromise let db = await client.db('blog') let posts = await db.collection('posts').find({}).toArray() posts.forEach((post) => { urls.push({ loc: `https://cfyt.me/blog/${post.title.toLowerCase().replace(/ /g, '-')}`, lastmod: new Date(post.date).toISOString(), }) })
Burada ise tüm blog verileri alıp teker teker url olarak ekliyoruz. Sizde yoksa veya farklı bir projeniz var ise buna göre ayarlayabilirsiniz.
return getServerSideSitemap(ctx, urls)
ve son olarak urllerimizi ekliyip return ediyoruz.
Son Görüntü
import { getServerSideSitemap } from 'next-sitemap' import fs from 'fs' import path from 'path' import clientPromise from 'lib/mongodb' export const getServerSideProps = async (ctx) => { let pagePath = "" if (process.env.NODE_ENV === 'production') { pagePath = path.join(process.cwd(), '.next', 'server', 'pages-manifest.json') } else { pagePath = path.join(process.cwd(), 'pages') } let urls = [] if (process.env.NODE_ENV === 'production') { const routes = JSON.parse(fs.readFileSync(pagePath, 'utf8')) let keys = Object.keys(routes) console.log(fs.statSync(pagePath)) console.log(routes) let date = new Date() keys.forEach((route) => { if (route !== '/sitemap.xml' && !route.includes('dashboard') && !route.includes('api') && !route.includes('_') && !route.includes('[') && !route.includes('404')) { urls.push({ loc: `https://cfyt.me${route}`, lastmod: date.toISOString(), priority: route === '/' ? 1 : 0.5, }) } }) } else { urls = fs.readdirSync(pagePath).filter(x => !x.includes('_') && !x.includes('sitemap') && !x.includes('index') && !x.includes('api') && !x.includes('dashboard')).map(f => ({ loc: `https://cfyt.me/${f.split('.')[0]}`, lastmod: new Date(fs.statSync(`${pagePath}/${f}`).mtime).toISOString(), })) urls = [{ loc: 'https://cfyt.me', lastmod: new Date(fs.statSync(`${pagePath}/index.js`).mtime).toISOString(), priority: 1, }, ...urls] } let client = await clientPromise let db = await client.db('blog') let posts = await db.collection('posts').find({}).toArray() posts.forEach((post) => { urls.push({ loc: `https://cfyt.me/blog/${post.title.toLowerCase().replace(/ /g, '-')}`, lastmod: new Date(post.date).toISOString(), priority: 0.9, }) }) return getServerSideSitemap(ctx, urls) } export default function SitemapIndex() { }
Çıktı:
https://cfyt.me/sitemap.xml
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"> <url> <loc>https://cfyt.me/about</loc> <lastmod>2022-10-14T15:38:54.488Z</lastmod> <priority>0.5</priority> </url> <url> <loc>https://cfyt.me/contact</loc> <lastmod>2022-10-14T15:38:54.488Z</lastmod> <priority>0.5</priority> </url> <url> <loc>https://cfyt.me/</loc> <lastmod>2022-10-14T15:38:54.488Z</lastmod> <priority>1</priority> </url> <url> <loc>https://cfyt.me/portfolio</loc> <lastmod>2022-10-14T15:38:54.488Z</lastmod> <priority>0.5</priority> </url> <url> <loc>https://cfyt.me/projects</loc> <lastmod>2022-10-14T15:38:54.488Z</lastmod> <priority>0.5</priority> </url> <url> <loc>https://cfyt.me/support</loc> <lastmod>2022-10-14T15:38:54.488Z</lastmod> <priority>0.5</priority> </url> <url> <loc>https://cfyt.me/blog</loc> <lastmod>2022-10-14T15:38:54.488Z</lastmod> <priority>0.5</priority> </url> <url> <loc>https://cfyt.me/profile</loc> <lastmod>2022-10-14T15:38:54.488Z</lastmod> <priority>0.5</priority> </url> <url> <loc>https://cfyt.me/blog/arrow-functions</loc> <lastmod>2022-10-07T14:01:30.288Z</lastmod> <priority>0.9</priority> </url> <url> <loc>https://cfyt.me/blog/dall-e-herkese-açık-hale-geldi</loc> <lastmod>2022-10-08T14:01:30.288Z</lastmod> <priority>0.9</priority> </url> <url> <loc>https://cfyt.me/blog/next.js-sitemap-oluşturma</loc> <lastmod>2022-10-10T12:42:54.846Z</lastmod> <priority>0.9</priority> </url> </urlset>
Robots.txt
robots.txt
dosyasını ise public
klasörü altında oluşturalım.
User-Agent: * Allow: Sitemap: https://cfyt.me/sitemap.xml
Sitemap urlmizi belirtiyoruz ve artık arama motoru botları sitemizi daha iyi bir şekilde indexliyor.
Umarım işinize yaramıştır.
Yorumlar
Yorum yapabilmek için giriş yapmalısınız.
Henüz yorum yapılmamış.