Move hosting to Cloudflare Workers - #28
Merged
Merged
Conversation
Swaps adapter-vercel (pinned to nodejs22.x) for adapter-cloudflare and adds wrangler config. Adds the nodejs_compat flag, which SvelteKit's server runtime needs for node:async_hooks; without it the Worker throws at runtime rather than failing the build. The contact form rate limiter kept its counter in a module-level Map. That survives on a warm Node lambda but not on Workers, where each isolate would get its own empty counter and the limit would barely apply. checkRateLimit now prefers the Workers rate limiting binding and falls back to the in-memory limiter locally, in tests, and if the binding throws. The binding's period is restricted to 10 or 60 seconds, so this is a 5-per-60s burst guard rather than the previous 5-per-10-minutes window. Verified against the real workerd runtime with wrangler dev: every route including sitemap, rss, robots and llms.txt, and a contact form POST that exercised CSRF, the rate limit binding (5 through, 6th and 7th blocked) and the Resend call.
All content is bundled at build time through import.meta.glob, so nothing needed a per-request render. Prerendering the site turns 19 routes into static assets, which Cloudflare serves free and without invoking a Worker. Only two routes stay dynamic: /contact, because form actions need a live handler, and /rss.xml, because as a static file it would be typed application/xml by extension and lose the application/rss+xml header that some feed readers expect. The e2e suite caught that one. Dropped the s-maxage header on the homepage; it existed for Vercel's CDN and a prerendered page never renders per request. Also makes the Playwright base URL overridable via E2E_BASE_URL so the suite can run against the Workers build rather than the Vite dev server. Verified against workerd: 28 e2e, 13 unit, typecheck clean.
injectAnalytics posts to /_vercel/insights, which only exists on Vercel. Left in place it would have produced failing requests and console noise on every page view after the move, while collecting nothing. Cloudflare Web Analytics covers the same ground from the dashboard with no client code, if we want it back. Also updates the README, which still described adapter-vercel.
|
Vercel didn’t deploy this pull request to the CJ Dyas' projects team. GitHub couldn’t verify an account for commit 3448c49. Vercel blocks this deployment before it can verify the account’s access to the team. Review the commit before changing settings. If you don’t recognize it, don’t deploy it. Ask a repository administrator to investigate. If you do recognize it, verify the commit email in GitHub, connect that GitHub account to Vercel, then create a new commit and deploy again. Check your GitHub commit email · Troubleshoot Vercel access Commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moves the site off Vercel onto Cloudflare Workers. Verified against the real runtime rather than just a build, and deployed to a preview at https://cjdyas-design.dyascj.workers.dev where the full e2e suite passes.
Three things only showed up on the Workers runtime, none of which a build would have caught:
The contact form rate limiter also needed rethinking. It kept its counter in a module-level Map, which survives on a warm Node lambda but not on Workers, where each isolate gets its own empty counter and the limit barely applies. It now prefers the Workers rate limiting binding and falls back to the in-memory limiter locally, in tests, and if the binding throws. The binding only supports 10 or 60 second periods, so the window changes from 5 per 10 minutes to 5 per 60 seconds.
Prerendering: all content is bundled at build time through import.meta.glob, so nothing needed a per-request render. 19 routes are now static assets that Cloudflare serves without invoking a Worker. Only /contact and /rss.xml stay dynamic. This site was 43 percent of the Vercel account function CPU, almost all of it rendering pages that never change.
Playwright now takes an E2E_BASE_URL override so the suite can run against the Workers build or a live deployment instead of the Vite dev server.
Verification: 13 unit tests, typecheck clean, 28 e2e against local workerd, and 28 e2e against the live Cloudflare deployment.
Not done yet: secrets are not set on the Worker, so the contact form returns its not-configured path. DNS is untouched and the site still serves from Vercel.