はじめに
突然ですが、今まで触れたことのないフロントエンドフレームワークを使ってみたいと思いました。
とある飲み会で「Svelteいいですよ!」と推しを受けたので、Svelteでなにか作ってみようと思い立ちました。
何かいいネタがないかと社内で相談したところ、Firebaseを使ってチャットツールを作る案をもらいました。
ということで、かなり軽いきっかけですがSvelte + Firebaseを使ってチャットツールを作ってみました。
本記事では主に、作った際に調べた内容を記載していきます。
Svelteとは
Svelteは、2016年から開発が開始されたWebフロントエンドフレームワークです。
State of JavaScript 2022によると利用率は第4位で、React / Angular / Vue.jsに次いでいます。
また、公式サイトに「サイバネティクスで強化されたwebアプリ」とのウリ文句がありました。
ちょっとよくわからなかったので、もう少し調べたら以下の記載が。
また、私たちはキャッチフレーズを「魔法のように消える UI フレームワーク」から「サイバネティックに強化されたウェブアプリ」に変更しました。
Svelte には様々な側面があります。-- 卓越した性能、小さなバンドル、アクセシビリティ、組み込みのスタイルカプセル化、宣言的な遷移、使いやすさ、コンパイラであることなど --
その中のどれか1つに焦点を当てることは、他のものに不公平感を与えるような気がします。「Cybernetically enhanced」は、私たちのツールは私たち自身の知能の拡張として機能するべきだという Svelte の包括的な哲学を思い起こさせるようにデザインされています
-- 願わくばレトロでウィリアム・ギブソン風のひねりを加えて。
...うーんこれは哲学🤔
「どれか1つではなく、全て良くなるように作っているよ」と言っているのだなと理解しました。
SvelteKitプロジェクトの作成
Svelteで実装を行うために、SvelteKitプロジェクト作成手順を記載します。
SvelteとSvelteKitは、Vue.jsとNuxt.jsの関係に似ていて、SvelteKitではサーバサイドの処理やサーバサイドレンダリングも実装可能です。
本記事では、サーバサイドに関するお話は省きます。
SvelteKitプロジェクトの作成は、CLIツールを用いて質問に答えていけばOKです。
前提
私が作成した環境は以下になります。
- OS: Ubuntu 22.04.2 LTS
- Node.js: v18.18.2
- npm v9.8.1
手順
ターミナルで以下のコマンドを実行します。
npm create svelte@latest svelte-chat
以降、プロジェクト作成に必要な質問が出てきますので答えていきます。
私は以下のように回答しました。
┌ Welcome to SvelteKit!
│
◇ Which Svelte app template?
│ Skeleton project
│
◇ Add type checking with TypeScript?
│ Yes, using TypeScript syntax
│
◇ Select additional options (use arrow keys/space bar)
│ Add Prettier for code formatting
│
└ Your project is ready!
(質問回答後にターミナルに表示されますが)後は以下のコマンドを実行すれば、開発用サーバが立ち上がって実装が進められる状態になります。
Next steps:
1: cd svelte-chat
2: npm install
3: git init && git add -A && git commit -m "Initial commit" (optional)
4: npm run dev -- --open
観察してみる
ディレクトリ構成
作成されたプロジェクトのディレクトリ構造は以下のような感じです。
基本的にroutes
ディレクトリの下に.svelte
ファイルを作成してページを実装していくこととなります。
.
├── ./README.md
├── ./node_modules
├── ./package-lock.json
├── ./package.json
├── ./src
│ ├── ./src/app.d.ts
│ ├── ./src/app.html
│ ├── ./src/lib
│ │ └── index.ts
│ └── ./src/routes
│ └── +page.svelte
├── ./static
│ └── favicon.png
├── ./svelte.config.js
├── ./tsconfig.json
└── ./vite.config.ts
routes
内のディレクトリ構成は、ユーザがアクセスするURLのパスと対応します。
すなわちディレクトリ構成によってルーティングを定義できます。例えば、以下のようになります。
-
http://<hostname>/
でアクセス →routes/+page.svelte
の内容が表示される -
http://<hostname>/hoge/fuga
でアクセス →routes/hoge/fuga/+page.svelte
の内容が表示される
その他細かいルーティングの仕様は、公式ページに記載がありますので確認してみてください。
Svelteファイル
Svelteファイルは以下の構成で記述していきます。
1つのファイルの中にページ(コンポーネント)に関わるHTML、ロジック、スタイルを全て記述できます(vueファイルと同じですね)。
<script lang="ts">
// 画面のロジックを記述
// JavaScript, TypeScriptどちらも可。
let message = "Hello, World!!";
</script>
<div>
メッセージ:
<div id="message-element">
{ message } <!-- TypeScriptで定義した変数と紐づけ -->
</div>
</div>
<style>
/* CSSを記述 */
#message-element {
color:blue;
font-size: x-large;
}
</style>
公式サイトにサンプルが大量に転がっているので参考にしてみてください。
SvelteプロジェクトにFirebaseをセットアップ
準備
FirebaseのWebサイトにて、以下作業を行います。
- Firebaseプロジェクトの作成
- 認証(Firebase Authentication)とデータベース(Firebase Realtime Database)の有効化
- 認証はログイン/ログアウト機能実装のため。
- データベースはチャットデータ管理のため。
こちらの作業は以下のページを参考にさせていただきました。
https://zenn.dev/hisho/books/617d8f9d6bd78b/viewer/chapter3
セットアップ
Firebaseを使うためのnpmモジュールを追加します。
npm install --save firebase
Svelteコード上でFirebaseを初期化します。
import { getAuth, type Auth } from "firebase/auth";
import { getDatabase, ref, type Database, type DatabaseReference } from "firebase/database";
import { getApps, initializeApp, type FirebaseApp } from 'firebase/app';
export let app: FirebaseApp | null = null;
export let db: Database | null = null;
export let dbRef: DatabaseReference | null = null;
export let auth: Auth | null = null;
export async function initFirebaseApp() {
if (getApps().length !== 0) {
console.log('Firebase app already initialized.');
return;
}
const firebaseConfig = {
apiKey: import.meta.env.VITE_API_KEY,
authDomain: import.meta.env.VITE_AUTH_DOMAIN,
projectId: import.meta.env.VITE_PROJECT_ID,
storageBucket: import.meta.env.VITE_STORAGE_BUCKET,
messagingSenderId: import.meta.env.VITE_MESSAGING_SENDER_ID,
appId: import.meta.env.VITE_APP_ID
};
app = initializeApp(firebaseConfig);
auth = getAuth(app);
db = getDatabase(app);
dbRef = ref(db, 'chat');
}
import { initFirebaseApp } from '$lib/firebase';
onMount(async () => {
await initFirebaseApp();
});
firebaseConfigの値は、環境変数として.env
ファイルに定義します。
Svelteからはimport.meta.env
の形で取得可能です。
VITE_API_KEY=xxxx
VITE_AUTH_DOMAIN=xxxx
VITE_PROJECT_ID=xxxx
VITE_STORAGE_BUCKET=xxxx
VITE_MESSAGING_SENDER_ID=xxxx
VITE_APP_ID=xxxx
チャットツールの実装
Svelte + Firebaseを使ってチャットツール(具体的には以下の機能)を実装しました。
- ログイン/ログアウト機能
- チャット閲覧/投稿機能
ソースコードはGitHubに上げていますので良ければご覧下さい。
https://github.com/imura-nalgo/svelte-chat
感想
Svelteについて
Vue.js(さらに言えばNuxt.js)経験者ならば、何の違和感もなく使えると思います。
Svelteファイルの構成はVueファイルと同じですし、ルーティングの定義方法はNuxt.jsとかなり似ていたためです。
検索して出てくる情報は、Angular/React/Vueと比べると少ないです(これから増えてくるとは思いますが)。
ただその分公式ドキュメントやexampleがかなり充実しており、かつ体系的に学習できるように作ってある印象でした。
Firebaseについて
便利すぎる!!というのが第一印象です。極端に言えば、サーバ側の事を何も考慮しなくても簡単なWebサイトなら作成可能だと思いました。
今回は「Firebase Authentication」と「Firebase Realtime Database」の2つを用いましたが、
認証ではユーザ情報のセッション管理方法等は全く考慮不要でした。Firebaseが提供している方法を選択して、指定のメソッドを呼び出しただけです。
データベースについても、今回はチャットの投稿/削除時に画面を更新する必要があったため、レコード追加/削除イベントをキャッチする必要がありました。
これもFirebaseが提供しているコールバック関数に実装するだけで実現できてしまいました。
最後に
Svelte、Firebaseともにまだまださわりの部分しか触れていないので、次はもう少し難しいものを作ってみようと思いました。