Static Site Generation (SSG) vs. Server-Side Rendering vs. Client-Side Rendering - javascript

I am baffled by the lack of concrete information about how Client-Side Rendering (CSR), Server-Side Rendering (SSR), and Static Site Generation (SSG) actually work.
There are tons of articles loosely explaining the concepts, but I have not found a single source that goes in-depth and explains exactly what HTML, CSS and JS are created on the server vs on the client, in the three concepts.
From the Next.js docs, we can read that:
Static Rendering
With Static Rendering, both Server and Client Components can be prerendered on the server at build time.
Client Components have their HTML and JSON prerendered and cached on the server. The cached result is then sent to the client for hydration.
Server Components are rendered on the server by React, and their payload is used to generate HTML. The same rendered payload is also used to hydrate the components on the client, resulting in no JavaScript needed on the client.
Note: Static Rendering is equivalent to Static Site Generation (SSG) and Incremental Static Regeneration (ISR).
And:
Dynamic Rendering
With Dynamic Rendering, both Server and Client Components are rendered on the server at request time.
Note: This is equivalent to Server-Side Rendering(getServerSideProps()).
Fine, so Static Rendering equals Static Site Generation (SSG), meaning that some html+css is created build-time. Exactly what html is created build-time depends on whether you use Client Components or Server Components.
I inspected the built public folder of a built Gatsby project and noticed that none of the React components were actually turned into html (regardless of whether they depended on user interaction). Gatsby had created an html file for each page, but the <body> of each of those was still React components defined in JS, expecting to be turned into html by React on the client, run-time. This breaks with my understanding of the second bullet from the Next.js docs, which states that the html is "prerendered".
Questions
By the above docs, could we say that Static Site Generation (SSG) actually requires both Server-Side Rendering (SSR) and Client-Side Rendering (CSR)?
If so, does that not conflict with the Dynamic Rendering definition above, which states that Dynamic Rendering is equivalent to Server-Side Rendering?
Finally, exactly what html+css+js is created upon Static Rendering with Client Components?

Related

What's the difference between SSR and fallback = true for dynamic paths in NextJS

So I'm finding it difficult to see the benefits of doing SSR for dynamic paths in NextJs when I can just just pre-render a few static paths, and use fallback=true to cover my bases on most pages.
Say I have an eCommerce site with 1 million product detail pages, but I only want to pre-render featured products on the home page(most clicked). If I set fallback to true in getStaticPaths, then the getStaticProps function runs every time a non featured product page is requested.
So what's the advantage of using SSR when I can just have a fallback that queries the database every time a non pre-rendered page is called?
Note: I saw a similar question on Stack Overflow, and the answer was that web-crawlers see only the fallback state of your react Component that you set for non pre-rendered pages (so the source code would only read <p>Loading...</p> or something like that, vs the SSR page which would load all your data for the product directly as the source code. But this doesn't seem to be true in my app.
Thanks for any help.
TLDR: [In NextJs..] Why can't I just use SSG for dynamic paths, with fallback=true in getStaticPaths, instead of SSR?
THANKS ALL
I tried reading the NextJs docs and couldn't find an explanation for the cons of using fallback=true in getStaticPaths
From next.js docs:
By default, Next.js pre-renders every page. This means that Next.js
generates HTML for each page in advance, instead of having it all done
by client-side JavaScript.
Two Forms of Pre-rendering
Next.js has two forms of pre-rendering: Static Generation and
Server-side Rendering. The difference is in when it generates the HTML
for a page.
Static Generation is the pre-rendering method that generates the HTML
at build time. The pre-rendered HTML is then reused on each request.
Server-side Rendering is the pre-rendering method that generates the
HTML on each request.
I put those definitions to clarify the terms in next.js. I believe your question is regarding fallback:true versus generating HTML on each request (or building page runtime vs build time). I think this note you shared is not correct
Note: I saw a similar question on Stack Overflow, and the answer was
that web-crawlers see only the fallback state of your react Component
that you set for non pre-rendered pages (so the source code would only
read Loading... or something like that, vs the SSR page which
would load all your data for the product directly as the source code.
But this doesn't seem to be true in my app.
In each case the populated page is seen by the crawlers.
Using getStaticPath in your e-commerce example is the usage of caching. those pages for popular products are already built and inside next build folder you can see them if you build your app locally. But in large applications, those static assets are stored in CDN, and whenever the server gets a request response will be in no time. so customer will have a better user experience so which will eventually affect the profit of the ecommerce site.
I think the clearest example would be thinking about a blogging website like Medium. The most popular blogs will be pre-generated since the content of the blogs do not change that often. Medium will use CDN's from different parts of the world, so user all around the world will have faster access to blogs.
Hitting databases is a very expensive operation. The more load you have on the database harder to maintain the availability, scalability, and reliability of your application.
Also, you might have a better internet connection, you use high end clients so you might access any data faster but you have to think about all people around the world who try to access data with low-quality clients or internet connections.

What is SSG (Nuxt.js, Gatsby) doing?

I have heard SSG generates static sites.
Then I thought SSG generates pure HTML that didn't include React, but I think it may not be true now.
I think:
SSG generates a usual React App and rendered HTMLs for initialization.
As it is a usual React App, if I click a button and trigger a side effect, client-side rendering will be triggered and the page will be updated.
When routing using router is triggered, next page's js file and data obtained when build will be downloaded, and then client-side rendering will be triggered.
The next page's rendered HTML for initialization isn't used here.
Is it true?
SSG (Static Site Generators) like Gatsby and Next, what they do is to create an output HTML based on a React environment code. This doesn't mean that the site is "static" in terms of interaction. This means that the page you are requesting is already created so you are avoiding response and compilation time in the server.
Summarizing, given a "traditional"/"old-fashioned" PHP site. When you request the homepage, for example, your requests go to the server, the server transpiles the PHP into HTML (what the browser can parse and print) and then you get the page. That processing time is omitted in Gatsby/Next because the HTML is already created.
When you build your site in Gatsby/Next, the data is being retrieved from the sources (using GraphQL from markdowns, CMSs, APIs, JSONs, etc) and creates the output (that's why there's a /public folder generated). All your JavaScript and React is bundled into the output HTML so your website will be "dynamic" in terms of user interactivity, React is part of the ecosystem so your side-effects (triggered by useEffect hook for example) or your rehydration process (useState hook for example) will be part of your site.
Explained as:
When you navigate into another page, you are requesting a page that is already built and generated, that's why is so blazingly fast.
I've answered this question few weeks ago on the Nuxt discussions: https://github.com/nuxt/nuxt.js/discussions/9493#discussioncomment-948643
Let's say that SSG bring several things:
SEO
speed
ecology
[probably some other things]
There are several ways of doing SSG and all of them have their pro/cons and their use-cases. For the most part, and if you're using Nuxt.js, you will probably go the target: static, ssr: true route.
This will:
generate fully static pages during build time and you'll be able to host it on Netlify, Vercel or alike
hydrate the static content with some JS after you have fetched the static files
have the Vue behavior afterwards, as a classic SPA (hence managing the routing without further server calls)
This behavior is called Isomorphic or Universal, more info in the linked discussion.
Gatsby and Next.js do work in somewhat similar ways. There are some minor differences but the general is globally the same across those 3 AFAIK.
SvelteKit and Astro handle this a bit differently. May be interesting to give it a look!

How can I implement Webpack for a EJS Reactjs Express MongoDb project?

The project is using EJS, Express/NodeJs, MongoDB and I have added ReactJs to it.
Now I want to implement Webpack for bundling EJS and ReactJs files together.
The project eventually has to be converted to ReactJs but for now we need to Bundle EJS as well.
Is there a way I can do that? I need help.
EJS can run client-side and React can run server-side but a typical Express/EJS set up runs the EJS server side and delivers plain HTML to the client, while a typical React setup runs the React code client-side (and might add server-side rendering as a bonus).
Assuming you aren't doing anything highly atypical (in which case you really need to explain your setup in much more detail) then the short answer is: No.
You need your EJS to run server-side, so putting it in a bundle and sending it to the client is pointless.
If you want to transition from a classical server-side rendering of HTML to a React system then a typical way to do that is on a page-by-page basis. \
You can either serve up a basic static bootstrap HTML document for the pages you replace, or get creative with a SSR system for those pages (and either do some clever mixing of routing rules or just put a reverse proxy that diverts different URLs to a Next.js server or an Express server depending on if they have migrated or not).
Another approach is is to write a series of small React components that replace individual components of pages (e.g. a navbar application) and have the entry point include multiple ReactDOM.render calls for each component.
That latter approach is less suited to involving SSR at all though.
Either way: You wouldn't be sending the server-side EJS code to the client so it wouldn't be bundled with the React code.

The technical problem "ejs" trying to solve

Because all Angular & React does similar type of templating behind the scene. So why use ejs..? Is that for project that do not use Angular/React and alike.?
React and Angular are tools initially built to create Client Side applications or Single Page Applications. This means that the client receives a single HTML file and one or more JS files that contain the app's code. All of the HTML that you then see generated in the website is actually built in the client (AKA the user's browser).
We now see both React and Angular being used for aplications that have their HTML built in the backend, either in run time (Server Side Rendering) or on build time (technically also Server Side Rendering but usually referred to as Static Site Generation, see Gatsby for an example).
EJS is a simpler tool, it basically just gets an HTML file (with the .ejs termination) and some placeholders {{data}}, and fills these with anything that we might want to use. What basically happens when you generate an HTML page to send to the client when using EJS is something along these lines:
index.ejs -> (In Node) Pass object with data values for placeholders -> Replace placeholders with actual values -> Output finished HTML file with value instead of placeholders
Notice that there is no special logic, state or any other complexity that you may find in a React or Angular application. It is a templating engine, it just does what was described in my snippet.

Next.js static server side rendering and Gatsby.js

I want to build a website with Next.js and am trying to better understand their Automatic Static Optimization, and the different ways that you can use it.
So to start with, there's Gatsby.js which is a static site generator. When you run Gatsby's build command you get a /public folder which is completely static and can be deployed without any need for some kind of a back-end. If I understand correctly, this means that the entire static folder is sent to the client on the first request, and from then on everything, including routing, happens client-side.
With Next.js on the other hand, you have static generation, which means that all pages are pre-rendered on the server at build time (like Gatsby), but the application still depends on a back-end (either a full-blown server or a serverless function) for routing. I.e, the pages are pre-rendered but, unlike Gatsby, they're sent to the client per request, i.e on navigation. (I found this answer which says there's only the initial request with Next, but then, what's the difference from Gatsby?)
What I find confusing in all this, are things like Next's docs for Static HTML Export. They start by stating
next export allows you to export your app to static HTML, which can be run standalone without the need of a Node.js server.
So, sounds like this option gives us the ability to use Next just like Gatsby, i.e as a completely static folder.
But then they go on remarking that:
If your pages don't have getInitialProps you may not need next export at all; next build is already enough thanks to Automatic Static Optimization.
But Automatic Static Optimization refers only to server side static pre-rendering, and next build does not produce a Gatsby like static folder that can be deployed as a standalone.
So what am I missing here? What's the difference between Gatsby.js and Next.js? Does Gatsby can do something Next can't? Can I build a completely static site with Next without using the export command?
Most importantly, can I build and deploy a Next.js application with some pages completely static (like Gatsby), some pages only pre-rendered (getStaticProps and getStaticPaths), and some pages rendered server-side (getServerSideProps)?
Thanks a lot in advance!
The first request is for <url>/index.html so no the entire public is not sent to the client.
Gatsby optimises the loading process to ensure critical resources (HTML, CSS, JS) are loaded first, ensuring best possible user experience. From there it will load remaining resources required to render the full page and will also prefetch linked pages from the main page. Of course if you have requested a route to a different page, then the client would fetch the HTML initially for that page, but the process followed will be similar.
Gatsby is still better at this than Next.js (SSG is a very new feature for Next and this the core of what Gatsby does) - see https://dev.to/notsidney/gatsby-won-against-next-js-in-this-head-to-head-37ka.
In answer to your questions, yes you can do full SSG, partial SSR/SSG and full SSR with Next. You need to do next export if you want full SSG, otherwise for the other modes you are in standard Next territory and Next will take care of both SSG/SSR given you have a traditional web server running that can serve both static content and perform dynamic SSR.

Categories