diff --git a/.changeset/tricky-clocks-end.md b/.changeset/tricky-clocks-end.md
new file mode 100644
index 0000000000..8b57899881
--- /dev/null
+++ b/.changeset/tricky-clocks-end.md
@@ -0,0 +1,7 @@
+---
+'@astrojs/vercel': minor
+---
+
+The Vercel adapter now streams responses!
+
+This brings better performance to your visitors by showing them content as it is rendered. The browser can also start loading the required stylesheets and scripts much sooner, which ultimately results in faster full page loads.
diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts
index ea7cd7e533..621849688f 100644
--- a/packages/integrations/vercel/src/serverless/adapter.ts
+++ b/packages/integrations/vercel/src/serverless/adapter.ts
@@ -341,7 +341,7 @@ interface CreateFunctionFolderArgs {
NTF_CACHE: any;
includeFiles: URL[];
excludeFiles?: string[];
- maxDuration?: number;
+ maxDuration: number | undefined;
}
async function createFunctionFolder({
@@ -381,6 +381,7 @@ async function createFunctionFolder({
handler,
launcherType: 'Nodejs',
maxDuration,
+ supportsResponseStreaming: true,
});
}
diff --git a/packages/integrations/vercel/test/fixtures/streaming/astro.config.mjs b/packages/integrations/vercel/test/fixtures/streaming/astro.config.mjs
new file mode 100644
index 0000000000..b1a48b07df
--- /dev/null
+++ b/packages/integrations/vercel/test/fixtures/streaming/astro.config.mjs
@@ -0,0 +1,7 @@
+import { defineConfig } from 'astro/config';
+import vercel from '@astrojs/vercel/serverless';
+
+export default defineConfig({
+ output: "server",
+ adapter: vercel()
+});
diff --git a/packages/integrations/vercel/test/fixtures/streaming/package.json b/packages/integrations/vercel/test/fixtures/streaming/package.json
new file mode 100644
index 0000000000..80068581cc
--- /dev/null
+++ b/packages/integrations/vercel/test/fixtures/streaming/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "@test/vercel-streaming",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "@astrojs/vercel": "workspace:*",
+ "astro": "workspace:*"
+ }
+}
+
\ No newline at end of file
diff --git a/packages/integrations/vercel/test/fixtures/streaming/src/pages/one.astro b/packages/integrations/vercel/test/fixtures/streaming/src/pages/one.astro
new file mode 100644
index 0000000000..0c7fb90a73
--- /dev/null
+++ b/packages/integrations/vercel/test/fixtures/streaming/src/pages/one.astro
@@ -0,0 +1,8 @@
+
+
+ One
+
+
+ One
+
+
diff --git a/packages/integrations/vercel/test/fixtures/streaming/src/pages/two.astro b/packages/integrations/vercel/test/fixtures/streaming/src/pages/two.astro
new file mode 100644
index 0000000000..e7ba9910e2
--- /dev/null
+++ b/packages/integrations/vercel/test/fixtures/streaming/src/pages/two.astro
@@ -0,0 +1,8 @@
+
+
+ Two
+
+
+ Two
+
+
diff --git a/packages/integrations/vercel/test/static-assets.test.js b/packages/integrations/vercel/test/static-assets.test.js
index 7f360aebc7..92e37c0af9 100644
--- a/packages/integrations/vercel/test/static-assets.test.js
+++ b/packages/integrations/vercel/test/static-assets.test.js
@@ -7,9 +7,10 @@ describe('Static Assets', () => {
const VALID_CACHE_CONTROL = 'public, max-age=31536000, immutable';
- async function build({ adapter, assets }) {
+ async function build({ adapter, assets, output }) {
fixture = await loadFixture({
root: './fixtures/static-assets/',
+ output,
adapter,
build: {
assets,
@@ -38,31 +39,31 @@ describe('Static Assets', () => {
}
describe('static adapter', async () => {
- const adapter = await import('@astrojs/vercel/static');
+ const { default: vercel } = await import('@astrojs/vercel/static');
it('has cache control', async () => {
- await build({ adapter });
+ await build({ adapter: vercel() });
checkValidCacheControl();
});
it('has cache control other assets', async () => {
const assets = '_foo';
- await build({ adapter, assets });
+ await build({ adapter: vercel(), assets });
checkValidCacheControl(assets);
});
});
describe('serverless adapter', async () => {
- const adapter = await import('@astrojs/vercel/serverless');
+ const { default: vercel } = await import('@astrojs/vercel/serverless');
it('has cache control', async () => {
- await build({ adapter });
+ await build({ output: "server", adapter: vercel() });
checkValidCacheControl();
});
it('has cache control other assets', async () => {
const assets = '_foo';
- await build({ adapter, assets });
+ await build({ output: "server", adapter: vercel(), assets });
checkValidCacheControl(assets);
});
});
diff --git a/packages/integrations/vercel/test/streaming.test.js b/packages/integrations/vercel/test/streaming.test.js
new file mode 100644
index 0000000000..93dc95c395
--- /dev/null
+++ b/packages/integrations/vercel/test/streaming.test.js
@@ -0,0 +1,21 @@
+import { loadFixture } from './test-utils.js';
+import { expect } from 'chai';
+
+describe('maxDuration', () => {
+ /** @type {import('./test-utils.js').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/streaming/',
+ });
+ await fixture.build();
+ });
+
+ it('makes it to vercel function configuration', async () => {
+ const vcConfig = JSON.parse(
+ await fixture.readFile('../.vercel/output/functions/render.func/.vc-config.json')
+ );
+ expect(vcConfig).to.deep.include({ supportsResponseStreaming: true });
+ });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0bfaef6371..525adb49ac 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4731,6 +4731,15 @@ importers:
specifier: workspace:*
version: link:../../../../../astro
+ packages/integrations/vercel/test/fixtures/streaming:
+ dependencies:
+ '@astrojs/vercel':
+ specifier: workspace:*
+ version: link:../../..
+ astro:
+ specifier: workspace:*
+ version: link:../../../../../astro
+
packages/integrations/vercel/test/fixtures/with-speed-insights-enabled/output-as-server:
dependencies:
'@astrojs/vercel':