v0.4.0 went stable today after a year of development: https://github.com/framesurge/perseus/discussions/270
v0.4.0 went stable today after a year of development: https://github.com/framesurge/perseus/discussions/270
“Perseus apps can generate state whenever they like”
So it’s a… computer program?
It feels like the word “state” is overloaded with some meaning that eludes me.
https://framesurge.sh/perseus/en-US/docs/next/state/intro
Seems like snapshots of the current data view, in this case.
Leptos is another frontend library that uses Signals and does not use a VDOM. https://github.com/leptos-rs
I think the key feature of these frontend frameworks is they enable Rust developers to do full-stack web development in the same way Nodejs enabled front end developers to do full-stack.
But it feels like a bit of a stretch. The whole point of SSG is to simplify your architecture and tooling by forgoing the ability to dynamically render content on the server. It is a trade-off that won't be suitable for every application, and that's absolutely fine.
If you want to argue that SSR tooling can be so simple and cheap that the SSG trade-off isn't worth it, then I'm keen to learn about that.
But to elide the distinction between the two seems unhelpful to me.
Yes it is limiting, and it won't be appropriate for many use cases. But if you can do it, it makes things simpler, cheaper and more efficient.
That's not to say you can't combine SSG tooling with dynamic content too if you need it. But static-only is a perfectly valid choice if you can get away with it.
If you live in Tokyo and connect to a website in Oregon, this effectively static could be ~100ms (served by origin) vs actual static that's ~10ms (served by CDN local PoP).
Side note: this is why developers need to care about infrastructure and vice versa. I distinctly dislike the abstract separations as the implementation details always matter.
- SSR: Dynamic rendering of paths, happening at runtime.
- SSG: Static rendering of paths, happening at compile time.
A separation makes it much clearer that the core difference here is that SSG can only take you as far as "something generic for everyone" and SSR will be able to render "a page unique for a specific user".
Infrastructure-wise there is a world of difference between the two approaches and they are not even close to being related.
- SSR: You'll need servers, scaling, load balancing, etc.
- SSG: CDN + S3 and you're done
EDIT: To add a bit, imagine the following "I'm using SSR.", "Ah, cool, like full SSR or only half SSR?", "Only half, serving static files" - at this point, it's clear that we've now overloaded SSR to be a less useful term to describe what it is, which I personally find quite unfortunate.
It all works super slick and conceptually there’s actually very little complexity for those applying it (the frameworks take care of the difficult bits). Since this is happening at the edge (in Cloudflare’s case, where I work, within something like 50ms of transit time to 95% of the population), and you’re only doing the initial view, you can get websites that load large pieces of content much more quickly than rendering it client side which is dominated by less powerful devices (ie SSR+transfer time is competitive) with less bandwidth/higher latency if you’re collating responses from different backends. You could even see that extending where they prefetch the raw data you’ll need to render the rest of the page in the background and either prepare a rendering, just bring it closer into the cache as a prefetch, or even push it to your browser proactively.
Now of course it’s possible this stuff won’t generalize but I don’t see any obvious obstacles. It feels like within 10 years this could be the dominant way client web apps will be written. I get that we originally used to do that but it’s about taking the best of both worlds (SSR let’s you get super high performance initial loads while dynamic client side handling let’s you handle interactivity better and doing it transparently makes your development process a heck of a lot simpler as you don’t really need to differentiate the code as much (whereas I think you would with SSG+SSR). For SSG you probably don’t need to find general pieces of content and set up a different layer vs changing some caching parameters / doing content based hashing transparently.
I think that’s maybe the direction OP was heading with in his remark of the distinction not being helpful.
> edge compute platform
I would consider that quite a big difference in infrastructure. It can easily be done already right now, but the cost and performance equation between serverless compute (at edge or not) v.s. static file serving becomes noticeable at scale.
Let's make some pricing examples:
- We'll have 2 million "first page loads" per day (~60 million per month)
- Let's give our bundle a low estimate of 200KB
------------
Vercel's pricing (just to take a popular example)[0]:
- Pro tier: $20/month includes 1m execution units (EU, 50ms of CPU time) and 1TB bandwidth
- Then $2 per 1m EU and $40 per 100 GB bandwidth
- Let's ignore GB-hours for now (memory x runtime)[1]
- Let's assume you're always able to render your SSR page in 50ms or less (quite optimistic if you're doing any form of DB operations in your SSR)
AWS CloudFront pricing[2]:
- Always free tier: 1TB bandwidth, 10m requests
- Then $0.085 per GB bandwidth and $0.0100 per 10k requests
- (at scale you can get +50% discount on bandwidth by committing)
------------
We can then run the numbers:
- Estimate (200 KB) on Vercel:
- (60m requests - 1m free) * $2 per 1m = $118/month
- 200 KB * 60 million = 12,000,000,000 kb = 12TB
- (12TB - 1TB free) / 0.1 * $40 per 100GB = $4400/month (you'd probably want an Enterprise plan at this point unless I did the math wrong here. Their FAQ suggests to reach out to their sales team which you should definitely be doing at this scale!)
- = $118 + $4400 = $4,518/month
- Estimate (200 KB) on CloudFront: - (60m requests - 10m free) / 0.01 * $0.01 per 10k request = $50/month
- 200 KB * 60 million = 12,000,000,000 kb = 12TB
- (12TB - 1TB free) / 0.001 * $0.085 per GB = $935/month (which could be $440/month with reserved capacity)
- = $50 + $935 = $985/month
------------Totally open for having made a calculation error above, but this is the kind of thing that one needs to concern themselves about at scale. The above example is quite realistic, in fact it's a lot less than our usage at my current work.
Admittedly here we are seeing most of the cost come from bandwidth. If you substituted Vercel with AWS Lambda you would be able to benefit from the CloudFront pricing on this.
[0]: https://vercel.com/pricing
[1]: https://vercel.com/guides/what-are-gb-hrs-for-serverless-fun...
Cost isn't the only thing to care about but performance. Functions might not run in every data center that would have a CDN PoP. The SSR vs SSG comparisons always miss the point and claim SSR is faster but that's only true if you're in a big popular city. As you expand - what about the other customers?
Also what about security - that's probably even more important. Each request for Vercel has a higher cost than the equivalent from Cloudfront. What are the safeguards e.g. rate limiting or DoS protection? For Cloudfront you'd need to account for WAF and other expenses.
You don't even need a lot of customers - just a bad actor to easily take down your hosting on Vercel. There have been plenty of blogs of startups using serverless setups getting attacked that costed them 1000s - 10000s of dollars.
Side note: bandwidth costs vary. Vercel does it with 1 price, so things may vary depending on where your users are. Cloudfront costs can go up. You may also need Cloudfront functions to do a few things.
You can manage DDoS and rate limiting protections although I don’t know the pricing on those (could be free - I don’t recall).
Disclaimer: work at Cloudflare
For many workloads Cloudflare can be more expensive.
* The closest one may already be at capacity, requiring rerouting some traffic away.
* ISPs in some parts of the world are weirdly fragmented, not interconnecting with other ISPs in the same region. As a result, if you're on the "wrong ISP", the network distance to the local colo may be longer than to some other colo that is physically further away.
* To serve content from servers in China, you must have an ICP license from the Chinese government. If you don't have that, Cloudflare will send Chinese traffic to the closest non-Chinese colo.
* Probably other reasons I'm not thinking of off the top of my head.
Note that all these apply to Cloudflare in general regardless of whether you use Workers. Enabling Workers has no effect on what datacenter you get routed to. Cloudflare's infrastructure team is always working to improve these situations, e.g. adding more servers, negotiating more connectivity, etc.
A nice thing about building on Workers is you don't have to worry about any of this. E.g. you don't need to think about redirecting your traffic when a colo is over capacity... it happens automatically.
(I'm the tech lead for Workers.)
I'm referring to e.g. https://community.cloudflare.com/t/does-free-plan-cloudflare... where the poster says:
"For predominantly Australian traffic, you’d probably need CF Business or Enterprise plan. For India traffic, would need CF Enterprise plan."
Where do workers run in this instance and what impacts are there say if I'm not on a business or enterprise plan?
Point being if we do need an enterprise or business plan for these features it's not 100% free.
All I can say is that if you use Workers, the Worker always runs in the datacenter that receives your request, which is exactly the same datacenter that would have received your request if you weren't using Workers.
Disclaimer: work at Cloudflare.
That said, super interesting to see the CloudFlare dropped the egress costs![0] That would make the equation for them probably the most attractive, although that will only be the case as long as you are then not having your CloudFlare Workers talking with e.g. an AWS database which will then just move the egress costs there instead (internal traffic can sometimes be orders of magnitude higher than external).
If you only use it for SSR and only keep whatever SSR is using to offerings within CloudFlare, then it looks to be the most competitive offering for that so far. Your API can still go other places, so little downside there.
One concern I would have, having been quite deep in AWS Lambda, is the 128MB memory limit on CloudFlare workers (unless I misunderstood and it can go higher?). For JS frameworks, that very likely has performance implications, whereas for Rust frameworks, they will be able to perform well within the lower memory limits. Lambda is a bit different though, since the CPU scales with memory, so would be curious if there are any benchmarks on CF Workers with these frameworks?
[0]: https://blog.cloudflare.com/workers-now-even-more-unbound/
1. Last I checked (admittedly not recently), Lambda throttles CPU proportionally to memory size, e.g. as I recall a 128MB instance is throttled to 1/8 CPU core, 256MB is 1/4, etc. Workers never throttles.
2. The same code running on Workers will use far less memory than when running on Lambda. In fact, the average Worker uses around 3MB RAM. The difference here is that Lambda is counting the memory for the whole runtime process, e.g. a Node.js process, whereas with Workers the runtime is shared with other tenants and only the pure JavaScript heap usage counts against the memory limit.
So, 128MB goes further with Workers.
That said, obviously some apps need more. At present we don't have a way to increase this limit, but we're working on it.
(I'm the tech lead for Workers.)
If you consider Cloudflare Workers pricing, it becomes a lot more competitive. No egress + much lower per request fees + you can choose between per wallclock ms billing and per request billing (different slopes + intersection points).
I'm not claiming we're a good fit for every use-case out there. My root point though was about SSR and I think a platform like Cloudflare Workers is perfect for making SSR extremely simple.
Disclaimer: Work at Cloudflare. My opinions are my own.
Traditionally an SPA has been just one single bundle file that is downloaded. With SSG you pre-generate a file per path which gives the user many of the benefits of SSR on that first page load, before the SPA part takes over again.
It's good if your platform can support it.
We're now given something that has routing i.e. NextJs but then allowed a SSG option that behaves somewhat different.
Also I don't want to squash them either but dynamic vs static is for instance much more appropriate, it's a shortcut for request-time vs build-time server rendering.
So to me and many others whether a framework can do SSR or SSG is a very important distinction, critical for infrastructure planning. I often see it being downplayed together with a promotion of various proprietary platforms offering edge computing but this stuff is just not necessary for many cases.
Edit: No idea what terminology is used at NextJS, above is what I think is generally understood by SSG (static site) and SSR (server-rendered site).
I could get behind static vs dynamic, but “server-side” has no meaning then to me, since there is no server/backend men at to be involved for the static part then (at least in my mental model of it).
Any CDN (CloudFront, CloudFlare, etc) coupled with any blob storage (S3 and others) vs the following:
- Servers to run your node process
- Load balancing to handle distributing traffic between several servers for your SSR’ed app
How do you then run and update your servers? You now need to start thinking about zero-downtime rollouts, and grab something like ECS or the big hammer k8s. You can still handhold your own EC2 instances, but then you’re now home brewing a solution.
The simplification of infrastructure that “static files” bring is not to be underestimated :)
Sure, but in common parlance that’s not really a useful point. There are also servers involved in serverless, but we’ve largely accepted that here it is meant to indicate (on a gradient) who manages those servers :)
When you set up your infrastructure, it will matter quite a lot whether you’re able to utilize a CDN as the only thing you need to deploy to, or if you need to run your own code at runtime (and hence need a something to run it on).
It’s worth noting: You can absolutely go for all of these solutions! I do have a bit of a penchant for solutioning things that I know will scale up massively, but that is not always a priority early on, so I don’t want anyone to be discouraged by these approaches and the other benefits they can provide :)
> there is always a server and a user request around even when you render statically
I’d love to dive into that part a bit more, genuinely curious! Is the point that there is always dynamic information to act on to improve the user experience? Or what would be the goal or vision once you know that?