Check out a free preview of the full Astro for Fast Website Development course:
The "Enabling SSR & Forms" Lesson is part of the full, Astro for Fast Website Development course featured in this preview video. Here's what you'd learn in this lesson:

Jason explores the various rendering modes available in Astro and integrates a newsletter subscription form. By activating the hybrid rendering mode, Astro will default to pre-rendering and selectively server-render pages that opt out of this process.

Get Unlimited Access Now

Transcript from the "Enabling SSR & Forms" Lesson

>> A little quick recap of how far we've come together. We've got ourselves a homepage that has a hero image, it's got a teaser about our products. We have a blog that is running off of Astro content collections, we've got a shop that's running off third party data.

[00:00:17] It's got React components talking to solid components using nano stores, all partially hydrated so that we're not wasting any kilobytes that we don't need. And we've got a marked down page, and I think all that's left to do is the thing that no company is gonna let us get away without which is a newsletter list.

[00:00:37] So we're gonna add a newsletter capture, and we want this newsletter capture to work with standard like post submission of a form. So we're not gonna make it client side, we're not gonna escape with a React component or a solid component to handle it on click on the client side.

[00:00:57] We are instead going to use hybrid rendering or server side rendering for our newsletter components so that we can submit directly using the platform, and then catch those submissions, and do whatever it is we need to do with them. To sort of do that, we first need to talk a little bit about the different rendering modes in Astro.

[00:01:18] So let me just get over to server-side rendering. And the way that this works is Astro, by default, is going to precompile everything, they call it pre-rendering. So they will look at everything in your site, they will prerender it, and they will output as much of it as they can statically.

[00:01:38] And in my opinion, this is the right default because again, the vast majority of the things we build are static content. Even if we get them in very dynamic ways from API's through a lot of data crunching, whatever it is, what we're ultimately putting out on the screen is static content.

[00:01:54] It's not gonna change between users, it updates on a very active site maybe once or twice a day, maybe once or twice an hour if it's a really active page. And because of that, static is a good default, but that's not always the right choice, sometimes you need more.

[00:02:12] If you do have a use case where you wanna do server rendering like a form submission or something where the data updates to the second, then you can turn on server rendering in Astro. Now they have an option for output server which puts you into SSR mode. However, this puts the entire site into SSR mode.

[00:02:33] So it can be the right call, depending on what you're building. If everything you're building is behind a login and it will be completely customized based on the user for every single page load, and the data's always different, then a server rendered site might be the right call.

[00:02:48] And if that's the case you are covered with this. But what I find really exciting is this new mode of hybrid rendering, and the way that hybrid rendering works, let me see if I can find the actual note here. Here this is the one. The static pre-rendering by default.

[00:03:07] So this is, I think, probably where I would be looking to go. First, it's where we're gonna go today is this hybrid rendering mode. And so what hybrid rendering means is that by default everything is statically rendered just like if you didn't choose one of these options. But you can export a const called pre-render and say false, and this will tell everything in your site except this page to statically render.

[00:03:37] And that's really exciting because it means that you can selectively opt-in to server rendering as you need it. So, this follows that same mindset of partial hydration and only using code when you need code. It's the same general idea here. And I should clarify that when you use the SSR mode, you are able to export a const of prerender = true.

[00:04:01] But what I found when I started using it is that when I'm in server mode, I end up exporting prerender = true on almost every page in my project, except for one or two. So I really like hybrid mode where we flip that, it's static by default and then I turn on server rendering when I need it.

[00:04:17] So we are gonna use this static pre rendering by default. To actually add this, we are going to add this little block of config into our site. So I'm gonna open up the Astro config here, and we're gonna add in this little block. So inside the config, I'm going to add an output and mark that as hybrid.

[00:04:45] And then below that, we're gonna turn on an experimental flag so that we can put hybrid output. Set as true. I'm not sure when this will be turned off, but at some point in the future, I believe all you're gonna need is the output hybrid for this feature or for this functionality to work.

[00:05:07] Now that we have changed this, actually this is something I think is really cool about Astro is that it notices that your configuration updated and it'll restart for you. This is a this is one of those tiny little DX improvements that makes such a big difference. Because I don't know about y'all, but I have spent so much time in my career refreshing a page going, why isn't this working?

[00:05:29] And then I'll go back and I'll save it. I'll turn it off and I'll turn it back on, just to realize that I was either refreshing the wrong environment, or that I needed to restart the dev server to see that change get picked up. So little things that save those very frustrating small moments.

[00:05:46] Now that we've got this running, functionally nothing really changes, our site is still operating as our site always did. These are all statically rendered pages, but now we have an option to add a server rendered page. So I'm gonna go into our pages folder, create a new file and call this one newsletter.astro.

[00:06:06] And add some frontmatter like you do, get our layouts from layouts/default, no page, we want page this time. And then we're also going to export const prerender = false. And that's going to tell Astro that this is a server rendered page. So then add in our layout, I think.

[00:06:41] I got the form, I put the form into the workshop assets so that we don't have to write a form from scratch. So we can grab that form, we're going to first add in a heading. So an h1 with a class of heading and we'll say, get the sandwich newsletter, and then below, we'll paste in that form.

[00:07:09] And then we're also gonna need some styles, so we can head up to our assets yet again and grab those styles out of there. And now that we've done that, we have, A functioning site. So we can go to our newsletter here. Did I forget to save this?

[00:07:34] What is going on? I know what's going on. There's a class that I'm gonna use later, so make sure you add the newsletter visible so that that is visible in there. So this is standard newsletter form, you can fill it out and you can subscribe. And so it submits.

[00:08:00] But something important happened here. So I have this set as method post, right? And if I didn't have it set as method post, it would put the values from the form into the query string. Because it would be submitted as a get request, which would allow us to, grab it using JavaScript and send it off somewhere.

[00:08:20] And that's a perfectly valid way to to handle some of these things. But putting somebody's email address in a URL, maybe not the best idea in the world just because there are ways for people to get out that, you don't really wanna leak people's emails, that can cause you some problems as a business.

[00:08:35] So we're using the post, so that it will submit to the page as the body of the request as opposed to a query parameter. And the next thing we need to do is actually do something with this. What's happening? How are we getting to this? And you just kind of don't have any indication that anything has happened.

[00:08:54] So the next thing we need to do is actually process this. So to handle a form submission, we have a nice, I was actually very pleasantly surprised by how pleasant or how nice this API is. So I get a message, and the way that we're doing this just so everybody's clear on why I'm creating a message here.

[00:09:14] I'm going to take the name and e-mail that gets submitted, put them into a message, and then print those on the screen. And that's how we're gonna handle the form submission. Again, we're not going to set up a newsletter service. It's a lot of steps, you've got to have accounts, I don't know that any of them have an easy free setup, so that's more of an exercise me.

[00:09:38] Find their API Doc's and you would submit to their API from this process. But for us, we're just gonna show that the submission actually worked. So we're gonna grab that message and then we can say if Astro request method, so this is similar to astro.props, it's part of that global Astro object, and I want to check if it is post.

[00:10:00] And if it's post, I get to do stuff. So I'm gonna try to do a few things, and if something goes wrong, I will catch that error, and then we'll just log it, so we can console.error. And so in here, what I wanna do is I wanna get the data out of the Astro request.

[00:10:23] So I'm gonna get astro.request, and then we can use form data, which is a browser API. So that's part of the request object includes a body, you can get the form data from the body. And then I want the name, which is data.get and the input name. So these names here are the ones that we're using.

[00:10:48] So name, we get the name, email, we get email. Great. Then this is where you would save the user info to your newsletter service, make this bigger again. And then down below, we're just gonna update this message, so we're gonna say subscribed as well, we'll say the name with the email.

[00:11:32] Great. And then down here in the body itself, we're gonna add a new section between the header and the form itself. And we're gonna use a little helper that I like from Astro called ClassList. And so what ClassList does is sometimes you have a value in your code that makes a class conditional and you end up writing these really just kind of messy looking ternaries.

[00:12:03] Or you have to declare your classes outside and then kind of pass them in as a variable. And Astro just was like, don't bother this is fine. So instead, what you can do is you can just set the class name. So in this case, we want to a class of success.

[00:12:18] That one's always true. But then whether or not it's visible is it gonna be dependent on whether or not we have a message. So we can say only add the visible class if there's a message set. And then inside, we can set the message itself and we'll just boop.

[00:12:36] And then we can add a link just to the newsletter page itself. And this will get us out of the post request and start over. So it's kinda like clearing everything. Then I'm also going to update this newsletter here, and I'm gonna change this to a class list.

[00:12:59] And we're going to have newsletter that's always on but then visible in this case Is dependent on there not being a message. So just the opposite. So if the form has been submitted, don't show the form, show the message. If there is no message, if it wasn't a form submission, show the form.

[00:13:18] So a little bit of logic, all rendered on the server. And then once we've done that, we save. Head back out to our browser, and you can see because this was submitted, it actually picked up that post request and is now showing us the details. And so, the next thing I wanna do is I want to show that this does in fact work without JavaScript.

[00:13:46] So we're gonna disable JavaScript, we're going to add one of these. And it still works, riight? And so this is like, I get why people want server rendering. I feel like I've spent a lot of time during this workshop saying you don't need server rendering, it's not important.

[00:14:05] That's not what I'm saying, there are a lot of good reasons to include server rendering. I am not against server rendering as a concept, I'm against server rendering as a default. I think that server rendering should be opted into when you have an actual reason to use it.

[00:14:18] And at that point, it becomes incredible. I love that this just works with JavaScript disabled amazing. Chef's kiss, love it, do it every time. However, nothing else on this website needs to be server rendered. And therefore, I don't want to have to opt in to server rendering for my entire project, just for this one form that needs server rendering.

[00:14:41] So, before I forget cuz that'll be confusing, later, I'm gonna re-enable JavaScript. And then when we click this, it's, I got a pop up of some sort, cancel. We were talking about you buy earlier. Yeah, that's a great reason not to use your buy. Did you see that the alert got put under the browser because the stack order got screwed up.

[00:15:07] So that's a fun, that's a fun problem to get to solve. Where are you going? You come back, you came back, and then you get out of there. All right, good. Okay, we're back to mostly normal here. Okay, so now what we've got, is we've got a pre-rendered newsletter page and this whenever we submit it, it's gonna work.

[00:15:33] I'll do it one more time now with the JavaScript on. And same result, it just posts to that page. And then when we're done, we hit start over and we start over.