import Since from '/components/Since.astro'; import ReadMore from '/components/ReadMore.astro';

セッションは、オンデマンドレンダリングページのリクエスト間でデータを共有するための方法です。

cookiesとは異なり、セッションはサーバーでデータを保存するため、より大きなデータを保存することができます。また、サイズ制限やセキュリティの問題も気にする必要がありません。ユーザーのデータ、ショッピングカート、フォームの状態などを保存するのに便利です。クライアント側のJavaScriptを使わないで機能します。

astro
---export const prerender = false; // 'server'出力の場合は不要const cart = await Astro.session?.get('cart');---<a href="/checkout">🛒 {cart?.length ?? 0} 点</a>

セッションの設定

セッションデータを保存するにはストレージドライバーが必要です。NodeCloudflareNetlify の各アダプターはデフォルトドライバーを自動的に設定します。しかし、その他のアダプターでは ドライバーを手動で指定する必要があります。

js
  {    adapter: vercel(),    session: {      driver: "redis",    },  }

セッションデータを操作する

sessionオブジェクト を使うと、保存されているユーザー状態(例:ショッピングカートへの商品の追加)やセッションID(例:ログアウト時にセッションID Cookieを削除)を操作できます。このオブジェクトはAstroのコンポーネントおよびページではAstro.sessionとして、APIエンドポイント・ミドルウェア・アクションではcontext.sessionとして利用できます。

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

ほとんどの場合は、session.get()session.set()の2つだけで十分です。

Astroコンポーネントとページ

.astroコンポーネントやページでは、グローバルAstroオブジェクト経由でセッションにアクセスできます。たとえば、ショッピングカート内の商品数を表示する例です。

astro
---export const prerender = false; // 'server'出力の場合は不要const cart = await Astro.session?.get('cart');---<a href="/checkout">🛒 {cart?.length ?? 0} 点</a>

APIエンドポイント

APIエンドポイントでは、セッションはcontextオブジェクト上で利用できます。たとえば、ショッピングカートに商品を追加する例です。

ts
export async function POST(context: APIContext) {  const cart = await context.session?.get('cart') || [];  const data = await context.request.json<{ item: string }>();  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オブジェクト上でセッションにアクセスできます。たとえば、ショッピングカートに商品を追加する例です。

ts
import { defineAction } from 'astro:actions';import { z } from 'astro:schema';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;    },  }),};

ミドルウェア

:::caution エッジミドルウェアでは、現在セッションはサポートされていません。 :::

ミドルウェア内では、contextオブジェクト上でセッションにアクセスできます。たとえば、セッションに最終訪問した時刻を保存する例です。

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

セッションデータの型

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

必要に応じて、src/env.d.tsファイルを作成し、App.SessionData型を宣言することでセッションデータにTypeScriptの型を付けることもできます。

ts
declare namespace App {  interface SessionData {    user: {      id: string;      name: string;    };    cart: string[];  }}

これにより、エディター上で型チェックと補完を受けながらセッションデータにアクセスできます。

ts
---const cart = await Astro.session?.get('cart');// const cart: string[] | undefinedconst something = await Astro.session?.get('something');// const something: anyAstro.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; }'.---

:::caution これは型チェック専用であり、実行時のセッション動作には影響しません。ユーザーのセッションに既にデータが保存されている状態で型を変更すると、実行時エラーが発生する可能性があるため注意してください。 :::