build(cloudflare): add a Cloudflare preview build target

DEPLOY_TARGET now selects the adapter; Netlify stays the default and NODE_ADAPTER
keeps working. Cloudflare compresses in transit, so the Worker build aliases
$lib/server/compression to a pass-through that leaves the streaming body alone.

CI builds and dry-run deploys this target. That is compilation and packaging
coverage only, not a production compatibility gate: native sharp still blocks the
share-preview route in the Worker runtime.
This commit is contained in:
Josh Creek
2026-09-15 17:47:14 +01:00
parent b2b750115f
commit 2766e5ea67
11 changed files with 1629 additions and 39 deletions
+2
View File
@@ -11,3 +11,5 @@ node_modules
pnpm-lock.yaml
package-lock.json
yarn.lock
.wrangler/
+17
View File
@@ -144,3 +144,20 @@ jobs:
if-no-files-found: ignore
- if: always()
run: npx supabase stop
cloudflare-preview-build:
runs-on: ubuntu-latest
timeout-minutes: 15
env:
WRANGLER_SEND_METRICS: 'false'
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run build:cloudflare
- run: npm run check:cloudflare
# This is compilation/package coverage, not a production compatibility gate.
# Native sharp still blocks the share-preview route in the Worker runtime.
+1
View File
@@ -17,3 +17,4 @@ playwright-report
test-results
/static/sprites-grid/
.wrangler/
+2 -1
View File
@@ -14,5 +14,6 @@ static/sprites-small/manifest.json
# Machine-local editor and tool settings.
**/*.local.json
# Generated grid artwork.
# Generated grid artwork and local Worker runtime output.
static/sprites-grid/
.wrangler/
+6 -15
View File
@@ -2,20 +2,11 @@ import process from 'node:process';
import AdapterNode from '@sveltejs/adapter-node';
import AdapterNetlify from '@sveltejs/adapter-netlify';
export const nodeAdapter = process.env.NODE_ADAPTER === 'true';
// Netlify is the deployment target; the node adapter exists so the service worker
// build tests can check the `build/client` layout a Node server produces, and so Lighthouse CI
// can audit a production build. Netlify's CDN compresses responses, so precompress here to match.
export const nodeAdapter =
process.env.NODE_ADAPTER === 'true' || process.env.DEPLOY_TARGET === 'node';
export const cloudflareAdapter = process.env.DEPLOY_TARGET === 'cloudflare';
export const adapter = nodeAdapter
? AdapterNode({ precompress: true })
: AdapterNetlify({
// if true, will create a Netlify Edge Function rather
// than using standard Node-based functions
edge: false,
// if true, will split your app into multiple functions
// instead of creating a single one for the entire app.
// if `edge` is true, this option cannot be used
split: false
});
: cloudflareAdapter
? (await import('@sveltejs/adapter-cloudflare')).default()
: AdapterNetlify({ edge: false, split: false });
+1565 -20
View File
File diff suppressed because it is too large Load Diff
+7 -2
View File
@@ -45,12 +45,16 @@
"migrate:convert-tsv": "node scripts/convert-tsv-to-sql.js",
"dev:local": "./scripts/dev-local.sh && npm run dev",
"dev:supabase": "supabase start && npm run dev",
"sprites:grid": "node scripts/grid-thumbnails.mjs"
"sprites:grid": "node scripts/grid-thumbnails.mjs",
"build:cloudflare": "DEPLOY_TARGET=cloudflare npm run build",
"preview:cloudflare": "wrangler dev",
"check:cloudflare": "wrangler deploy --dry-run"
},
"devDependencies": {
"@lhci/cli": "^0.15.1",
"@playwright/test": "1.55.1",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/adapter-cloudflare": "7.2.9",
"@sveltejs/adapter-netlify": "^4.1.0",
"@sveltejs/adapter-node": "^2.0.0",
"@sveltejs/adapter-static": "^3.0.0",
@@ -78,7 +82,8 @@
"tailwindcss": "^3.4.3",
"tslib": "^2.6.2",
"typescript": "^5.3.3",
"vitest": "^1.0.4"
"vitest": "^1.0.4",
"wrangler": "4.131.2"
},
"type": "module",
"dependencies": {
+4
View File
@@ -0,0 +1,4 @@
/** Cloudflare performs transport compression; preserve the streaming Response body. */
export function compressResponse(_request: Request, response: Response): Response {
return response;
}
+1 -1
View File
@@ -10,7 +10,7 @@ const config = {
preprocess: vitePreprocess(),
kit: {
// Netlify by default, or the node adapter when NODE_ADAPTER=true. See adapter.mjs.
// Netlify by default; DEPLOY_TARGET selects the Cloudflare preview or Node test build.
adapter,
serviceWorker: {
// VitePWA owns registration. Registering here as well requests SvelteKit's default
+11
View File
@@ -1,10 +1,21 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { fileURLToPath } from 'node:url';
import { defineConfig } from 'vite';
import { SvelteKitPWA } from '@vite-pwa/sveltekit';
// you don't need to do this if you're using generateSW strategy in your app
import { generateSW } from './pwa.mjs';
export default defineConfig({
resolve: {
alias:
process.env.DEPLOY_TARGET === 'cloudflare'
? {
'$lib/server/compression': fileURLToPath(
new URL('./src/lib/server/compression.cloudflare.ts', import.meta.url)
)
}
: {}
},
plugins: [
sveltekit(),
SvelteKitPWA({
+13
View File
@@ -0,0 +1,13 @@
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "livingdextracker-preview",
"main": ".svelte-kit/cloudflare/_worker.js",
"compatibility_date": "2026-09-15",
"compatibility_flags": ["nodejs_compat"],
"assets": {
"directory": ".svelte-kit/cloudflare",
"binding": "ASSETS"
},
"observability": { "enabled": true },
"vars": { "POKEDEX_PERFORMANCE": "true" }
}