くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Nuxt(SPA)+Firebaseでsitemapを生成してみる

積読ハウマッチをNuxt.jsのSPAで作ってみたけど、
静的ページじゃないので、NuxtのSitemap Moduleだと微妙...

なので、CloudFunction for Firebaseを使って、
サイトマップを自動生成するようにしてみたときの備忘録。

sitemap.xmlのサンプル

sitemapの形式はこんな感じ。必須なのは<loc>だけなので、
とりあえず、そこだけあればいい感じ。

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <!-- 必須: URL -->
    <loc>http://www.example.com/</loc>
    
    <!-- 任意: 最終更新日 -->
    <lastmod>2005-01-01</lastmod>
    
    <!-- 任意: 更新頻度。always/daily/yearly/neverなども -->
    <changefreq>monthly</changefreq>
    
    <!-- 任意: 優先度: 0.0〜1.0で指定。デフォルトで0.5 -->
    <priority>0.8</priority>
  </url>
  <url>
    <!-- 以後、繰り返し -->
  </url>
</urlset> 

Hostingの設定

ホスティング側の設定をして、Functionを呼び出すように変更。

{
  // ...略
  "hosting": {
    // ...略
    "rewrites": [
      {
        "source": "/sitemap",
        "function": "sitemap"
      },
      // ...略
    ],
  },
}

Functionのコード

Function側のコードはこんな感じ。とりあえず<loc>だけ対応

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

const db = admin.firestore();

// ********************************************************
// * サイトマップの生成
// ********************************************************
exports.sitemap = functions.https.onRequest(async (req, res) => {
  try {
    const lines = [];
    // head
    lines.push(`<?xml version="1.0" encoding="UTF-8"?>`);
    lines.push(`<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`);

    // root
    lines.push(`<url><loc>https://example.com/</loc></url>`);

    // userの個別ページ
    const userDocs = await db.collection("users").get();
    userDocs.docs.map(s => {
      lines.push(`<url><loc>https://example.com/user/${s.data().uid}</loc></url>`);
    });

    // end
    lines.push(`</urlset>`);

    // キャッシュを有効に
    res.set("Cache-Control", "public, max-age=7200, s-maxage=600");
    // コンテントタイプをxmlに
    res.set("Content-Type", "text/xml");
    // リストを改行でJOINして、レスポンスを返す
    res.end(lines.join("\n"));
  } catch (error) {
    // なにかエラーがあったら、静的ファイルの方へリダイレクト
    console.error(`Error occuered in sitemap: ${error}`, error);
    res.redirect("/sitemap.xml");
  }
});

これで、Firestoreにあるデータも踏まえたsitemap.xmlを作れるように(´ω`)

結果はこんな感じ

固定なURLはトップページしかなかったので、
@nuxtjs/sitemapを使うと1だったけど...

f:id:wannabe-jellyfish:20190807181449p:plain

DBデータから自動生成もしたので、5052ページに♪

f:id:wannabe-jellyfish:20190807181533p:plain

以上!!

参考にしたサイト様