Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-server-island-dev-build-output.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes server islands returning a 500 error in dev mode for adapters that do not set `adapterFeatures.buildOutput` (e.g. `@astrojs/netlify`)
11 changes: 7 additions & 4 deletions packages/astro/src/core/dev/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ export async function createContainer({
.map((r) => r.clientEntrypoint)
.filter(Boolean) as string[];

// Set the initial buildOutput default before runHookConfigDone, so that
// setAdapter() inside astro:config:done can upgrade it to 'server'.
// This matches the ordering in the build path (packages/astro/src/core/build/index.ts).
if (!settings.adapter?.adapterFeatures?.buildOutput) {
settings.buildOutput = getPrerenderDefault(settings.config) ? 'static' : 'server';
}

// Create the route manifest already outside of Vite so that `runHookConfigDone` can use it to inform integrations of the build output
await runHookConfigDone({ settings, logger, command: 'dev' });

Expand All @@ -94,10 +101,6 @@ export async function createContainer({
dev: true,
},
);
// If the adapter explicitly set a buildOutput, don't override it
if (!settings.adapter?.adapterFeatures?.buildOutput) {
settings.buildOutput = getPrerenderDefault(settings.config) ? 'static' : 'server';
}
const viteConfig = await createVite(
{
server: { host, headers, open, allowedHosts },
Expand Down
26 changes: 26 additions & 0 deletions packages/astro/test/server-islands.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,32 @@ describe('Server islands', () => {
});
});

it('can fetch the server island endpoint in dev with adapter that does not set buildOutput', async () => {
// Use an adapter that does NOT set adapterFeatures.buildOutput,
// like @astrojs/netlify. This triggers the bug in container.ts where
// buildOutput is reset to 'static' after runHookConfigDone sets it to 'server'.
const devFixture = await loadFixture({
root: './fixtures/server-islands/hybrid',
adapter: testAdapter({
extendAdapter: {
adapterFeatures: {},
},
}),
});
const devServer = await devFixture.startDevServer();
try {
const res = await devFixture.fetch('/');
assert.equal(res.status, 200);
const html = await res.text();
const fetchMatch = /fetch\('(\/_server-islands\/Island[^']*)/.exec(html);
assert.ok(fetchMatch, 'should have a server island fetch URL');
const islandRes = await devFixture.fetch(fetchMatch[1]);
assert.equal(islandRes.status, 200, 'server island endpoint should return 200, not GetStaticPathsRequired error');
} finally {
await devServer.stop();
}
});

describe('with no adapter', () => {
let devServer;

Expand Down