コンテンツにスキップ

セッション

追加: astro@5.7.0

セッションは、オンデマンドレンダリングされるページ間でリクエストをまたいでデータを共有するために使用します。

cookiesとは異なり、セッションはサーバーに保存されるため、サイズ制限やセキュリティの問題を気にすることなく大量のデータを保存できます。ユーザーデータ、ショッピングカート、フォームの状態などの保存に便利で、クライアントサイドのJavaScriptなしで動作します。

src/components/CartButton.astro
---
export const prerender = false; // 'server' outputでは不要
const cart = await Astro.session?.get('cart');
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>

セッションを使うには、セッションデータを保存するためのストレージドライバーが必要です。Node、Cloudflare (EN)、Netlifyのアダプターはデフォルトのドライバーを自動的に設定しますが、その他のアダプターでは現在ドライバーを手動で指定 (EN)する必要があります。

astro.config.mjs
import { defineConfig, sessionDrivers } from 'astro/config'
import vercel from '@astrojs/vercel'
export default defineConfig({
adapter: vercel()
session: {
driver: sessionDrivers.lruCache({
max: 800,
}),
}
})

ストレージドライバーの設定やその他の設定可能なオプションの詳細については、session設定オプション (EN)を参照してください。

デフォルトでは、セッションドライバーはビルド時に設定され、使用される環境変数はすべてビルド成果物にインライン化されます。つまり、実行時に設定を上書きすることはできません。

(外部サービスへの接続などで)異なる設定が必要な場合は、別のファイルでそれを定義します。そして、そのファイルをドライバーのエントリポイントとして使用します。

次の例では、Unstorageとの互換性を利用して、Redisドライバーを独自のエントリポイントで設定しています。

  1. unstorageとioredisパッケージをインストールします。

    ターミナルウィンドウ
    npm install unstorage ioredis
  2. ドライバー設定用のファイル(例: src/session-driver.ts)を作成し、ドライバーインスタンスを返すデフォルト関数をエクスポートします。

    src/session-driver.ts
    import type { SessionDriver } from "astro";
    import redisDriver from "unstorage/drivers/redis";
    import { REDIS_HOST, REDIS_PORT } from "astro:env";
    export default function (): SessionDriver {
    const driver = redisDriver({
    host: REDIS_HOST,
    port: REDIS_PORT,
    });
    return {
    async getItem(key) {
    return await driver.getItem(key);
    },
    async setItem(key, value) {
    await driver.setItem?.(key, value, {});
    },
    async removeItem(key) {
    await driver.removeItem?.(key, {});
    },
    };
    }
  3. このファイルをAstroの設定ファイルでドライバーのエントリポイントとして使用します。

    astro.config.mjs
    import { defineConfig, envField, sessionDrivers } from "astro/config";
    import vercel from "@astrojs/vercel";
    export default defineConfig({
    adapter: vercel(),
    env: {
    schema: {
    REDIS_HOST: envField.string({
    context: "server",
    access: "public",
    default: "localhost",
    }),
    REDIS_PORT: envField.number({
    context: "server",
    access: "public",
    default: 6379,
    }),
    },
    },
    session: {
    driver: {
    entrypoint: new URL("./src/session-driver.ts", import.meta.url),
    },
    },
    });

追加: astro@7.2.0

セッションドライバーが設定されていない場合、自動的にセッションの実行環境がサーバーのバンドルから取り除かれます。追加でsession: falseを設定すると、アダプターにデフォルトのドライバーを提供しないように指示でき、プロジェクト全体でセッションを無効化できます。

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
session: false,
});

通常はデフォルトのセッションドライバーを提供するアダプター(たとえば、Node、Cloudflare (EN)、Netlifyなど)であっても、ドライバーを提供しないようになります。これは、バンドルサイズを小さくすることでコールドスタートを短縮できる、サーバーレスやエッジの実行環境において有用です。

sessionオブジェクト (EN)を使用すれば、保存されたユーザー状態の操作(例: ショッピングカートへのアイテム追加)やセッションIDの操作(例: ログアウト時のセッションIDクッキーの削除)が可能です。このオブジェクトは、AstroコンポーネントやページではAstro.sessionから、APIエンドポイント、ミドルウェア、アクションではcontext.sessionからアクセスできます。

セッションは初回使用時に自動的に生成され、session.regenerate() (EN)でいつでも再生成したり、session.destroy() (EN)で破棄したりできます。

多くのユースケースでは、session.get() (EN)とsession.set() (EN)のみで十分です。

詳細については、セッションAPIリファレンス (EN)を参照してください。

.astroコンポーネントやページでは、グローバルなAstroオブジェクトを通じてセッションオブジェクトにアクセスできます。たとえば、ショッピングカート内のアイテム数を表示するには次のようにします。

src/components/CartButton.astro
---
export const prerender = false; // 'server' outputでは不要
const cart = await Astro.session?.get('cart');
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>

APIエンドポイントでは、contextオブジェクトからセッションオブジェクトにアクセスできます。たとえば、ショッピングカートにアイテムを追加するには次のようにします。

src/pages/api/addToCart.ts
import type { APIContext } from "astro";
export async function POST(context: APIContext) {
const cart = await context.session?.get('cart') || [];
const data = await context.request.json();
if(!data?.item) {
return new Response('Item is required', { status: 400 });
}
cart.push(data.item);
await context.session?.set('cart', cart);
return Response.json(cart);
}

アクションでは、contextオブジェクトからセッションオブジェクトにアクセスできます。たとえば、ショッピングカートにアイテムを追加するには次のようにします。

src/actions/addToCart.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro/zod';
export const server = {
addToCart: defineAction({
input: z.object({ productId: z.string() }),
handler: async (input, context) => {
const cart = await context.session?.get('cart');
cart.push(input.productId);
await context.session?.set('cart', cart);
return cart;
},
}),
};

ミドルウェアでは、contextオブジェクトからセッションオブジェクトにアクセスできます。たとえば、セッションに最終訪問日時を設定するには次のようにします。

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(async (context, next) => {
context.session?.set('lastVisit', new Date());
return next();
});

デフォルトではセッションデータには型がなく、任意のキーに任意のデータを保存できます。値はdevalueを使用してシリアライズ・デシリアライズされます。これはコンテンツコレクションやアクションで使用されているのと同じライブラリです。そのため、サポートされる型も同じで、文字列、数値、Date、Map、Set、URL、配列、プレーンなオブジェクトが含まれます。

src/env.d.tsファイルを作成し、App.SessionData型の宣言を追加することで、セッションデータのTypeScript型を定義することもできます。

src/env.d.ts
declare namespace App {
interface SessionData {
user: {
id: string;
name: string;
};
cart: string[];
}
}

これにより、エディターで型チェックと自動補完を使ってセッションデータにアクセスできるようになります。

src/components/CartButton.astro
---
const cart = await Astro.session?.get('cart');
// const cart: string[] | undefined
const something = await Astro.session?.get('something');
// const something: any
Astro.session?.set('user', { id: 1, name: 'Houston' });
// Error: Argument of type '{ id: number; name: string }' is not assignable to parameter of type '{ id: string; name: string; }'.
---
貢献する コミュニティ スポンサー