mcpField
B
bun-sveltekit

bun-sveltekit

github.com/secondsky開発240505 回インストール5 週間前に更新
リポジトリ

bun-sveltekit について

Bun で SvelteKit アプリを実行、デプロイするための開発スキルです。初期設定、Bun API の例、デプロイ方法、依存関係のインストール時のセキュリティ対策を扱います。

主な機能

  1. 01Bun を使った SvelteKit の設定
  2. 02Bun アダプターの設定
  3. 03Bun API の使用例
  4. 04ビルドと Docker デプロイの指針
  5. 05依存関係インストールのセキュリティ

活用シーン

  1. 01Bun での SvelteKit プロジェクト開始
  2. 02サーバーロード関数での SQLite 利用
  3. 03Bun によるビルドとデプロイ
  4. 04依存関係のセキュリティチェック設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/secondsky/claude-skills --skill bun-sveltekit

インストール後、Claude Code で/bun-sveltekitを入力して読み込まれたか確認します。

詳細

Bun SvelteKit

Bun を使用して SvelteKit アプリケーションを実行し、開発とビルドを高速化します。

クイックスタート

# Create new SvelteKit project
bunx sv create my-app
cd my-app

# Install dependencies
bun install

# Development
bun run dev

# Build
bun run build

# Preview
bun run preview

安全なインストール

bunx sv create のようなスキャフォールディングツールは、リモートコードをダウンロードして実行します。実行する前に、サプライチェーンセキュリティのベストプラクティスに従ってください。

  • インストール後スクリプトをブロックする — Bun はデフォルトでこれらを無効にします。package.json の trustedDependencies で特定のパッケージを許可できます
  • クールダウン期間 — bunfig.toml で minimumReleaseAge を設定し、新しいバージョンを 7 日間待ってから使用します
  • インストール前に監査する — socket package score npm <pkg> を実行するか、socket npm install <pkg> を使用してパッケージを確認します

Socket CLI の統合、クールダウンの設定、ロックファイルの検証、CI による適用を含むセキュリティ設定の全容については、dependency-upgrade スキルを読み込んでください。

プロジェクトのセットアップ

package.json
{
  "scripts": {
    "dev": "vite dev",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "@sveltejs/adapter-auto": "^7.0.0",
    "@sveltejs/kit": "^2.0.0",
    "svelte": "^5.0.0",
    "vite": "^7.3.0"
  }
}
Bun アダプターを使用する
bun add -D svelte-adapter-bun
// svelte.config.js
import adapter from "svelte-adapter-bun";
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";

/** @type {import('@sveltejs/kit').Config} */
export default {
  preprocess: vitePreprocess(),
  kit: {
    adapter: adapter(),
  },
};

Bun API の使用

サーバーロード関数
// src/routes/users/+page.server.ts
import { Database } from "bun:sqlite";
import type { PageServerLoad } from "./$types";

export const load: PageServerLoad = async () => {
  const db = new Database("data.sqlite");
  const users = db.query("SELECT * FROM users").all();
  db.close();

  return { users };
};
フォームアクション
// src/routes/users/+page.server.ts
import { Database } from "bun:sqlite";
import type { Actions } from "./$types";
import { fail } from "@sveltejs/kit";

export const actions: Actions = {
  create: async ({ request }) => {
    const data = await request.formData();
    const name = data.get("name") as string;

    if (!name) {
      return fail(400, { error: "Name required" });
    }

    const db = new Database("data.sqlite");
    db.run("INSERT INTO users (name) VALUES (?)", [name]);
    db.close();

    return { success: true };
  },

  delete: async ({ request }) => {
    const data = await request.formData();
    const id = data.get("id") as string;

    const db = new Database("data.sqlite");
    db.run("DELETE FROM users WHERE id = ?", [id]);
    db.close();

    return { success: true };
  },
};
API ルート
// src/routes/api/users/+server.ts
import { Database } from "bun:sqlite";
import { json } from "@sveltejs/kit";
import type { RequestHandler } from "./$types";

export const GET: RequestHandler = async () => {
  const db = new Database("data.sqlite");
  const users = db.query("SELECT * FROM users").all();
  db.close();

  return json(users);
};

export const POST: RequestHandler = async ({ request }) => {
  const { name } = await request.json();

  const db = new Database("data.sqlite");
  const result = db.run("INSERT INTO users (name) VALUES (?)", [name]);
  db.close();

  return json({ id: result.lastInsertRowid });
};
ファイル操作
// src/routes/api/files/[name]/+server.ts
import type { RequestHandler } from "./$types";

export const GET: RequestHandler = async ({ params }) => {
  const file = Bun.file(`./data/${params.name}`);

  if (!(await file.exists())) {
    return new Response("Not found", { status: 404 });
  }

  return new Response(file);
};

export const PUT: RequestHandler = async ({ params, request }) => {
  const content = await request.text();
  await Bun.write(`./data/${params.name}`, content);

  return new Response("Saved");
};

サーバーフック

// src/hooks.server.ts
import type { Handle } from "@sveltejs/kit";
import { Database } from "bun:sqlite";

// Initialize database on startup
const db = new Database("data.sqlite");
db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
  )
`);

export const handle: Handle = async ({ event, resolve }) => {
  // Add database to locals
  event.locals.db = db;

  // Auth check
  const session = event.cookies.get("session");
  if (session) {
    event.locals.user = await getUser(session);
  }

  return resolve(event);
};
// src/app.d.ts
import type { Database } from "bun:sqlite";

declare global {
  namespace App {
    interface Locals {
      db: Database;
      user?: { id: number; name: string };
    }
  }
}

Svelte 5 コンポーネント


<script lang="ts">
  import type { PageData } from "./$types";

  let { data }: { data: PageData } = $props();
  let { users } = $derived(data);

  let name = $state("");
</script>

<h1>Users</h1>

<form method="POST" action="?/create">
  <input type="text" name="name" bind:value={name} />
  <button type="submit">Add User</button>
</form>

<ul>
  {#each users as user}
    <li>
      {user.name}
      <form method="POST" action="?/delete" style="display: inline">
        <input type="hidden" name="id" value={user.id} />
        <button type="submit">Delete</button>
      </form>
    </li>
  {/each}
</ul>

デプロイ

Bun 用にビルドする
bun run build
bun ./build/index.js
Docker
FROM oven/bun:1 AS builder

WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile

COPY . .
RUN bun run build

FROM oven/bun:1

WORKDIR /app
COPY --from=builder /app/build ./build
COPY --from=builder /app/package.json ./

EXPOSE 3000

CMD ["bun", "./build/index.js"]
アダプターのオプション
// svelte.config.js
import adapter from "svelte-adapter-bun";

export default {
  kit: {
    adapter: adapter({
      out: "build",
      precompress: true, // Generate .gz and .br files
      envPrefix: "",     // Environment variable prefix
      development: false,
      dynamic_origin: true,
      xff_depth: 1,
    }),
  },
};

環境変数

# .env
DATABASE_URL=./data.sqlite
PUBLIC_API_URL=https://api.example.com
// Access in server code
import { DATABASE_URL } from "$env/static/private";
import { PUBLIC_API_URL } from "$env/static/public";

// Or dynamic
import { env } from "$env/dynamic/private";
const dbUrl = env.DATABASE_URL;

よくあるエラー

エラー原因解決方法
Cannot find bun:sqliteアダプターが正しくありませんsvelte-adapter-bun を使用します
Vite errorビルドの問題.svelte-kit をクリアします
Hydration failedサーバーとクライアントの差異ロード関数を確認します
404 on refreshSPA フォールバックアダプターを設定します

参照資料を読み込むタイミング

次の場合は references/adapter-config.md を読み込みます:

  • アダプターの高度なオプション
  • 静的プリレンダリング
  • エッジデプロイ

次の場合は references/performance.md を読み込みます:

  • キャッシュ戦略
  • 遅延読み込み
  • ストリーミング SSR

コメント