Automatic Site Maps in Svelte
Autogenerate a sitemap
Let's update our sitemap generation code to produce clean URLs without the "/src/routes" prefix:
// src/routes/sitemap.xml/+server.js
import { readdirSync, statSync } from 'fs';
import { join, relative } from 'path';
function getRoutes(dir) {
const baseDir = join(process.cwd(), 'src', 'routes');
const routes = [];
function traverse(currentDir) {
const files = readdirSync(currentDir);
files.forEach(file => {
const filePath = join(currentDir, file);
const stat = statSync(filePath);
if (stat.isDirectory()) {
traverse(filePath);
} else if (file === '+page.svelte') {
let route = '/' + relative(baseDir, currentDir)
.split('\\')
.join('/');
// Handle index routes
route = route === '/.' ? '/' : route;
routes.push(route);
}
});
}
traverse(baseDir);
return routes;
}
export async function GET() {
const routes = getRoutes('src/routes');
const body = `
<?xml version="1.0" encoding="UTF-8" ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${routes.map(route => `
<url>
<loc>https://example.com${route}</loc>
</url>
`).join('')}
</urlset>
`.trim();
return new Response(body, {
headers: {
'Content-Type': 'application/xml'
}
});
}
Let's break down the changes and explain how this solves the problem:
We import the
relative
function from thepath
module. This will help us get the relative path from the base directory to each route.In the
getRoutes
function:We define
baseDir
as the absolute path to the 'src/routes' directory.We use a nested
traverse
function to recursively go through the directories.For each '+page.svelte' file, we calculate the route by getting the relative path from
baseDir
to the current directory.We replace backslashes with forward slashes to ensure consistent URL formatting.
We handle the root route ('/') separately by checking if the relative path is '.'.
We've removed any hardcoded 'src/routes' parts from the URL generation process.
This improved version should generate clean URLs for your sitemap, like:
<url>
<loc>https://example.com/</loc>
</url>
<url>
<loc>https://example.com/about</loc>
</url>
<url>
<loc>https://example.com/testpage</loc>
</url>
Handling Dynamic Content
If you need to include dynamic content, you can still add it as before:
async function getBlogPosts() {
// Fetch blog posts from your API or database
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return posts.map(post => `/blog/${post.slug}`);
}
export async function GET() {
const staticRoutes = getRoutes('src/routes');
const blogPosts = await getBlogPosts();
const allRoutes = [...staticRoutes, ...blogPosts];
// Generate XML as before
}
Automating Updates
To keep your sitemap up-to-date, consider these options:
Generate the sitemap during the build process.
Use a serverless function to regenerate the sitemap periodically.
Trigger sitemap regeneration when content is updated.
For example, add a build script to your package.json
:
{
"scripts": {
"build": "vite build && node generate-sitemap.js"
}
}
Then create a generate-sitemap.js
file that uses this logic to create a static sitemap.xml file during builds.
By implementing these improvements, you'll have a robust, automated sitemap generation system for your SvelteKit project that produces clean URLs without the "/src/routes" prefix, ensuring search engines always have the most up-to-date and accurate information about your site structure.
Citations: [1] https://example.com/src/routes/testpage
Last updated