07.SvelteKitを使ってSSGモードでFirestore開発しましょう
湯 鵬飛
湯 鵬飛
2024-03-05
SvelteKitを使ってSSGモードでFirestore開発しましょう

Svelte SSGモード


1.SvelteKitプロジェクトを作る

npm create svelte@latest sveltestudytan
cd sveltestudytan
npm i

2.FirebaseのWebフレームワーク自動感知機能をON

firebase experiments:enable webframeworks

3.Firebaseプロジェクトを初期化する

firebase init

Firebase Hostingを選択して、プロジェクトも選択してください。
その後、SvelteKitを自動感知できて、Enterを押してください。


4.firebase.jsonの内容を修正

{
  "hosting": {
    "source": ".",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "frameworksBackend": {
      "region": "asia-northeast1",
      "maxInstances": 1
    }
  }
}

5.SSGモードに切り替えたい

  1. 作業フォルダーに下記のライブラリを追加する
npm i -D @sveltejs/adapter-static
  1. svelte.config.jsファイルを上書きする
import adapter from '@sveltejs/adapter-static';

export default {
    kit: {
        adapter: adapter()
    }
};

3.「src\routes+layout.js」ファイルに下記の2行を追加(修正)する

export const prerender = true;

以上実行したら、Firebase Hostingのみ使用のSSGモードになります。
SSGの場合、+page.server.js, +layout.server.js, +server.jsが使えなくなります。


6.使用するlibをインストール

npm i bootstrap
npm i firebase

7.Firebase SDKの情報を利用するため、共通libを作成する

※Firebaseサービスアカウントは、「Firebaseプロジェクト」→「プロジェクト設定」→「全般」の順で獲得できます。

/src/lib/firebase/firebaseApp.js

import { initializeApp ,getApps} from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";
import { getFunctions } from "firebase/functions";
import { getStorage } from "firebase/storage";


// Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
const firebaseConfig = {
    //Firebaseの内容をコピーしてください
};

var app;

if (!getApps().length) {
    app = initializeApp(firebaseConfig);
} else {
    app = getApps()[0];
}

var firestore = getFirestore(app);
var auth = getAuth(app);
var functions = getFunctions(app);
var storage = getStorage(app, `gs://${firebaseConfig.storageBucket}`);

export default {
    app,
    firestore,
    auth,
    functions,
    storage,
};

例1:一覧画面

  • フロントエンドのみ: /src/routes/blog/+page.svelte
<script>
    // @ts-nocheck
    import { onMount } from 'svelte';
    import firebaseApp from '$lib/firebase/firebaseApp';
    import {collection,getDocs} from 'firebase/firestore';

    let bloglist = [];
    onMount(async()=>{
        const querySnapshot = await getDocs(collection(firebaseApp.firestore, 'blog'));
        if(querySnapshot.docs.length>0){
            bloglist = querySnapshot.docs.map(doc=>{
                var doctemp = doc.data();
                doctemp.blogid = doc.id;
                return doctemp;
            })
        }
    })
    
</script>

{#if bloglist.length == 0}
    読み込み中
{:else}
<div class="container">
    <div class="d-flex flex-column">
        {#each bloglist as item}
            <a href={`/blog/${item.blogid}`}>{item.title}</a>
        {/each}
    </div>
</div>
{/if}

例2:Blog詳細

  • フロントパラメータ処理: /src/routes/blog/[blogid]/+page.js
/** @type {import('./$types').PageLoad} */
export async function load({ params }) {
    console.log('params AAAAAA:',params)
    return params;
};

export function entries(){
    return [
        {blogid:'blogid'}
    ]
}
  • フロントエンド: /src/routes/blog/[blogid]/+page.svelte
<script>
    // @ts-nocheck

    export let data;
    import { onMount } from 'svelte';
    import firebaseApp from '$lib/firebase/firebaseApp';
    import { doc, getDoc } from 'firebase/firestore';

    let bloginfo = null;

    onMount(async()=>{
        const docRef = doc(firebaseApp.firestore, "blog", data.blogid);
        const docSnap = await getDoc(docRef);

        if (docSnap.exists()) {
            console.log("ドキュメントデータ:", docSnap.data());
            bloginfo =  docSnap.data();
        } else {
            console.log("該当するドキュメントが見つかりません!");
        }
    });
    
</script>


{#if !bloginfo}
    読み込み中
{:else}
<div class="container">
    <div class="d-flex flex-column">
        <div class="">{bloginfo.title}</div>
        <div class="">{bloginfo.body}</div>
        <div class="">{data.blogid}</div>
    </div>
</div>

{/if} 

最後:SSGモードデプロイする前の注意事項:

SSGモードでは、firebase deployする時、「/src/routes」の中に、全ての「+page.svelte」の中の「a」タグのURLは、必ず事前に生成しなければなりません(prerender)。
そのため、「/blog」画面に記載した動的リンクには、デフォルト値に設定しないと、Buildができません。
なので、動的リンクの場合、下記の記述でリンクのデフォルト値を設定できます。

[/src/routes/blog/[blogid]/+page.js]

//...
//...
//...

export function entries(){
    return [
        {blogid:'blogid'}
    ]
}