From 9dbd2910a3d2f71c9fa9dec10bfdfeda2805f341 Mon Sep 17 00:00:00 2001 From: Javi Velasco Date: Mon, 27 Oct 2025 11:37:31 +0900 Subject: [PATCH 01/11] Support experimental Bun in Vercel Adapter --- packages/adapter-vercel/index.d.ts | 2 +- packages/adapter-vercel/index.js | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/adapter-vercel/index.d.ts b/packages/adapter-vercel/index.d.ts index d44e8a70fcbf..78d5665b3686 100644 --- a/packages/adapter-vercel/index.d.ts +++ b/packages/adapter-vercel/index.d.ts @@ -9,7 +9,7 @@ export interface ServerlessConfig { * @default Same as the build environment * @deprecated */ - runtime?: `nodejs${number}.x`; + runtime?: `nodejs${number}.x` | 'experimental_bun1.x'; /** * To which regions to deploy the app. A list of regions. * More info: https://vercel.com/docs/concepts/edge-network/regions diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index d4ec606663b0..86e1b5244943 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -305,9 +305,13 @@ const plugin = function (defaults = {}) { } const node_runtime = /nodejs([0-9]+)\.x/.exec(runtime); - if (runtime !== 'edge' && (!node_runtime || parseInt(node_runtime[1]) < 20)) { + if ( + runtime !== 'edge' && + runtime !== 'experimental_bun1.x' && + (!node_runtime || parseInt(node_runtime[1]) < 20) + ) { throw new Error( - `Invalid runtime '${runtime}' for route ${route.id}. Valid runtimes are 'edge' and 'nodejs20.x' or higher ` + + `Invalid runtime '${runtime}' for route ${route.id}. Valid runtimes are 'edge', 'experimental_bun1.x', and 'nodejs20.x' or higher ` + '(see the Node.js Version section in your Vercel project settings for info on the currently supported versions).' ); } @@ -315,9 +319,9 @@ const plugin = function (defaults = {}) { if (config.isr) { const directory = path.relative('.', builder.config.kit.files.routes + route.id); - if (!runtime.startsWith('nodejs')) { + if (!runtime.startsWith('nodejs') && runtime !== 'experimental_bun1.x') { throw new Error( - `${directory}: Routes using \`isr\` must use a Node.js runtime (for example 'nodejs20.x')` + `${directory}: Routes using \`isr\` must use a Node.js or Bun runtime (for example 'nodejs20.x' or 'experimental_bun1.x')` ); } From c7923cb3d57439e16e71edebdd5ce85429569b22 Mon Sep 17 00:00:00 2001 From: Javi Velasco Date: Mon, 27 Oct 2025 12:22:15 +0900 Subject: [PATCH 02/11] Remove the experimental prefix in the actual output --- packages/adapter-vercel/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 86e1b5244943..43201cd740e4 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -263,7 +263,7 @@ const plugin = function (defaults = {}) { `${dirs.functions}/${name}.func/.vc-config.json`, JSON.stringify( { - runtime: config.runtime, + runtime: config.runtime.replace(/^experimental_/, ''), regions: config.regions, entrypoint: 'index.js', framework: { @@ -786,7 +786,7 @@ async function create_function_bundle(builder, entry, dir, config) { `${dir}/.vc-config.json`, JSON.stringify( { - runtime: config.runtime, + runtime: config.runtime.replace(/^experimental_/, ''), regions: config.regions, memory: config.memory, maxDuration: config.maxDuration, From 068f044561081b62fe652402bf00c2ed0ba2698b Mon Sep 17 00:00:00 2001 From: Javi Velasco Date: Mon, 27 Oct 2025 16:39:34 +0900 Subject: [PATCH 03/11] Rename experimental_bun to be just bun --- packages/adapter-vercel/index.d.ts | 2 +- packages/adapter-vercel/index.js | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/adapter-vercel/index.d.ts b/packages/adapter-vercel/index.d.ts index 78d5665b3686..dd40ff345952 100644 --- a/packages/adapter-vercel/index.d.ts +++ b/packages/adapter-vercel/index.d.ts @@ -9,7 +9,7 @@ export interface ServerlessConfig { * @default Same as the build environment * @deprecated */ - runtime?: `nodejs${number}.x` | 'experimental_bun1.x'; + runtime?: `nodejs${number}.x` | `bun${string}`; /** * To which regions to deploy the app. A list of regions. * More info: https://vercel.com/docs/concepts/edge-network/regions diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 43201cd740e4..ca23dbfdae3f 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -305,13 +305,14 @@ const plugin = function (defaults = {}) { } const node_runtime = /nodejs([0-9]+)\.x/.exec(runtime); + const bun_runtime = /^bun/.exec(runtime); if ( runtime !== 'edge' && - runtime !== 'experimental_bun1.x' && + !bun_runtime && (!node_runtime || parseInt(node_runtime[1]) < 20) ) { throw new Error( - `Invalid runtime '${runtime}' for route ${route.id}. Valid runtimes are 'edge', 'experimental_bun1.x', and 'nodejs20.x' or higher ` + + `Invalid runtime '${runtime}' for route ${route.id}. Valid runtimes are 'edge', 'bun' (e.g., 'bun1.x'), and 'nodejs20.x' or higher ` + '(see the Node.js Version section in your Vercel project settings for info on the currently supported versions).' ); } @@ -319,9 +320,9 @@ const plugin = function (defaults = {}) { if (config.isr) { const directory = path.relative('.', builder.config.kit.files.routes + route.id); - if (!runtime.startsWith('nodejs') && runtime !== 'experimental_bun1.x') { + if (!runtime.startsWith('nodejs') && !bun_runtime) { throw new Error( - `${directory}: Routes using \`isr\` must use a Node.js or Bun runtime (for example 'nodejs20.x' or 'experimental_bun1.x')` + `${directory}: Routes using \`isr\` must use a Node.js or Bun runtime (for example 'nodejs20.x' or 'bun1.x')` ); } From a8789f2bd0d351f40b279307f9dfd5d79bc7b4cb Mon Sep 17 00:00:00 2001 From: Javi Velasco Date: Mon, 27 Oct 2025 16:40:13 +0900 Subject: [PATCH 04/11] The default runtime should be bun if it is used for building --- packages/adapter-vercel/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index ca23dbfdae3f..5e2418bb0c05 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -25,6 +25,10 @@ const INTERNAL = '![-]'; // this name is guaranteed not to conflict with user ro const [kit_major, kit_minor] = VERSION.split('.'); const get_default_runtime = () => { + if ('Bun' in globalThis) { + return 'bun1.x'; + } + const major = Number(process.version.slice(1).split('.')[0]); // If we're building on Vercel, we know that the version will be fine because Vercel From edca606fc611a12b92206ba16a00704095adb65f Mon Sep 17 00:00:00 2001 From: Javi Velasco Date: Mon, 27 Oct 2025 16:40:38 +0900 Subject: [PATCH 05/11] Allow to opt-in with vercel.json to use bun --- packages/adapter-vercel/index.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 5e2418bb0c05..07d41ad9ccd0 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -78,10 +78,14 @@ const plugin = function (defaults = {}) { builder.rimraf(dir); builder.rimraf(tmp); + /** @type {string | undefined} */ + let vc_bun_version; + if (fs.existsSync('vercel.json')) { const vercel_file = fs.readFileSync('vercel.json', 'utf-8'); const vercel_config = JSON.parse(vercel_file); validate_vercel_json(builder, vercel_config); + vc_bun_version = vercel_config.bunVersion; } const files = fileURLToPath(new URL('./files', import.meta.url).href); @@ -298,7 +302,8 @@ const plugin = function (defaults = {}) { // group routes by config for (const route of builder.routes) { - const runtime = route.config?.runtime ?? defaults?.runtime ?? get_default_runtime(); + const runtime = + route.config?.runtime ?? defaults?.runtime ?? vc_bun_version ?? get_default_runtime(); const config = { runtime, ...defaults, ...route.config }; if (is_prerendered(route)) { @@ -409,7 +414,7 @@ const plugin = function (defaults = {}) { // we need to create a catch-all route so that 404s are handled // by SvelteKit rather than Vercel - const runtime = defaults.runtime ?? get_default_runtime(); + const runtime = defaults.runtime ?? vc_bun_version ?? get_default_runtime(); const generate_function = runtime === 'edge' ? generate_edge_function : generate_serverless_function; From eac096dfd6c3215d723dc526810f18ef99a58930 Mon Sep 17 00:00:00 2001 From: Javi Velasco Date: Mon, 27 Oct 2025 16:46:36 +0900 Subject: [PATCH 06/11] Fix experimental replacing --- packages/adapter-vercel/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 07d41ad9ccd0..5ec6bb0f822e 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -271,7 +271,7 @@ const plugin = function (defaults = {}) { `${dirs.functions}/${name}.func/.vc-config.json`, JSON.stringify( { - runtime: config.runtime.replace(/^experimental_/, ''), + runtime: config.runtime, regions: config.regions, entrypoint: 'index.js', framework: { @@ -796,7 +796,7 @@ async function create_function_bundle(builder, entry, dir, config) { `${dir}/.vc-config.json`, JSON.stringify( { - runtime: config.runtime.replace(/^experimental_/, ''), + runtime: config.runtime, regions: config.regions, memory: config.memory, maxDuration: config.maxDuration, From da1e3e02ce25cdc7dc5ea5c4cd69d7f83dae098b Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Mon, 27 Oct 2025 11:23:51 -0600 Subject: [PATCH 07/11] tweak --- packages/adapter-vercel/index.d.ts | 3 +-- packages/adapter-vercel/index.js | 15 +++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/adapter-vercel/index.d.ts b/packages/adapter-vercel/index.d.ts index dd40ff345952..792dfe5b4f00 100644 --- a/packages/adapter-vercel/index.d.ts +++ b/packages/adapter-vercel/index.d.ts @@ -7,9 +7,8 @@ export interface ServerlessConfig { /** * Whether to use [Edge Functions](https://vercel.com/docs/concepts/functions/edge-functions) (`'edge'`) or [Serverless Functions](https://vercel.com/docs/concepts/functions/serverless-functions) (`'nodejs18.x'`, `'nodejs20.x'` etc). * @default Same as the build environment - * @deprecated */ - runtime?: `nodejs${number}.x` | `bun${string}`; + runtime?: `nodejs${number}.x` | `experimental_bun1.x`; /** * To which regions to deploy the app. A list of regions. * More info: https://vercel.com/docs/concepts/edge-network/regions diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 5ec6bb0f822e..4c78f69fbfb9 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -78,14 +78,10 @@ const plugin = function (defaults = {}) { builder.rimraf(dir); builder.rimraf(tmp); - /** @type {string | undefined} */ - let vc_bun_version; - if (fs.existsSync('vercel.json')) { const vercel_file = fs.readFileSync('vercel.json', 'utf-8'); const vercel_config = JSON.parse(vercel_file); validate_vercel_json(builder, vercel_config); - vc_bun_version = vercel_config.bunVersion; } const files = fileURLToPath(new URL('./files', import.meta.url).href); @@ -302,8 +298,11 @@ const plugin = function (defaults = {}) { // group routes by config for (const route of builder.routes) { - const runtime = - route.config?.runtime ?? defaults?.runtime ?? vc_bun_version ?? get_default_runtime(); + const runtime = ( + route.config?.runtime ?? + defaults?.runtime ?? + get_default_runtime() + ).replace('experimental_', ''); const config = { runtime, ...defaults, ...route.config }; if (is_prerendered(route)) { @@ -321,7 +320,7 @@ const plugin = function (defaults = {}) { (!node_runtime || parseInt(node_runtime[1]) < 20) ) { throw new Error( - `Invalid runtime '${runtime}' for route ${route.id}. Valid runtimes are 'edge', 'bun' (e.g., 'bun1.x'), and 'nodejs20.x' or higher ` + + `Invalid runtime '${runtime}' for route ${route.id}. Valid runtimes are 'edge', 'bun1.x', and 'nodejs20.x' or higher ` + '(see the Node.js Version section in your Vercel project settings for info on the currently supported versions).' ); } @@ -414,7 +413,7 @@ const plugin = function (defaults = {}) { // we need to create a catch-all route so that 404s are handled // by SvelteKit rather than Vercel - const runtime = defaults.runtime ?? vc_bun_version ?? get_default_runtime(); + const runtime = (defaults.runtime ?? get_default_runtime()).replace('experimental_', ''); const generate_function = runtime === 'edge' ? generate_edge_function : generate_serverless_function; From d72239667e88e7569ba7c84236fc55c1fd4d2e27 Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Mon, 27 Oct 2025 11:25:53 -0600 Subject: [PATCH 08/11] changeset --- .changeset/sour-fans-pay.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sour-fans-pay.md diff --git a/.changeset/sour-fans-pay.md b/.changeset/sour-fans-pay.md new file mode 100644 index 000000000000..127139fb9521 --- /dev/null +++ b/.changeset/sour-fans-pay.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-vercel': minor +--- + +feat: Add experimental support for Bun runtime From 6b3be45172c5abffdcc99dc4348a8995d2d16427 Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Mon, 27 Oct 2025 16:21:06 -0600 Subject: [PATCH 09/11] Update packages/adapter-vercel/index.js --- packages/adapter-vercel/index.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 4c78f69fbfb9..9fff8505c000 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -25,10 +25,6 @@ const INTERNAL = '![-]'; // this name is guaranteed not to conflict with user ro const [kit_major, kit_minor] = VERSION.split('.'); const get_default_runtime = () => { - if ('Bun' in globalThis) { - return 'bun1.x'; - } - const major = Number(process.version.slice(1).split('.')[0]); // If we're building on Vercel, we know that the version will be fine because Vercel From 6404bab9d4aae2c2496aede51724105fcc7b05b8 Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Mon, 27 Oct 2025 17:59:27 -0600 Subject: [PATCH 10/11] Update index.js Co-authored-by: Rich Harris --- packages/adapter-vercel/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 9fff8505c000..d0ba7d18d677 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -316,7 +316,7 @@ const plugin = function (defaults = {}) { (!node_runtime || parseInt(node_runtime[1]) < 20) ) { throw new Error( - `Invalid runtime '${runtime}' for route ${route.id}. Valid runtimes are 'edge', 'bun1.x', and 'nodejs20.x' or higher ` + + `Invalid runtime '${runtime}' for route ${route.id}. Valid runtimes are 'edge', 'experimental_bun1.x', 'nodejs20.x' or 'nodejs22.x' ` + '(see the Node.js Version section in your Vercel project settings for info on the currently supported versions).' ); } From 2b5ce565d125fdf9bd2b9de08be330d1b9f58b1d Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Mon, 27 Oct 2025 17:59:45 -0600 Subject: [PATCH 11/11] Update index.js Co-authored-by: Rich Harris --- packages/adapter-vercel/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index d0ba7d18d677..809c6dea3382 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -326,7 +326,7 @@ const plugin = function (defaults = {}) { if (!runtime.startsWith('nodejs') && !bun_runtime) { throw new Error( - `${directory}: Routes using \`isr\` must use a Node.js or Bun runtime (for example 'nodejs20.x' or 'bun1.x')` + `${directory}: Routes using \`isr\` must use a Node.js or Bun runtime (for example 'nodejs22.x' or 'experimental_bun1.x')` ); }