Skip to content

Commit 829182b

Browse files
fix: server islands broken in dev mode with adapters that don't set buildOutput (#15703)
* fix: set buildOutput default before runHookConfigDone in dev mode (#15701) Server islands in dev mode with adapters that don't set adapterFeatures.buildOutput (like @astrojs/netlify) were broken because buildOutput was reset to 'static' after runHookConfigDone already set it to 'server' via setAdapter(). This moves the default assignment before runHookConfigDone, matching the build path ordering. * add changeset * Update .changeset/fix-server-island-dev-build-output.md Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev> * Simply test * Update regex method --------- Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>
1 parent 862d77b commit 829182b

3 files changed

Lines changed: 38 additions & 4 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Fixes server islands returning a 500 error in dev mode for adapters that do not set `adapterFeatures.buildOutput` (e.g. `@astrojs/netlify`)

packages/astro/src/core/dev/container.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ export async function createContainer({
7878
.map((r) => r.clientEntrypoint)
7979
.filter(Boolean) as string[];
8080

81+
// Set the initial buildOutput default before runHookConfigDone, so that
82+
// setAdapter() inside astro:config:done can upgrade it to 'server'.
83+
// This matches the ordering in the build path (packages/astro/src/core/build/index.ts).
84+
if (!settings.adapter?.adapterFeatures?.buildOutput) {
85+
settings.buildOutput = getPrerenderDefault(settings.config) ? 'static' : 'server';
86+
}
87+
8188
// Create the route manifest already outside of Vite so that `runHookConfigDone` can use it to inform integrations of the build output
8289
await runHookConfigDone({ settings, logger, command: 'dev' });
8390

@@ -94,10 +101,6 @@ export async function createContainer({
94101
dev: true,
95102
},
96103
);
97-
// If the adapter explicitly set a buildOutput, don't override it
98-
if (!settings.adapter?.adapterFeatures?.buildOutput) {
99-
settings.buildOutput = getPrerenderDefault(settings.config) ? 'static' : 'server';
100-
}
101104
const viteConfig = await createVite(
102105
{
103106
server: { host, headers, open, allowedHosts },

packages/astro/test/server-islands.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,32 @@ describe('Server islands', () => {
394394
});
395395
});
396396

397+
it('can fetch the server island endpoint in dev with adapter that does not set buildOutput', async () => {
398+
// Use an adapter that does NOT set adapterFeatures.buildOutput,
399+
// like @astrojs/netlify. This triggers the bug in container.ts where
400+
// buildOutput is reset to 'static' after runHookConfigDone sets it to 'server'.
401+
const devFixture = await loadFixture({
402+
root: './fixtures/server-islands/hybrid',
403+
adapter: testAdapter({
404+
extendAdapter: {
405+
adapterFeatures: {},
406+
},
407+
}),
408+
});
409+
const devServer = await devFixture.startDevServer();
410+
try {
411+
const res = await devFixture.fetch('/');
412+
assert.equal(res.status, 200);
413+
const html = await res.text();
414+
const fetchMatch = /fetch\('(\/_server-islands\/Island[^']*)/.exec(html);
415+
assert.ok(fetchMatch, 'should have a server island fetch URL');
416+
const islandRes = await devFixture.fetch(fetchMatch[1]);
417+
assert.equal(islandRes.status, 200, 'server island endpoint should return 200, not GetStaticPathsRequired error');
418+
} finally {
419+
await devServer.stop();
420+
}
421+
});
422+
397423
describe('with no adapter', () => {
398424
let devServer;
399425

0 commit comments

Comments
 (0)