Skip to content

Large Sitemaps

When your site has thousands of URLs, the plugin automatically handles sitemap splitting according to Google's guidelines.

Automatic Splitting

The plugin automatically splits sitemaps when they exceed:

  • 50,000 URLs per sitemap file
  • 45 MB file size (with 5 MB buffer from Google's 50 MB limit)

No configuration required - it just works.

How It Works

When splitting is triggered:

  1. Routes are distributed across multiple sitemap files
  2. Each file is named sequentially: sitemap-0.xml, sitemap-1.xml, etc.
  3. A sitemap-index.xml is generated referencing all sitemap files

Example Output

For a site with 120,000 URLs:

dist/
├── sitemap-0.xml        # URLs 1-50,000
├── sitemap-1.xml        # URLs 50,001-100,000
├── sitemap-2.xml        # URLs 100,001-120,000
└── sitemap-index.xml    # References all sitemaps

Generated Index File

xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <sitemap>
    <loc>https://example.com/sitemap-0.xml</loc>
    <lastmod>2025-01-15</lastmod>
  </sitemap>
  <sitemap>
    <loc>https://example.com/sitemap-1.xml</loc>
    <lastmod>2025-01-15</lastmod>
  </sitemap>
  <sitemap>
    <loc>https://example.com/sitemap-2.xml</loc>
    <lastmod>2025-01-15</lastmod>
  </sitemap>
</sitemapindex>

Named Exports with Splitting

When using named exports, each export can be split independently:

typescript
// Large product catalog
export async function products(): Promise<Route[]> {
  // Returns 75,000 routes
  return await fetchAllProducts();
}

// Large blog archive
export async function blog(): Promise<Route[]> {
  // Returns 60,000 routes
  return await fetchAllPosts();
}

Output:

dist/
├── sitemap-products-0.xml    # Products 1-50,000
├── sitemap-products-1.xml    # Products 50,001-75,000
├── sitemap-blog-0.xml        # Posts 1-50,000
├── sitemap-blog-1.xml        # Posts 50,001-60,000
└── sitemap-index.xml         # References all 4 sitemaps

Performance Considerations

Memory Usage

For extremely large sitemaps, consider:

  1. Streaming data - Don't load all routes into memory at once
  2. Pagination - Fetch routes in batches
typescript
export default async function getRoutes(): Promise<Route[]> {
  const routes: Route[] = [];
  let page = 1;
  const pageSize = 10000;

  while (true) {
    const batch = await fetchRoutes({ page, pageSize });
    if (batch.length === 0) break;

    routes.push(...batch);
    page++;
  }

  return routes;
}

Build Time

Large sitemaps increase build time. To optimize:

  1. Cache API responses - Store fetched data locally during development
  2. Parallel fetching - Use Promise.all for independent data sources
typescript
export default async function getRoutes(): Promise<Route[]> {
  // Parallel fetching
  const [products, posts, pages] = await Promise.all([fetchProducts(), fetchPosts(), fetchPages()]);

  return [...products, ...posts, ...pages];
}

robots.txt with Split Sitemaps

When generateRobotsTxt is enabled with split sitemaps, the Sitemap directive points to the index file:

txt
User-agent: *
Allow: /

Sitemap: https://example.com/sitemap-index.xml

Monitoring Sitemap Size

Use the CLI to check sitemap sizes without building:

bash
vite-sitemap preview --verbose

Output shows size information:

bash
 Preview: default (75,000 routes)

Size: 12.4 MB
Routes: 75,000

 Sitemap will be split into 2 files (exceeds 50,000 URL limit)

Google Search Console

After deploying split sitemaps:

  1. Submit sitemap-index.xml to Google Search Console
  2. Google will automatically discover all child sitemaps
  3. Monitor indexing status for each sitemap file

Best Practices

  1. Use the index file - Always submit the index, not individual sitemaps
  2. Keep URLs consistent - Don't change URL structures between builds
  3. Update incrementally - Only regenerate sitemaps when content changes
  4. Monitor coverage - Check Search Console for indexing issues

Released under the MIT License.