diff --git a/.changeset/tidy-bases-serve.md b/.changeset/tidy-bases-serve.md new file mode 100644 index 000000000000..dd3a3001cc95 --- /dev/null +++ b/.changeset/tidy-bases-serve.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-vercel': patch +--- + +fix: serve prerendered pages when `paths.base` is set diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 7cec5f02109a..c24fa618d716 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -400,6 +400,10 @@ function static_vercel_config(builder, config, dir) { /** @type {Record} */ const overrides = {}; + // prerendered files are written to `static${base}`, but their paths are relative to `base`, + // whereas the keys of `overrides` must be relative to `static` + const static_prefix = builder.config.paths.base ? `${builder.config.paths.base.slice(1)}/` : ''; + /** @type {import('./index.js').ImagesConfig | undefined} */ const images = config.images; @@ -441,7 +445,7 @@ function static_vercel_config(builder, config, dir) { ); } - overrides[page.file] = { path: overrides_path }; + overrides[static_prefix + page.file] = { path: overrides_path }; } const routes = [ diff --git a/packages/adapter-vercel/test/apps/paths-base/build.test.js b/packages/adapter-vercel/test/apps/paths-base/build.test.js new file mode 100644 index 000000000000..b65595cf7c0d --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/build.test.js @@ -0,0 +1,24 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { assert, beforeAll, test } from 'vitest'; +import { deploy } from '../../../../../test-utils/deploy.vitest.js'; + +const app = deploy(import.meta.dirname); +const output = path.join(app, '.vercel/output'); + +/** @type {{ overrides: Record }} */ +let config; +beforeAll(() => (config = JSON.parse(fs.readFileSync(`${output}/config.json`, 'utf8')))); + +test('prerendered pages are written below the base path', () => { + assert.deepEqual(config.overrides, { + 'base/index.html': { path: 'base' }, + 'base/prerendered/a.html': { path: 'base/prerendered/a' } + }); +}); + +test('overrides refer to files that exist', () => { + for (const file of Object.keys(config.overrides)) { + assert.ok(fs.existsSync(`${output}/static/${file}`), `${file} does not exist`); + } +}); diff --git a/packages/adapter-vercel/test/apps/paths-base/package.json b/packages/adapter-vercel/test/apps/paths-base/package.json new file mode 100644 index 000000000000..a551b08142cc --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/package.json @@ -0,0 +1,21 @@ +{ + "name": "test-vercel-paths-base", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite dev", + "preview": "vite preview", + "build": "vite build", + "test:build": "vitest run build.test.js" + }, + "devDependencies": { + "@sveltejs/adapter-vercel": "workspace:*", + "@sveltejs/kit": "workspace:*", + "@sveltejs/vite-plugin-svelte": "catalog:", + "svelte": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", + "vitest": "catalog:" + }, + "type": "module" +} diff --git a/packages/adapter-vercel/test/apps/paths-base/src/app.d.ts b/packages/adapter-vercel/test/apps/paths-base/src/app.d.ts new file mode 100644 index 000000000000..da08e6da592d --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/src/app.d.ts @@ -0,0 +1,13 @@ +// See https://svelte.dev/docs/kit/types#app.d.ts +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } +} + +export {}; diff --git a/packages/adapter-vercel/test/apps/paths-base/src/app.html b/packages/adapter-vercel/test/apps/paths-base/src/app.html new file mode 100644 index 000000000000..f273cc58f7eb --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/src/app.html @@ -0,0 +1,11 @@ + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/adapter-vercel/test/apps/paths-base/src/routes/+page.js b/packages/adapter-vercel/test/apps/paths-base/src/routes/+page.js new file mode 100644 index 000000000000..189f71e2e1b3 --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/src/routes/+page.js @@ -0,0 +1 @@ +export const prerender = true; diff --git a/packages/adapter-vercel/test/apps/paths-base/src/routes/+page.svelte b/packages/adapter-vercel/test/apps/paths-base/src/routes/+page.svelte new file mode 100644 index 000000000000..390193780af3 --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/src/routes/+page.svelte @@ -0,0 +1 @@ +

Hello from SvelteKit on Vercel

diff --git a/packages/adapter-vercel/test/apps/paths-base/src/routes/prerendered/[slug]/+page.server.ts b/packages/adapter-vercel/test/apps/paths-base/src/routes/prerendered/[slug]/+page.server.ts new file mode 100644 index 000000000000..70458b95c82a --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/src/routes/prerendered/[slug]/+page.server.ts @@ -0,0 +1,9 @@ +export const prerender = true; + +export function entries() { + return [{ slug: 'a' }]; +} + +export function load({ params }) { + return { slug: params.slug }; +} diff --git a/packages/adapter-vercel/test/apps/paths-base/src/routes/prerendered/[slug]/+page.svelte b/packages/adapter-vercel/test/apps/paths-base/src/routes/prerendered/[slug]/+page.svelte new file mode 100644 index 000000000000..e22414ef4977 --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/src/routes/prerendered/[slug]/+page.svelte @@ -0,0 +1,5 @@ + + +

prerendered: {data.slug}

diff --git a/packages/adapter-vercel/test/apps/paths-base/tsconfig.json b/packages/adapter-vercel/test/apps/paths-base/tsconfig.json new file mode 100644 index 000000000000..e8cd55f66e68 --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "$app/tsconfig", + "compilerOptions": { + "rewriteRelativeImportExtensions": true, + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "moduleResolution": "bundler" + }, + "include": ["src", "build.test.js", "vite.config.ts"] +} diff --git a/packages/adapter-vercel/test/apps/paths-base/vite.config.ts b/packages/adapter-vercel/test/apps/paths-base/vite.config.ts new file mode 100644 index 000000000000..2c055311f7c6 --- /dev/null +++ b/packages/adapter-vercel/test/apps/paths-base/vite.config.ts @@ -0,0 +1,12 @@ +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vite'; +import adapter from '@sveltejs/adapter-vercel'; + +export default defineConfig({ + plugins: [ + sveltekit({ + paths: { base: '/base' }, + adapter: adapter() + }) + ] +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1c65bc761dcd..30b50cdcf31a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -677,6 +677,30 @@ importers: specifier: 'catalog:' version: 5.0.1(@opentelemetry/api@1.9.1)(@types/node@22.20.4)(@vitest/browser-playwright@5.0.1)(@vitest/ui@5.0.1)(jsdom@30.1.0)(vite@8.3.0(@types/node@22.20.4)(esbuild@0.28.1)(yaml@2.9.1)) + packages/adapter-vercel/test/apps/paths-base: + devDependencies: + '@sveltejs/adapter-vercel': + specifier: workspace:* + version: link:../../.. + '@sveltejs/kit': + specifier: workspace:* + version: link:../../../../kit + '@sveltejs/vite-plugin-svelte': + specifier: 'catalog:' + version: 7.3.1(svelte@5.57.1(@typescript-eslint/types@8.70.1))(vite@8.3.0(@types/node@22.20.4)(esbuild@0.28.1)(yaml@2.9.1)) + svelte: + specifier: 'catalog:' + version: 5.57.1(@typescript-eslint/types@8.70.1) + typescript: + specifier: 'catalog:' + version: 6.0.3 + vite: + specifier: 'catalog:' + version: 8.3.0(@types/node@22.20.4)(esbuild@0.28.1)(yaml@2.9.1) + vitest: + specifier: 'catalog:' + version: 5.0.1(@opentelemetry/api@1.9.1)(@types/node@22.20.4)(@vitest/browser-playwright@5.0.1)(@vitest/ui@5.0.1)(jsdom@30.1.0)(vite@8.3.0(@types/node@22.20.4)(esbuild@0.28.1)(yaml@2.9.1)) + packages/adapter-vercel/test/apps/split: devDependencies: '@sveltejs/kit':