SvelteKit で作ったサイトやWebアプリを保守していると、依存関係の更新で @sveltejs/kit を 3 系に上げるPRが届くことがあります。2026年10月1日(日本時間2日)に npm へ公開された SvelteKit 3.0.0 は、変更履歴の「Major Changes」に70を超える項目が並ぶ大きな更新です。10月14日には 3.1.0 も公開されていますが、変更履歴を見るかぎり、この記事で扱う4点に関わる変更はありません。
型や import の場所の変更のように、TypeScript のチェックやビルドのエラーで気づける項目もあります。厄介なのは、ビルドは通るのに、本番で動かすと挙動が変わる項目です。編集部は 2.70.3 と 3.0.1 で同じ小さなアプリを作り、@sveltejs/adapter-node でビルドして、リクエストを送って結果を比べました。そのうち、問い合わせフォームやログインのあるサイトに関わる4点を取り上げます。

1. 外部URLへのリダイレクトが500エラーになる
変更履歴には「breaking: forbid external redirects by default」とあります。サーバー側で redirect(303, 'https://example.com/') のように別のドメインへ飛ばす処理を、両方の版で動かした結果です。
# 2.70.3
GET /go → 303 location=https://example.com/
# 3.0.1
GET /go → 500 (ログ: Error: https://svelte.dev/e/kit/redirect_external_not_allowed)
同じサイト内へのリダイレクト(/form など)は、どちらの版も 303 で動きました。
外部へのリダイレクトを許可するには、第3引数を渡します。redirect の説明には「you must pass { external: true } to allow any external URL except javascript: URLs, or { external: [...] } with an allowlist of permitted origins」とあります。許可先を ['https://example.com'] にした場合は、https://example.com/ へは 303、別のドメインを指定すると 500 になりました。
決済サービスや外部の認証画面、旧サイトへの転送など、外部へ飛ばす処理がないかをコードで確認します。ログインの後に ?next= の値へ戻す処理のように、利用者が指定したURLへ飛ばす箇所は、external: true で一括して許可するのではなく、許可先を列挙する方が安全です。変更前の 2 系では、こうした箇所が外部のURLへ飛ばせる状態(オープンリダイレクト)になっていなかったかも確認しておきます。
2. Cookieのpathを省略できるようになった
cookies.set() で path を指定しなかった場合の挙動が変わりました。変更履歴では「breaking: default the cookie path option to '/'」です。
# /cookie/sub で cookies.set('sub', 'abc', { httpOnly: true })
2.70.3 → 500 ERROR: You must specify a `path` when setting, deleting or serializing cookies
3.0.1 → 200 set-cookie: sub=abc; Path=/; HttpOnly; SameSite=Lax
(3.0.1 の結果は paths.origin に http のURLを設定した状態のものです。設定しない状態では Secure も付きました)
2 系では path の省略はエラーだったため、既存のコードには path が書かれているはずで、そのまま動きます。注意が要るのは、3 系に上げてから書く新しいコードです。下の階層のページだけで使う Cookie でも、path を省くとサイト全体に送られる Cookie になります。管理画面などで範囲を絞りたい Cookie は、引き続き path を明示します。
3. adapter-node の ORIGIN 環境変数が効かない
Node.js のサーバーで動かしている場合、ビルドや起動の段階ではエラーにならず、送信して初めて気づく変更です。adapter-node 6.0.0 の変更履歴に「add kit.paths.origin config option, remove kit.prerender.origin and the adapter-node ORIGIN environment variable」とあります。
逆プロキシの後ろで動かしていると、SvelteKit がリクエストから判断するサイトのURL(オリジン)が、利用者がアクセスしたURLと一致しないことがあります。2 系の adapter-node では、ORIGIN 環境変数で正しいURLを渡せました。この値は、フォームの送信元のチェック(CSRF 対策)に使われます。
編集部の環境で、フォームの送信(同じオリジンからの POST)を試した結果です。
# 2.70.3 + ORIGIN=http://localhost:6201 → 200
# 3.0.1 + ORIGIN=http://localhost:6302 → 403 Cross-site POST form submissions are forbidden
# 3.0.1 + paths.origin を設定(環境変数なし) → 422(アクションが返した fail(422))
3 系では ORIGIN を設定したままでも無視され、サイト自身のフォームが403で拒否される状態になりました。設定は Vite の設定に移ります。3.0 では「require Svelte config options to be passed through the Vite plugin」という変更もあり、編集部は次のように書いて動かしました。
// vite.config.js(3.0.1 で確認した形)
import { sveltekit } from '@sveltejs/kit/vite';
import adapter from '@sveltejs/adapter-node';
export default {
plugins: [
sveltekit({
adapter: adapter(),
paths: { origin: 'https://www.example.co.jp' }
})
]
};
型定義の説明では、paths.origin を設定しなければ「SvelteKit will derive the origin from request.url」とされ、逆プロキシが host ヘッダーを渡さない場合などに設定するよう案内されています。デプロイの手順書やサーバーの環境変数に ORIGIN が書かれているなら、更新と同時に設定を移します。
なお、2 系では fail(422) を返したフォームでも、JavaScript なしの送信への応答は 200 でした。3 系では「form action responses now use the HTTP status code returned from fail」となり、422 が返ります。応答の状態コードで成否を判定している外形監視やテストがあれば、あわせて見直します。
4. Content-Type のない社外からの送信を拒否する
「disallow cross-origin form submissions without a Content-Type header」という変更もあります。別のオリジンから、Content-Type を付けずに POST した結果です。
2.70.3 → 415 Unsupported Media Type(送信元のチェックを通り、アクションの処理まで進んだ)
3.0.1 → 403 Cross-site POST form submissions are forbidden
2 系でも結果はエラーですが、送信元のチェックではなく、その先の処理で止まっていました。3 系では入口のチェックで止まります。通常のフォームの利用には影響しない変更ですが、決済サービスなど外部からフォーム形式で POST を受けている場合は、csrf.trustedOrigins に送信元を登録しているかを確認します(型定義の説明では、信頼できる送信元だけを入れるよう注意書きがあります)。
そのほかに更新前に確かめること
挙動ではなく、ビルドや起動の段階で止まる変更も多数あります。主なものを挙げます。
- Node.js 22.17 以上が必要(
enginesは>=22.17)。Vite 8.0.12 以上、TypeScript 6 以上、Svelte 5.57.1 以上、@sveltejs/vite-plugin-svelte7 以上も必要です(移行ガイドと 3.0.1 の peerDependencies による。変更履歴の項目には「Svelte 5.56.4 or newer」とありますが、公開版の要件は 5.57.1 です)。Node.js の版ごとの保守期限はNode.js 24は10月20日に保守期へで整理しています $app/storesの削除、$libから#libへの変更、$app/pathsのbase・assetsの削除csrf.checkOriginの削除(trustedOriginsに置き換え)- adapter-node 6.0.0 では、静的ファイルの一覧をビルド時に記録し、ビルド後に出力先へ追加したファイルは配信されない、静的ファイルは GET と HEAD だけに応答する、という変更もあります
Vite 8 への移行についてはVite+ 1.0正式版、移行前に確かめるNode要件、別のフレームワークのメジャー更新を案件で採用する判断はRemix 3.0正式版 案件で採用する前に確かめる5つの点でも扱っています。
更新の進め方
公式の移行ガイド(Migrating to SvelteKit 3)は、先に 2 系の最新版へ上げて非推奨の警告を確認すること、多くの変更は npx sv migrate sveltekit-3 で自動変換できることを案内しています。この記事の4点のうち、外部へのリダイレクトの許可先や paths.origin の値は、サイトごとに決める必要があります。
以下は編集部の提案です。
- コードを検索する。
redirect(、cookies.set(、checkOrigin、$app/stores、$libを検索し、外部へのリダイレクトと Cookie の範囲を一覧にする - デプロイ設定を確認する。 サーバーやコンテナの環境変数に
ORIGINがあれば、paths.originに移す値を控える - 検証環境で、本番と同じ逆プロキシの構成で動かす。 問い合わせフォームの送信、ログイン、外部へのリダイレクト(決済・認証)を一通り試す
- 監視とテストの期待値を直す。 フォームの失敗時の状態コード(200 → 422 など)
確認した範囲
2026年10月12日に、sveltejs/kit の packages/kit/CHANGELOG.md(3.0.0・3.0.1)と packages/adapter-node/CHANGELOG.md(6.0.0)、npm に公開された @sveltejs/kit 3.0.1 の型定義・
redirectの説明・package.json、registry.npmjs.org の公開日時を確認しました(資料調査)。あわせて Linux 上の Node.js 22.22.0 で、@sveltejs/kit 2.70.3(adapter-node 5.5.7、Vite 7.3.7)と 3.0.1(adapter-node 6.0.0、Vite 8.3.4)で同じ小さなアプリをビルドし、curl でリクエストを送って結果を比べました(実機検証)。逆プロキシ、HTTPS、各種ホスティングの adapter、クライアント側の動き(use:enhanceなど)、npx sv migrate sveltekit-3による自動変換は試していません。2026年10月16日に、svelte.dev の移行ガイド「Migrating to SvelteKit 3」と、3.1.0 までの変更履歴を確認しました。
SvelteKit をはじめとするフレームワークの更新や、既存サイトの保守は、開発・AI・自動化のご相談からお問い合わせください。









