TLDR: I'm doing Server-Side Rendering (SSR) of a Svelte for JSS application in a Cloudfare Worker running against a (very) small Azure VM. The demo site is available here: https://silent-resonance-320e.aelamarre.workers.dev/.
Unfamiliar with Sitecore JSS? Read more about it here.
If you follow me on Twitter, you might have seen me retweet this:
Sitecore Symposium was about to happen and I just didn't have time to really explore this idea and see if it was viable for Svelte for JSS. I ultimately wanted to know if I could use Cloudflare Workers to handle the Server-Side Rendering of a Sitecore JSS application... is Svelte SSR fast enough?
First, let's start by taking a look at the plans that Cloudflare has available:
Whoa. I think those plans are pretty generous. Free gives you 100,000 requests free a day? For $5 you can get 10 million requests a month? Huh? The interesting bit is the second line on the free tier, 10ms of CPU time per request. That means whatever we do in the worker has to be fast. Unlimited increases this limit to 50ms.
When you deploy any worker on Cloudflare, they give you a unique URL for your worker and when you hit anything on that worker, it triggers your worker code to run.
If you have watched or attended my Symposium presentation, you'll remember that if you tell Svelte that you want SSR functions built when you compile your code, it will generate these functions that just return a string representation of your component and any nested components are just built using string functions as well and the whole thing takes advantage of template literals.
So all of the sample applications have the ability to render a page in under 2ms. Note, these numbers were generated locally and they all describe just the time performing Server-Side Rendering against completely prefetched data. Times could vary depending on how complex your page is. This only accounts for the time to go from prefetched, in memory data to HTML. No transfer time or time taken to prefetch data is accounted for in these numbers. Svelte clocks in at under a half ms for a single render, which is so mind boggling that I second guess it every time I read it.
What's nice here is that we're only truly constrained by CPU time. This is important because consider we navigate to
/styleguide or any other page on our Cloudflare worker. We still need to retrieve data from our origin server layout service to be able to even render our sample application.
What's amazing here is we can call the
fetch function in our worker and it does not take up any CPU time because we can just leverage
await in our worker and only do work when the call completes.
So that's neat... because requests do not count against us, we can easily fit a full SSR within the free tier but Unlimited is probably the way to go and I'll explain the next section.
So to prove that this could be done, I deployed the full sample application to a worker: https://silent-resonance-320e.aelamarre.workers.dev/.
This is running in connected mode and is powered by a $100 a month Azure VM that is running absolutely everything on it... Solr, SQL express, xConnect. It's the whole thing. There is no caching currently on the edge for any of the layout service calls. You'll notice the client side routing is making requests through my worker as well. These requests are just being proxied (currently ;)).
This is running in an Unlimited plan for one simple reason: I wanted to upload my JS/CSS bundles to Cloudflare. I could have just put them on another CDN but I thought it would be nice to keep it all in one location. I could justify $5 for this. Plus, obviously I'm going to get over 100,000 visits a day on it. Obviously.
If you've made it this far and are still reading, I have a bonus: you can even make your Cloudflare worker your Rendering Host in Sitecore. I adapted some of Adam Weber's gist located here. So you can do something crazy like this in our JSS application config (Sitecore 9.2 only):
<app name="svelteclean" sitecorePath="/sitecore/content/svelteclean" useLanguageSpecificLayout="true" graphQLEndpoint="/api/svelteclean" serverSideRenderingEngine="http" serverSideRenderingEngineEndpointUrl="https://silent-resonance-320e.aelamarre.workers.dev/jss-render" inherits="defaults" />
So now Cloudflare is now responsible for building the Experience Editor version of pages now as well.
Isn't that cool? Just to be absolutely clear, the only place my
server.bundle exists is on the edge. I'm not running any SSR proxies or rendering host instances of my own. It's all been moved to edge.
Where's the code?
It's largely still a work in progress so I'm not quite ready to release the implementation for this. I will say I did have to restructure things a bit in the jss-svelte application to make this work right and all of those changes will be merged into master this week so if you wanted to put together something yourself in the mean time, you could.
Get in touch if you're really interested though.
This feels like the future to me. There's lots left to explore here.