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.
Related
In the Gatsby documentation it says that the default build mode is SSG:
SSG is the default rendering mode in Gatsby. While the name has the word “static” in it, it doesn’t at all mean boring or lifeless. It simply means the entire site is pre-rendered into HTML, CSS, and JavaScript at build time, which then get served as static assets to the browser.
But it seems that when you build it, the compontents and libraries have to be SSR friendly, and you need to use workarounds when using client-only libraries.
From the documentation it seems like there are three options for rendering:
SSG - Static Site Generation
DSG - Deferred Static Generation
SSR - Server Side Rendering
What if I am not interested in using SSR and just want to serve the static SSG version of a Gatsby site. Is there an option to build a purely static site, client-side site like Vite or Create React App and not have it complain about server-side rendering errors like this?
failed Building static HTML for pages - 1.639s
ERROR #95312 HTML.COMPILATION
"window" is not available during server-side rendering. Enable "DEV_SSR" to debug this during "gatsby develop".
Building a static site and doing server-side rendering are very nearly the same thing. The primary difference is when it is done (at build time instead of on demand).
The code to generate the HTML to be delivered to the client still has to be executed, and it still has to run in an environment where window is not available.
So no. You still need to do the workaround so that the code which can only run on the client is only run on the client.
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.
I was tasked with implementing an i18n for the company website. At present we are using Netlify with #netlify/plugin-nextjs, and I hit the wall when submitting a PR when I got an error saying that
Error: i18n support is not compatible with next export.
I have read several topics here and a few articles and I found one smart workaround https://dev.to/adrai/static-html-export-with-i18n-compatibility-in-nextjs-8cd
And other suggestions were to move to Vercel. Is this the thing I should consider? We do not use getServerSIdeProps anywhere, the website is fully SSG so what is the benefit of the next export over the SSG approach? Is SEO better with the next export?
Next-translate seems to be building pages in development on every page change so perhaps it is possible to build a separate page for every translation without the need for such a burden?
I think moving to Vercel would be doable but should I do that? Would this allow me to deploy the translation while saving the SEO that next export gives? Or should I go with the custom solution above?
Thanks
With next export you can generate static HTML pages (SSG) that can be served easily from any server of your choice, but this way you won't be able to use all of the features listed on this page:
https://nextjs.org/docs/advanced-features/static-html-export#unsupported-features
And other suggestions were to move to Vercel. Is this the thing I should consider? We do not use getServerSIdeProps anywhere, the website is fully SSG so what is the benefit of the next export over the SSG approach? Is SEO better with the next export?
When deploying to Vercel or Netlify you still have all the SEO benefits of statically generated pages (Either through Automatic Static Optimization or manual usage of getStaticProps) and full access to all Next features listed in the link above (including i18n). Hence, if you have static pages, next-export has no SEO benefits over deploying on Vercel/Netlify, as in both cases you will serve pre-rendered pages to users, but next-export just gives you better flexibility when it comes to deployment.
Next-translate seems to be building pages in development on every page change so perhaps it is possible to build a separate page for every translation without the need for such a burden?
As you mentioned, that's exactly what the example you linked above achieves: It pre-renders every page for every locale you have, which is also exactly what you'd get when deploying a Next app with a i18n package like next-translate or next-i18next on Vercel or Netlify.
I think moving to Vercel would be doable but should I do that? Would this allow me to deploy the translation while saving the SEO that next export gives? Or should I go with the custom solution above?
If you can, you should deploy on Vercel or Netlify to save a lot of time and get all the features like i18n out of the box. But, the example you provided above also makes i18n work with next-export so if you have a plain, static website that requires no other custom Next features like routing, middleware or Image optimization, it will surely work too if you don't want to deploy on Vercel/Netlify.
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!
I am using react-markdown (escaped) to load markdown from a JSON file.
I utilize a static site delivers on CloudFront to cut cost and remove the need of operations costs on servers.
Currently all posts get compiled into a posts.json file that get read by react-markdown in a react-based static site.
Beyond maybe chunking this to into multiple files to prevent a huge json file needing downloading, is there any kind of issue from this method?
Is this a bad idea?
EDIT; react-snap is being used to "prebuild" or whatever the term may be. I however am unsure if this is doing anything in regards the json that gets loaded on the page, for example if its getting output in build as plain HTML. Will have to confirm.
Your approach does take on some overhead and latency since there are several dependencies that must be satisfied before your content reaches the user.
The browser must load and parse the script
The script must fetch the JSON from the server
react-markdown has to parse the markdown strings
React has to render the components
None of these are likely to be particularly slow, but we can't do any of it concurrently, and it adds up.
But since your markdown is static and doesn't require re-rendering, you can get some efficiency from moving the render to the server, possibly even to the build step itself. If the markdown string is compiled to HTML via react-markdown at build time, then the client receives the markup that much more quickly.
Frameworks like Next.js do this by design - it allows you to specify async functions that fetch the data needed to render the page at build time. The data can of course be anything that is representable as React props, including JSON.
It may be neither your reponsibility nor your preference to change your project to use a new framework, but I hope the general ideas are useful on their own.
I think server-side rendering will help in your case as most of the resources need to be compiled on the client machine. you can also use a chrome puppeteer that is headless chrome that can be used to transpile resources on the server and then send it client to reduce the latency. Refer https://developers.google.com/web/tools/puppeteer
It looks like you have everything you need to use a static site generator like Gatsby. A static site generator will allow you to keep your big JSON file which will only be read on build time. A static site generator like GatsBy will help you generate stand alone static HTML documents for each of your blog post.
You also can host your static site for free on any the popular CDNs free tiers like Nelify and Surge