ASTRO JS | P2 | SSG and SSR
Tags: html, javascript, webdev, tutorial
Published: 2024-07-03 08:08:53

Hello my fellow web developers, today i will be continuing my astro js series with the second part where we are going to cover some more topics like SSG, SSR, and Hybrid mode. It is mostly related to how we are going to render our pages and in which mode

- [What is SSG?](#ssg)
- [What is SSR?](#ssr)
- [What is Hybrid Mode?](#hybrid-mode)
- [Enabling SSG, SSR and Hybrid(SSG + SSR) mode](#render-mode)
- [SSG and SSR on single page](#ssg-ssr-single)
- [Data fetching](#data-fetching)

<a id="ssg"></a>
## What is SSG?
* Definition: SSG involves generating the HTML for your pages at build time, meaning the pages are pre-rendered as static HTML files.
* Use Case: Ideal for content that doesn't change often, such as blogs, documentation sites, and marketing pages.

### Benefits:

1. Fast performance: Since the content is pre-rendered, it can be served quickly from a CDN.
2. Lower server load: No need to generate content on-the-fly.
3. Improved SEO: Search engines can easily index the static content.

<a id="ssr"></a>
## What is SSR?
* Definition: SSR involves generating the HTML for your pages on-the-fly for each request. This is done on the server before sending the content to the client's browser.
* Use Case: Suitable for dynamic content that changes frequently, such as user dashboards, e-commerce sites, and personalized content.

### Benefits:
1. Fresh content: Always serves the latest content, as it's generated per request.
2. SEO friendly: Since the content is rendered on the server, search engines can index it.
3. Reduced client-side workload: Less JavaScript is needed on the client side compared to client-side rendering.

<a id="hybrid-mode"></a>
## What is Hybrid mode?
* Definition: Hybrid rendering combines both SSG and SSR within the same project. You can choose which pages or parts of your site are statically generated and which are server-rendered.
* Use Case: Useful for websites that have both static and dynamic content. For example, a blog with static posts but a dynamic user profile page.

###Benefits:

1. Flexibility: Allows you to optimize each part of your site according to its needs.
2. Performance: Static pages can be served quickly while dynamic pages provide up-to-date content.
3. SEO and user experience: Balances the benefits of both SSG and SSR, ensuring both good SEO and a dynamic user experience where needed.

<a id="render-mode"></a>
## Enabling SSG, SSR and Hybrid(SSG + SSR) mode
* Updating astro.config.mjs file to enable SSG(default), SSR and Hybrid. You need to specify the SSR adapter you want to use in case of SSR and Hybrid.
* The primary purpose of SSR adapters is to bridge the gap between Astro and the target server environment, allowing developers to deploy their SSR-capable Astro applications to platforms like Vercel, Netlify, Node.js servers, and others.

```js
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
  output: 'server', // server - enable SSR, hybrid - enable both SSR and SSG, static - SSG(default)
  adapter: vercel(),
});
```

<a id="ssg-ssr-single"></a>
## SSG and SSR on single page
* If the mode is static or hybrid, add 1 prerender variable with false value will make the page opt out of the pre rendering mode and generates the html on server side.
```js
---
export const prerender = false;
---

<html>
  <body>
    <h1>Dynamic Page</h1>
    <p>This page is not statically generated.</p>
  </body>
</html>
```
* If the mode is server, add 1 prerender variable with true value will make the page opt out of the ssr mode and generates the html at build time just like ssg.

```js
---
export const prerender = true;
import Layout from "../layouts/Layout.astro";
import Bears from "../components/Bears";
import CardComponent from "../components/Card";
---

<Layout title="Welcome to Astro.">
  <div class="py-10">
    <h1 class="text-center text-3xl mb-6">Home page</h1>
    <Bears client:load />
    <CardComponent client:load />
  </div>
</Layout>

```

<a id="data-fetching"></a>
## Data Fetching
### SSG
* In SSG, we use a method called getStaticPaths to generates the pages for a possible route at build time, routes other than these will show 404 page.
```js
---
export const prerender = true;
import Layout from "../../layouts/Layout.astro";
import { getCollection, type CollectionEntry } from "astro:content";

export const getStaticPaths = async () => {
  const blogs = await getCollection("blog");
  const paths = blogs.map((blog) => {
    return {
      params: {
        blogId: blog.slug,
      },
      props: {
        blog,
      },
    };
  });
  return paths;
};

type Props = {
  blog: CollectionEntry<"blog">;
};

const { blog } = Astro.props;
const { Content } = await blog.render();
---

<Layout title={blog?.data.title}>
  <div
    class="bg-slate-900 text-slate-100 grid place-items-center min-h-screen pt-16"
  >
    <h1 class="text-3xl mb-4">{blog?.data.title}</h1>
    <div class="px-10 prose lg:prose-xl text-slate-100">
      <Content />
    </div>
  </div>
</Layout>
```
* In this example, we are fetching some blogs build in markdown with getCollectionMethod, it is a method to fetch the markdown blogs created with createCollection method.
* Then we are mapping over the blogs array and returning params value, which will be the routes that are going to generate at build time and second is the props which has the individual blog data. At the end, we are returning the path variable itself.
* CollectionEntry type binds the blog data with the schema we have created for our collection, in this case, it is "blog".
* Finally, we are destructuring our blog using Astro.props and from blog, we are destructuring the Content from the blog.render() method, which helps in rendering the markdown content in astro file, and it is used as a component like this `<Content />`

### SSR
* In SSR,we can do the data fetching directly and could use try catch block to handle the exceptions and errors.
```js
---
import Layout from "../../layouts/Layout.astro";
import { Image } from "astro:assets";
import type Blogs from "../../interfaces/blogs";
import fetchApi from "../../lib/strapi";

const { blogId } = Astro.params;

let article: Blogs;

try {
  article = await fetchApi<Blogs>({
    endpoint: `blogs`,
    wrappedByKey: "data",
    wrappedByList: true,
    query: {
      populate: "*",
      "filters[slug][$eq]": blogId,
    },
  });
} catch (error) {
  console.log("Error", error);

  return Astro.redirect("/404");
}
if (!article) {
  return Astro.redirect("/404");
}
---

<Layout
  title={article?.attributes.meta.title}
  description={article?.attributes.meta.description}
>
  <section class="min-h-screen bg-slate-900 text-slate-100">
    <div class="grid justify-center pt-20 px-10">
      <div class="prose prose--md prose-invert">
        <Image
          src={`${article?.attributes.image.data.attributes.url}`}
          alt={article?.attributes.image.data.attributes.alternativeText}
          inferSize
          loading="lazy"
          class="object-cover max-h-[400px]"
        />
        <h1 class="text-3xl mb-4 text-center">{article?.attributes.title}</h1>
        <p class="mb-4 text-base">{article?.attributes.body}</p>
      </div>
    </div>
  </section>
</Layout>
```
* This is an example of fetching blog data from strapi, which is a headless CMS.
* Firstly, we are going to get the params using Astro.params as we are going to use the page slug to find the individual blog.
* Then using a custom fetchApi method, get the blogs data and stored it in an article variable.
* If the article is not there, It will redirect to 404 page.
* Finally we have mapped our data to the UI.

That's it for this post, in part 3, we will be covering Astro api references

You can contact me on -

Instagram - https://www.instagram.com/supremacism__shubh/
LinkedIn - https://www.linkedin.com/in/shubham-tiwari-b7544b193/
Email - shubhmtiwri00@gmail.com

You can help me with some donation at the link below Thank you👇👇
https://www.buymeacoffee.com/waaduheck

Also check these posts as well

{% link https://dev.to/shubhamtiwari909/button-component-with-cva-and-tailwind-1fn8 %}
{% link https://dev.to/shubhamtiwari909/microfrontend-react-solid-vue-333b %}
{% link https://dev.to/shubhamtiwari909/codium-ai-assistant-for-devs-57of %}
{% link https://dev.to/shubhamtiwari909/zustand-a-beginners-guids-fh7 %}