Closed JanWerder closed 9 months ago
Like you hinted at, in the alternatives, it's fairly straightforward to build out your own sitemap generation. So just for reference, an implementation idea that might work for you, using sitemap.. This assumes you have srcDir: './pages'
set.
const fs = require('fs')
const path = require('path')
const fg = require('fast-glob')
const { SitemapStream, streamToPromise } = require('sitemap')
console.log('Start building sitemap..')
const linksStream = fg.stream(['./pages/*.md'])
.map((filePath) => ({ url: filePath.replace('pages/', '').replace(/\.md$/, '.html') }))
const sitemapStream = new SitemapStream({ hostname: 'https://www.example.org' })
// Return a promise that resolves with your XML string
streamToPromise(linksStream.pipe(sitemapStream)).then((sitemap) => {
fs.writeFileSync(
path.resolve(__dirname, '../pages/public/sitemap.xml'),
sitemap,
)
})
Note that this uses Stream#readable.map, which is a brand new node feature, but you also implement it differently, if you don't want to rely on a experimental api.
It's also possible to use something like gray-matter
, to include your meta data in your sitemaps, if needed.
If it can help, i have done a sitemap.xml and robots.txt generator using typescript: sitemap-ts
.
This plugin was created and externalized from vite-ssg-sitemap ans is also used in vite-plugin-sitemap.
@jbaubree amazing, I'll check it out
any status on this?
@lmtr0 We need to wait next release of Vitepress with this pushed https://github.com/vuejs/vitepress/pull/709. We will be able to configure like that :
// .vitepress/config.ts
import { version } from '../../../../packages/snap-design/package.json'
import { generateSitemap as sitemap } from 'sitemap-ts'
export default {
vite: {
buildEnd: () => {
sitemap()
},
},
}
understood, for now a simple script solves my problem, thanks
On newer versions of VitePress this can be done (there is no need to traverse the dist directory):
import { createWriteStream } from 'node:fs'
import { resolve } from 'node:path'
import { SitemapStream } from 'sitemap'
import { defineConfig } from 'vitepress'
const links = []
export default {
// ...
transformHtml: (_, id, { pageData }) => {
if (!/[\\/]404\.html$/.test(id))
links.push({
// you might need to change this if not using clean urls mode
url: pageData.relativePath.replace(/((^|\/)index)?\.md$/, '$2'),
lastmod: pageData.lastUpdated
})
},
buildEnd: ({ outDir }) => {
const sitemap = new SitemapStream({ hostname: 'https://vitepress.vuejs.org/' })
const writeStream = createWriteStream(resolve(outDir, 'sitemap.xml'))
sitemap.pipe(writeStream)
links.forEach((link) => sitemap.write(link))
sitemap.end()
}
}
if not using clean urls mode, you can use this transformHtml
transformHtml: (_, id, { pageData }) => {
if (!/[\\/]404\.html$/.test(id))
links.push({
url: pageData.relativePath.replace(/\.md$/, '.html'),
lastmod: pageData.lastUpdated
})
},
Since release of 1.0.0-alpha.23 the script above does not create a file anymore even though the script runs through as far as I can judge.
Could it be that the buildEnd hook behaves differently than before? The bugfix "build: explicitly exit process after build to prevent hangup" sounds suspicious.
Ah right, it is exiting the process before stream can finish. Try this for now:
buildEnd: async ({ outDir }) => {
const sitemap = new SitemapStream({
hostname: 'https://vitepress.vuejs.org/'
})
const writeStream = createWriteStream(resolve(outDir, 'sitemap.xml'))
sitemap.pipe(writeStream)
links.forEach((link) => sitemap.write(link))
sitemap.end()
await new Promise((r) => writeStream.on('finish', r))
}
@brc-dd Maybe it would be useful if you can specify in the config file if a sitemap should be generated automatically or not.
@brc-dd Maybe it would be useful if you can specify in the config file if a sitemap should be generated automatically or not.
any updates on this?
now I'm at "vitepress": "^1.0.0-alpha.27", "vue": "^3.2.41"
Which way to make sitemaps is the most beginner friendly method?
Which way to make sitemaps is the most beginner friendly method?
Someone might find it usefull as people want to come and grab working snippet.
I'm on "vitepress": "1.0.0-alpha.75"
and seems it generates good sitemap.xml
ht for @brc-dd updates!
import { createWriteStream } from 'node:fs'
import { resolve } from 'node:path'
import { SitemapStream } from 'sitemap'
import { defineConfig } from 'vitepress'
const links = []
// ...
export default defineConfig({
transformHtml: (_, id, { pageData }) => {
if (!/[\\/]404\.html$/.test(id))
links.push({
// you might need to change this if not using clean urls mode
url: pageData.relativePath.replace(/((^|\/)index)?\.md$/, '$2'),
lastmod: pageData.lastUpdated
})
},
buildEnd: async ({ outDir }) => {
const sitemap = new SitemapStream({
hostname: 'https://subwork.xyz/'
})
const writeStream = createWriteStream(resolve(outDir, 'sitemap.xml'))
sitemap.pipe(writeStream)
links.forEach((link) => sitemap.write(link))
sitemap.end()
await new Promise((r) => writeStream.on('finish', r))
},
If you are not using clean URLs mode, you can write it like this:
transformHtml: (_, id, { pageData }) => {
if (!/[\\/]404\.html$/.test(id)) {
links.push({
url: pageData.relativePath.replace(/\/index\.md$/, '/').replace(/\.md$/, '.html'),
lastmod: pageData.lastUpdated,
})
}
},
Is your feature request related to a problem? Please describe.
vitepress does not generate a sitemap.xml
Describe the solution you'd like
vitepress should generate a sitemap based on the config.js
Describe alternatives you've considered
The user could create a sitemap by hand
Additional context
No response
Validations