adapter-cloudflare: serve prerendered pages and static assets using `_routes.json`
See original GitHub issueDescribe the problem
From what I’ve seen and tested (please correct me), sites deployed via Cloudflare Pages still process prerendered pages (export const prerender = true;
) and static assets through _worker.js
. This means that even requests to static resources contribute to the host’s “function calls” budget.
Describe the proposed solution
This recently updated Cloudflare doc indicates that _routes.json
can be used to bypass _worker.js
, which typically handles all requests. By restructuring the build output folder (to serve static assets as they are normally routed in-app), we could take advantage of this feature. This would make adapter-cloudflare infinitely more viable for high traffic sites.
Alternatives considered
- Using adapter-static, but that only works if all of your site is prerendered.
- Stricter rate limiting, but that’s not scalable, reliable, or customizable (4 rules max on Cloudflare).
- Maybe surprise outages are OK ¯\_(ツ)_/¯
Importance
i cannot use SvelteKit without it
Additional Information
I understand that traditionally, the contents of the build output folder is not meant to be exposed, and that _worker.js
is meant to handle every request, even for static assets. However, I think that falling back onto Cloudflare Page’s built-in file routing would be well worth it if it meant saving actual money on hosting costs (or in my case, having my site stay live for the whole day).
Issue Analytics
- State:
- Created a year ago
- Reactions:3
- Comments:13 (4 by maintainers)
Cloudflare charges per “function” aka per Worker invocation. Requests to static assets on the site are not billable.
Consistent behaviour across platforms. Cloudflare Pages might serve assets, match paths, match URLs, etc. differently from the way SvelteKit wants to. That being said, it’s easier just to let SvelteKit handle all of it, even if it causes extra Worker invocations (billable).
For example, Cloudflare Pages lets you have a static
404.html
page. If I wanted to do that with SvelteKit, I’d have to implement an+error.svelte
file. The first approach is nice because it doesn’t invoke a Worker but cannot be dynamic. The second approach is the opposite.They get served the same way, and still get cached (luckily). The difference, as Rich mentioned above, is that every call to a static asset now invokes a Worker (unnecessarily, 99% of the time).
Yes, that’s what I was talking about in my earlier comments. Is there a way or us to track that “upstream auth” middleware, or do we just say “excluding prerendered routes is good enough for now”.
The (my) main concern is/was spending requests on just HTML assets (which are not cached by default on Cloudflare, along with worker responses). That being the case, calls to HTML files make up 80% of my current requests (again, until I bypass caching behaviour). In my own eyes, my revamped solution is “good enough”.
Realistically, you’d have to bypass this behaviour anyway if your site has a lot of endpoint calls, but that’s still a fairly big drop in worker calls (again, 80% for me, and I don’t even have to add any hooks or anything for
Cloudflare-CDN-Cache-Control
headers onto everything). However, you’re probably still gonna get plenty of bots/attackers/crawlers hitting/
on your site, so caching headers don’t help there. Implementing this change seems like a win-win-win to me.*I can PR it later, I just want to make sure I’m not missing something obvious