SvelteKitでSitemapとRSSを作成する
sveltekitとは
svelteのフレームワークSapperの後継で
Webアプリケーションが作れます
対象
すでにsveltekitでアプリの作成が完了している方が対象です
markdownで作成したものをhtmlページとして作成している場合に使えます
Sitemap.xmlを作成する
src/routes/sitemap.xml.ts
を作成して以下のように記述します。
import fs from "fs";
import path from "path";
import frontmatter from "front-matter";
import { base } from "$app/paths";
import { create } from "xmlbuilder2";
function getPosts(filePath: string) {
const posts = fs.readdirSync(filePath)
.filter((fileName) => !fs.lstatSync(path.resolve(filePath, fileName)).isDirectory())
.map((fileName) => {
const post = fs.readFileSync(path.resolve(filePath, fileName), "utf-8");
const { attributes } = frontmatter(post);
return attributes;
});
return posts;
}
export async function get() {
const posts = getPosts("./posts");
let xml = create({ version: "1.0", encoding: "utf-8" })
.ele("urlset", {
"xmlns": "http://www.sitemaps.org/schemas/sitemap/0.9",
"xmlns:xhtml": "http://www.w3.org/1999/xhtml",
})
if (Array.isArray(posts)) {
posts.forEach((post) => {
xml
.ele("url")
.ele("loc").txt(`${base}/${post.slug}`).up()
.ele("lastmod").txt(post.updatedAt).up()
.ele("changefreq").txt(`daily`).up();
});
}
xml
.ele("url")
.ele("loc").txt(`${base}/`).up()
.ele("lastmod").txt(String(new Date())).up()
.ele("changefreq").txt(`daily`).up();
let sitemap = xml.end({ prettyPrint: true });
return {
status: 200,
body: sitemap,
}
}
getPosts
マークダウンで作成したファイルを読み込むのに使っています
get()内で読み込む際にMarkdownのフォルダを指定してください
get
lastmod
がpostのupdatedAt
になっていますが、これはマークダウン内のメタデータによって変更してください
最後に編集した時刻の乗っているものです
xmlbuilder2
xmlを作成するのに便利なライブラリです
github xmlbuilder2
使い方はGithubを見た方がわかりやすいと思います。
frontmatter
マークダウンのメタデータを読み込んでくれるライブラリです
github front-matter
RSSを作成する
src/routes/rss.xml.ts
を作成して以下のように記述します。
import fs from "fs";
import path from "path";
import frontmatter from "front-matter";
import { create } from "xmlbuilder2";
let basePath = "https://mekos.site";
let today = new Date().toUTCString();
function getPosts(filePath: string) {
const posts = fs.readdirSync(filePath)
.filter((fileName) => !fs.lstatSync(path.resolve(filePath, fileName)).isDirectory())
.map((fileName) => {
const post = fs.readFileSync(path.resolve(filePath, fileName), "utf-8");
const { attributes } = frontmatter(post);
return attributes;
});
return posts;
}
export async function get() {
const posts = getPosts("./posts");
let xml = create({ version: "1.0", encoding: "utf-8" })
.ele("rss", {
"xmlns:atom": "http://www.w3.org/2005/Atom",
"xmlns:dc": "http://purl.org/dc/elements/1.1/",
"xmlns:content": "http://purl.org/rss/1.0/modules/content/",
"version": "2.0"
})
.ele("channel")
.ele("title").txt("Signpost by meko").up()
.ele("link").txt(basePath + "/").up()
.ele("language").txt("ja").up()
.ele("copyright").txt("Copyright 2020-2021 meko").up()
.ele("description").txt("engineer blog").up()
.ele("lastBuildDate").txt(today).up()
.ele("docs").txt("https://validator.w3.org/feed/docs/rss2.html").up()
.ele("atom:link", { "href": `${basePath}/feed.xml`, rel: "self", type: "application/rss+xml" }).up();
if (Array.isArray(posts)) {
posts.forEach((post) => {
xml
.ele("item")
.ele("title").txt(`${post.title}`).up()
.ele("dc:creator").txt(`${post.author}`).up()
.ele("link").txt(`${basePath}/${post.slug}/`).up()
.ele("guid", { isPermaLink: "true" }).txt(`${basePath}/${post.slug}/`).up()
.ele("pubDate").txt(new Date(post.updatedAt).toUTCString()).up()
.ele("enclosure", { url: `${basePath}/${post.thumbnail}`, length: 0, type: "image/png"}).up()
.ele("description").txt(`<![CDATA[${post.description}<img src="${basePath}/${post.thumbnail}">]]>`).up();
});
}
let rss = xml.end({ prettyPrint: true });
return {
status: 200,
body: rss,
}
}
getPosts
マークダウンで作成したファイルを読み込むのに使っています
get()内で読み込む際にMarkdownのフォルダを指定してください
get
basePath
はサイトのベースのURLです
lastmod
がpostのupdatedAt
になっていますが、これはマークダウン内のメタデータによって変更してください
最後に編集した時刻の乗っているものです
slug
はページまでのパスです
forEach内の項目で無いものは削除しても大丈夫です
xmlbuilder2
xmlを作成するのに便利なライブラリです
github xmlbuilder2
使い方はGithubを見た方がわかりやすいと思います。
frontmatter
マークダウンのメタデータを読み込んでくれるライブラリです
github front-matter
Validaterでチェック
Sitemap用
RSS用
Index.svelte
src/routes/index.svelte
内で先ほど作成したページを読み込みます
<script context="module">
...
export async function load({ fetch }) {
// sitemap & rss
await fetch(`${base}/sitemap.xml`);
await fetch(`${base}/rss.xml`);
}
</script>
これで完了です。
上手くいかない時
RSSにしていない
svelte.config.js
内で設定できます
...
const config = {
kit: {
// hydrate the <div id="svelte"> element in src/app.html
...
ssr: true,
},
};
export default config;