feat/SW-550 sitemap route
* feat(SW-550): Added rewrites to handle sitemap paths * feat(SW-550): Added sitemap-index generation * feat(SW-550): Added sitemap xml file generation * feat(SW-550): Added feature flag 'HIDE_FOR_NEXT_RELEASE' to sitemap routes Approved-by: Linus Flood
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -11,3 +11,6 @@ node_modules
|
|||||||
|
|
||||||
# Turbo
|
# Turbo
|
||||||
.turbo
|
.turbo
|
||||||
|
|
||||||
|
# Local Netlify folder
|
||||||
|
.netlify
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Lang } from "@/constants/languages"
|
import { Lang } from "@/constants/languages"
|
||||||
import { env } from "@/env/server"
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
|
import { removeTrailingSlash } from "@/utils/url"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
mergeEntriesCounter,
|
mergeEntriesCounter,
|
||||||
mergeEntriesSuccessCounter,
|
mergeEntriesSuccessCounter,
|
||||||
@@ -114,13 +116,11 @@ function mapEntriesToSitemapEntry(entries: SyncItem[]) {
|
|||||||
if (mainEntry) {
|
if (mainEntry) {
|
||||||
const { locale, url } = mainEntry.data
|
const { locale, url } = mainEntry.data
|
||||||
const sitemapEntry: SitemapEntry = {
|
const sitemapEntry: SitemapEntry = {
|
||||||
url: `${env.PUBLIC_URL}/${locale}${url}`,
|
url: removeTrailingSlash(`${env.PUBLIC_URL}/${locale}${url}`),
|
||||||
lastModified,
|
lastModified,
|
||||||
changeFrequency,
|
changeFrequency,
|
||||||
priority,
|
priority,
|
||||||
}
|
alternates,
|
||||||
if (alternates) {
|
|
||||||
sitemapEntry.alternates = alternates
|
|
||||||
}
|
}
|
||||||
return sitemapEntry
|
return sitemapEntry
|
||||||
}
|
}
|
||||||
|
|||||||
50
apps/scandic-web/app/sitemap/[sitemapId]/route.ts
Normal file
50
apps/scandic-web/app/sitemap/[sitemapId]/route.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
|
import { getSitemapDataById } from "@/utils/sitemap"
|
||||||
|
|
||||||
|
import type { NextRequest } from "next/server"
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic"
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
_request: NextRequest,
|
||||||
|
context: { params: { sitemapId: string } }
|
||||||
|
) {
|
||||||
|
if (env.HIDE_FOR_NEXT_RELEASE) {
|
||||||
|
notFound()
|
||||||
|
}
|
||||||
|
|
||||||
|
const sitemapId = context.params.sitemapId
|
||||||
|
if (!sitemapId) {
|
||||||
|
notFound()
|
||||||
|
}
|
||||||
|
|
||||||
|
const sitemapData = await getSitemapDataById(Number(sitemapId))
|
||||||
|
if (!sitemapData.length) {
|
||||||
|
notFound()
|
||||||
|
}
|
||||||
|
|
||||||
|
const entries = sitemapData.map((entry) => {
|
||||||
|
const alternates = Object.entries(entry.alternates).map(
|
||||||
|
([lang, url]) =>
|
||||||
|
`<xhtml:link rel="alternate" hreflang="${lang}" href="${url}" />`
|
||||||
|
)
|
||||||
|
|
||||||
|
return `
|
||||||
|
<url>
|
||||||
|
<loc>${entry.url}</loc>
|
||||||
|
<lastmod>${entry.lastModified}</lastmod>
|
||||||
|
<changefreq>${entry.changeFrequency}</changefreq>
|
||||||
|
<priority>${entry.priority}</priority>
|
||||||
|
${alternates.join("")}
|
||||||
|
</url>`
|
||||||
|
})
|
||||||
|
|
||||||
|
const sitemapXML = `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">${entries.join("")}\n</urlset>`
|
||||||
|
|
||||||
|
return new Response(sitemapXML, {
|
||||||
|
headers: { "Content-Type": "text/xml" },
|
||||||
|
})
|
||||||
|
}
|
||||||
29
apps/scandic-web/app/sitemap/route.ts
Normal file
29
apps/scandic-web/app/sitemap/route.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
|
import { env } from "@/env/server"
|
||||||
|
|
||||||
|
import { getLastUpdated, getSitemapIds } from "@/utils/sitemap"
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic"
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
if (env.HIDE_FOR_NEXT_RELEASE) {
|
||||||
|
notFound()
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastUpdated = await getLastUpdated()
|
||||||
|
const sitemaps = await getSitemapIds()
|
||||||
|
|
||||||
|
const urls = sitemaps.map(
|
||||||
|
(id) => `<sitemap>
|
||||||
|
<loc>${env.PUBLIC_URL}/sitemap-${id}.xml</loc>
|
||||||
|
<lastmod>${lastUpdated}</lastmod>
|
||||||
|
</sitemap>`
|
||||||
|
)
|
||||||
|
|
||||||
|
const sitemapIndexXML = `<?xml version="1.0" encoding="UTF-8"?>\n<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${urls.join("")}\n</sitemapindex>`
|
||||||
|
|
||||||
|
return new Response(sitemapIndexXML, {
|
||||||
|
headers: { "Content-Type": "text/xml" },
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -308,6 +308,14 @@ const nextConfig = {
|
|||||||
source: findMyBooking.sv,
|
source: findMyBooking.sv,
|
||||||
destination: "/sv/hotelreservation/get-booking",
|
destination: "/sv/hotelreservation/get-booking",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
source: `/sitemap-:id(\\d{1,}).xml`,
|
||||||
|
destination: `/sitemap/:id`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: `/sitemap-index.xml`,
|
||||||
|
destination: `/sitemap`,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export interface SitemapEntry {
|
|||||||
lastModified: string
|
lastModified: string
|
||||||
changeFrequency: ChangeFrequency
|
changeFrequency: ChangeFrequency
|
||||||
priority: number
|
priority: number
|
||||||
alternates?: Partial<Record<Lang, string>>
|
alternates: Partial<Record<Lang, string>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SitemapData = SitemapEntry[]
|
export type SitemapData = SitemapEntry[]
|
||||||
|
|||||||
Reference in New Issue
Block a user