SvelteKit 服务器端渲染:创建 XML 响应

SvelteKit server-side rendering: creating XML responses

如何使用 SvelteKit 渲染 XML 或其他非 HTML 输出?我想使用 SvelteKit 为我的博客呈现 Google sitemap.xml 和 RSS 提要。

您将创建一个端点并定义一个不同的 Content-Type:

// example.xml.js
export async function get() {
  const xml = 
`<?xml version="1.0" encoding="UTF-8"?>
<data>
  <field>This is an example</field>
</data>
`
  return {
    status: 200,
    body: xml,
    headers: {
      'Content-Type': 'application/xml'
    }
  }
}

替代方法

如果你愿意,你可以创建一个常规路由,你可以在其中使用 Svelte 组件并劫持 handle 挂钩中的渲染,但这种方法非常脆弱,因为简单地更改 headers 不是足够了,该文件仍将被渲染,其他通常与它周围的 html 页面相关联的绒毛(如 body 和 head 标签)所以你必须先找到一种方法将它们剪掉。

<!-- example.xml.svelte -->
<script>
  let value = 0
</script>
<data>
  <field>{value}</field>
</data>
// hooks.js
export async function handle({ request, resolve }) {
    const response = await resolve(request)

    if (request.path.endsWith('.xml')) {        
        // Set the content type to xml
        response.headers["content-type"] = "application/xml"

        // remove whitespace
        response.body = response.body.replaceAll('\n','')
        response.body = response.body.replaceAll('\t','')

        // find the body tags if present
        const start = response.body.indexOf('<body>')
        const stop = response.body.indexOf('</body>')
        if (start > 0 && stop > 0) {
            // only show the content of the body
            response.body = response.body.substring(start + 6, stop)
        }
    }
    return { 
        ...response
    }
}

作为参考,我提供了一个根据 Stephane Vanraes 回答生成 sitemap.xml 的完整示例。

这里是routes/sitemap.xml.ts:

// sitemap.xml generation


// This sitemap is manually maintained and page paths included here one by one
const staticPages = [
    "",
    "about",
    "trading-view",
    "trading-view/backtesting",
    "community",
    "trading-view/exchanges",
    "trading-view/blockchains",
]


/***
 * Sitemap.xml HTTP GET endpoint
 *
 * For more information see 
 */
export async function get(page) {
  
  // SvelteKit page object does not include protocol, so assume HTTPS
  const proto = "https";

  // Generate the sitemap.xml file with string fiddling
  const fragments = [];
  for(let path of staticPages) {
    const fullUrl = `${proto}://${page.host}/${path}`;
    fragments.push(`<url><loc>${fullUrl}</loc></url>`);
  }

  // Build the XML for pages
  const urlXml = "".concat(...fragments);

  // See https://en.wikipedia.org/wiki/Sitemaps
  const xml =
    `<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
   ${urlXml}
</urlset>`

  return {
    status: 200,
    body: xml,
    headers: {
      'Content-Type': 'application/xml'
    }
  }
}