Skip to content

Commit ee519e5

Browse files
authored
fix(cloudflare): remove worker output for fully static sites (#15478)
* fix(cloudflare): remove worker output for fully static sites When all non-internal routes are prerendered, the _worker.js directory is now removed from the build output since it's not needed for static deployments. - Detect fully static sites in astro:routes:resolved - Remove _worker.js directory in astro:build:done for static sites - Change staticOutput support from 'unsupported' to 'stable' - Add test fixture and test for static output * fix: remove unused HookParameters import * Update lockfile * fix: require at least one non-internal route to be considered fully static
1 parent a71856a commit ee519e5

File tree

7 files changed

+77
-7
lines changed

7 files changed

+77
-7
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@astrojs/cloudflare": patch
3+
---
4+
5+
Fixes fully static sites to not output server-side worker code. When all routes are prerendered, the `_worker.js` directory is now removed from the build output.

packages/integrations/cloudflare/src/index.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { createReadStream, existsSync, readFileSync } from 'node:fs';
2-
import { appendFile, stat } from 'node:fs/promises';
2+
import { appendFile, rm, stat } from 'node:fs/promises';
33
import { createInterface } from 'node:readline/promises';
44
import { removeLeadingForwardSlash } from '@astrojs/internal-helpers/path';
55
import { createRedirectsFromAstroRoutes, printAsRedirects } from '@astrojs/underscore-redirects';
66
import { cloudflare as cfVitePlugin, type PluginConfig } from '@cloudflare/vite-plugin';
77
import type {
88
AstroConfig,
99
AstroIntegration,
10-
HookParameters,
1110
IntegrationResolvedRoute,
1211
} from 'astro';
1312
import { astroFrontmatterScanPlugin } from './esbuild-plugin-astro-frontmatter.js';
@@ -79,9 +78,9 @@ export type Options = {
7978

8079
export default function createIntegration(args?: Options): AstroIntegration {
8180
let _config: AstroConfig;
82-
let finalBuildOutput: HookParameters<'astro:config:done'>['buildOutput'];
8381

8482
let _routes: IntegrationResolvedRoute[];
83+
let _isFullyStatic = false;
8584

8685
const sessionKVBindingName = args?.sessionKVBindingName ?? DEFAULT_SESSION_KV_BINDING_NAME;
8786
const imagesBindingName = args?.imagesBindingName ?? DEFAULT_IMAGES_BINDING_NAME;
@@ -233,10 +232,13 @@ export default function createIntegration(args?: Options): AstroIntegration {
233232
},
234233
'astro:routes:resolved': ({ routes }) => {
235234
_routes = routes;
235+
// Check if all non-internal routes are prerendered (fully static site)
236+
const nonInternalRoutes = routes.filter((route) => route.origin !== 'internal');
237+
_isFullyStatic =
238+
nonInternalRoutes.length > 0 && nonInternalRoutes.every((route) => route.isPrerendered);
236239
},
237-
'astro:config:done': ({ setAdapter, config, buildOutput, injectTypes, logger }) => {
240+
'astro:config:done': ({ setAdapter, config, injectTypes, logger }) => {
238241
_config = config;
239-
finalBuildOutput = buildOutput;
240242

241243
injectTypes({
242244
filename: 'cloudflare.d.ts',
@@ -254,7 +256,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
254256
supportedAstroFeatures: {
255257
serverOutput: 'stable',
256258
hybridOutput: 'stable',
257-
staticOutput: 'unsupported',
259+
staticOutput: 'stable',
258260
i18nDomains: 'experimental',
259261
sharpImageService: {
260262
support: 'limited',
@@ -387,7 +389,7 @@ export default function createIntegration(args?: Options): AstroIntegration {
387389
),
388390
),
389391
dir,
390-
buildOutput: finalBuildOutput,
392+
buildOutput: _isFullyStatic ? 'static' : 'server',
391393
assets,
392394
});
393395

@@ -402,6 +404,11 @@ export default function createIntegration(args?: Options): AstroIntegration {
402404
}
403405
}
404406

407+
// For fully static sites, remove the worker directory as it's not needed
408+
if (_isFullyStatic) {
409+
await rm(_config.build.server, { recursive: true, force: true });
410+
}
411+
405412
// Delete this variable so the preview server opens the server build.
406413
delete process.env.CLOUDFLARE_VITE_BUILD;
407414
},
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import cloudflare from '@astrojs/cloudflare';
2+
import { defineConfig } from 'astro/config';
3+
4+
export default defineConfig({
5+
adapter: cloudflare(),
6+
output: 'static',
7+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "@test/astro-cloudflare-static",
3+
"version": "0.0.0",
4+
"private": true,
5+
"scripts": {
6+
"build": "astro build"
7+
},
8+
"dependencies": {
9+
"@astrojs/cloudflare": "workspace:*",
10+
"astro": "workspace:*"
11+
}
12+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<html>
2+
<head>
3+
<title>Static Site</title>
4+
</head>
5+
<body>
6+
<h1>Static Site</h1>
7+
<p>This is a fully static Astro site using the Cloudflare adapter.</p>
8+
</body>
9+
</html>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { describe, it } from 'node:test';
2+
import { loadFixture } from './_test-utils.js';
3+
import assert from 'node:assert/strict';
4+
import { existsSync } from 'node:fs';
5+
import { fileURLToPath } from 'node:url';
6+
7+
describe('Static output', () => {
8+
let fixture;
9+
10+
it('should not output a _worker.js directory for fully static sites', async () => {
11+
fixture = await loadFixture({
12+
root: './fixtures/static',
13+
});
14+
15+
await fixture.build();
16+
17+
const workerExists = existsSync(fileURLToPath(new URL('_worker.js', fixture.config.outDir)));
18+
19+
assert.ok(!workerExists, '_worker.js directory should not exist for static sites');
20+
});
21+
});

pnpm-lock.yaml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)