I’m building a static site in Next.js. As static sites produce pages with the .html extension, I’m using the as attribute on my Link elements, which allow my pages to be reloaded.
I have now introduced the use of query strings to my URL’s so that, when the pages are reloaded, they remember what content to display, by use of the getInitialProps() method.
So far, so good, BUT ONLY DURING DEVELOPMENT.
The problem I face is, when the site is exported out as the static version, Next.js fails to call the getInitialProps() method, hence, when the browser is refreshed, my pages no longer know what to display.
Can anybody help with any of the following:
Is there another way to allow static pages to be refreshed, without the use of the .html extension?
Is there a way to ensure that the getInitialProps() method is called when exporting a static site and when reloading a page?
Is there another way in which I can retrieve the query string from the browser URL, as Next.js doesn’t seem to have the ability to access even the top level window object?
getInitialProps is only available on server-side rendered apps. It runs during development because Next doesn't know if you want your pages to be static or SSR. But when you run next build && next export, they become static and getInitialProps no longer runs. I believe this is also why next switched to getServerSideProps and getStaticProps instead of getInitialProps (for everything but the _app.js page)
In response to your list of questions:
Next exports so that you don't have to use/show the HTML extension, but that also depends on your hosting setup. Exporting a static site exports .html files, but it's up to your hosting configuration to determine whether or not those are shown.
See above and no - there is no way to have getInitialProps run on a fully static, exported site. You'd need to switch to a server-side rendered site if you have to use getInitialProps.
Your static site can retrieve the query string, but it's not going to have it at build time. Instead, you'd need to check for it (usually in React.useEffect) when the window object is available. On a static site, that's not at buildtime but only at runtime. Check out this answer on how to get the query string in javascript - you can use this in your useEffect.
Related
So I get the difference between next build && next export and next build && next start from here.
In short, next build && next export generates a fully static app which does not require a server to host, whereas next build && next start starts a server which renders and serves content.
My question is then, how is next build && next export different from just using React? Seems both approaches generate static files (html, css, js). If I want to optimize SEO, is next export better than using react?
There are many ways to create a React web app. And there are many types of them as well.
Client-Side Rendering
Noticeable toolchain: Create React App
Everything is done on the client side. You send a blank HTML file and various JS bundles to the browser. And the browser parses the bundle and renders contents on the HTML and presents it to the users.
It takes less effort to set up so it best suits small projects.
This is properly what you were referring to when you said: "just using React".
Server-Side Rendering
Noticeable Toolchain: Next.js
Most of the works is done on the server-side. When a user requests to view a page, the server generates the need HTML file dynamically with static contents in it. Then, it sends the file to the user together with JS bundles for interactive content. The browser then attaches those JS to the HTML and present it to the users.
It requires far more effort to set up compared to Create React App. It best suits mid to large projects.
Static Site Generator (Prerender)
Noticeable Toolchain: Gatsby
Similar to Next.js, but instead of generating the HTML dynamically. It generates ALL OF THEM at build time and just sends it to users upon being requested.
This property has the best performance overall. But it can become a nightmare when the site is growing bigger and have hundreds of pages. Building a large, static Gatsby site takes ages to complete.
p.s. Next.js is also capable of generating static sites, but why don't you pick the right tool which is designed and optimized for generating a static site in the first place?
Answering my own question after I tried the following:
Launch a create-next-app then do next build && next export
Launch a create-react-app then do yarn build
Compare out/index.html in the next app and build/index.html in the react app
I found out that out/index.html actually contains all the static contents, whereas build/index.html contains nothing but <script> elements in its <body>. Everything including paragraphs (<p> elements) are later generated (or hydrated) when opened in the browser.
So in conclusion, even though both Next and React can be used to generate static site (SSG), Next is still better for SEO purposes since the contents are already in the html file.
Next.js can be used as static side builder (in the case you are referencing) which means it will generate all of you html at the time of build and along provide some performance features.
React(if not used on server) will always just have 1 HTML page which then loads of all your App(or chunks if you are code splitting) when the client requests it.
If you are not familiar about the concept read more on Static side building.
For SEO purposes using Next.js with either static or server side rendering would be the best approach since everything is prebuilt and easily accessible by robots(Although Google bot should already read javascript apps as well).
I'm creating a real estate website.
I'm using Next.Js as framework for react.
To optimise my system, I want to create a system such that:-
On first request of main page from client side, server should serve some basic data and redux, then using redux, I want to call api, recieve data and further render some same kind components on client side. Then I want to attach a functionality to the components such that, on click it checks the requested page on a custom static folder, if it is available then serve it statically to client, if not then rendered the page on server by taking data stored in redux and copy the static version of page to custom static folder and serve to client. I also want to make a function which continuosly checks on the static files expiry and update.
Problem is I'm unable to achieve the functionality of storing chunks of page statically on a custom folder, and creating check function for it on Next.Js
-------->>>>>>>>>>>>
Attaching rough image of system.
Rough Image of system
-------->>>>>>>>>>>>>
Any help or idea will be appreciated.
I've been using NextJS for a while, but don't fully get how its SSR process really works.
I've put a console.log inside some components return method, and I see that those are executed on the client side. Shouldn't these be displayed on the server's console instead because SSR is being used?
Also, when I try to console.log the window object, NextJS throws an error saying that window is not defined. That left me more confused, because according to my previous test, console.log is running on the client side, but according to this error, it is running on the server.
If you've set up React components to render on the server (which you should for non static sites), when code executes on the server in NodeJS, there is no window object. That only exists in the browser. You need to account for that in SSR components.
There are features of Next to control when components are available to the client or server only, like dynamic imports.
In the end, on the server, Next is mostly doing renderToString, and serving the HTML from the server, no different than any other webserver serving HTML.
Once in the client, React "hydrates" the rendered DOM, as in it re-runs React over the HTML created by the server. It doesn't change the DOM, but it does add things like interactivity, click handlers, etc, that you've defined for your app.
Server side nextjs generates .js in your .next directory if it is GetServerSideProps. If it is ISR (GetStaticProps + revalidate), then it generates .html, .json, and .js files in the .next directory for that page (or those pages if dynamic). If using GetStaticProps sans revalidate, it generates .html and .json in the .next directory. If using no server side rendering method (e.g., GetStaticProps or GetServerSideProps) then it only generates .html at build time (automatic static optimization).
There is more to it, but this is what I've noticed from inspecting the contents of the output pages in the .next directory
I have a MERN app in which I have integrated NextJS. First time with NextJS so bear with me. I have initially used SSR everywhere (getServerSideProps).
Key points:
I have over 150,000 pages with static content that it's never going to change.
Every week I add around +100 new pages.
I guess the ideal situation here would be using getStaticProps and getStaticPaths and, after an initial build of those 150k pages, just build the new added pages every week and keep what I already have built as it is since it's never going to change.
How can I achieve this? Should I use revalidate here? I have been reading about it in the documentation but I don't completely understand it.
That can be achieved with getStaticProps/getStaticPaths. You'll have to use fallback: true or fallback: 'blocking' in getStaticPaths.
With fallback: true the paths not generated at build time will serve a fallback page on the first request while Next.js statically generates the page. When this is done the page will be swapped from the fallback page to the actual full page.
With fallback: 'blocking', the paths not generated at build time will wait for the HTML to be generated by Next.js, then serve the page once that's done. Unlike fallback: true, since there's no fallback the rendering gets blocked until the page is generated, similar to what happens during server-side rendering.
In both cases the page gets added to the list of pre-rendered pages. Subsequent requests to the same path will serve the pre-generated page.
Neither of these options is supported by next export, in case you depend on that.
Note that revalidate is used in getStaticProps for Incremental Static Regeneration - in cases where you'd want to update existing, generated pages. Since you mentioned generated pages will never change, then there's no need to use revalidate.
I'm reading Next.js fetching data part of the documentation and one question came to my mind.
Next.js can fetch data with getStaticProps, getStaticPaths, getInitialProps and getServerSideProps, right?
But some happens on Build-time as I quote:
getStaticProps (Static Generation): Fetch data at build-time
When is this Build-time happening?
Is it when we run npm run build? (To build the production build)
Or when the user accesses our Next.js app? (On each request)
Build time happens when you're building the app for production (next build). Runtime happens when the app is running in production (next start).
getInitialProps (gIP) runs on both the client and the server during runtime for every page request. Most common use case is retrieving some sort of shared data (like a session that lets the client and server know if a user is navigating to a specific page) before the requested page loads. This always runs before getServerSideProps. While its usage is technically discouraged, sometimes it absolutely necessary to do some logic on both the client and server.
getServerSideProps (gSSP) only runs on the server during runtime for every page request. Most common use case would be to retrieve up-to-date, page-specific data (like a product's pricing and displaying how much of it is in stock) from a database before a page loads. This is important when you want a page to be search engine optimized (SEO), where the search engine indexes the most up-to-date site data (we wouldn't want our product to show "In stock - 100 units," when it's actually a discontinued product!).
getStaticProps (gSProps) only runs during build-time (sort of). It's great for sites whose data and pages don't update that often. The advantage of this approach is the page is statically generated, so if a user requests the page, they'll download an optimized page where the dynamic data is already baked into it. Most common use case would be a blog or some sort of large shopping catalog of products that may not change that often.
getStaticPaths (gSPaths) only runs during build-time (sort of). It's great for pre-rendering similar paths (like a /blog/:id) that require dynamic data to be used at build-time. When used in conjunction with gSProps, it generates the dynamic pages from a database/flat file/some sort of data structure, which Next can then statically serve. An example use case would be a blog that has many blog posts which share the same page layout and similar page URL structure, but require the content to be dynamically baked into the page when the app is being built.
Why are gSProps and gSPaths sort of ran during build-time? Well, Next introduced revalidate with fallback options that allows these two Nextjs functions to be ran during runtime after a timeout in seconds. This is useful if you want your page to be statically regenerated, but it should only be regenerated every n amount of seconds. The upside is that the page doesn't need to request dynamic data when navigated to, but the downside is that the page may initially show stale data. A page won't be regenerated until a user visits it (to trigger the revalidation), and then the same user (or another user) visits the same page to see the most up-to-date version of it. This has the unavoidable consequence of User A seeing stale data while user B sees accurate data. For some apps, this is no big deal, for others it's unacceptable(†).
† If you're using a version of Next v12.2.0+, you can use On-demand Revalidation to mitigate a stale static page from being shown to users if/when its data has been updated.
And lastly, there's client-side rendering (CSR) which are assets requested at run-time on the client (the browser) which aren't vital for SEO or can't be run on the server-side (like attaching an Event Listener to the document; this can't be done because server's don't have DOMs). Most common use case would be a user-specific dashboard page that is only relevant to that user and therefore doesn't need to be indexed by a search engine or some sort of JavaScript that manipulates the DOM and therefore can't be run on the server.
Other things of note: gIP and gSSP are render blocking. Meaning, the page won't load until their code resolves/returns props. This has the unavoidable consequence of showing a blank page before the page loads. This also means slower page response times where: Page is requested, gIP/gSSP runs code that blocks page from loading, gIP/gSSP code resolves, assets are then downloaded, page begins to load the JavaScript on the client while the HTML is being loaded into the DOM, JavaScript is done running, page is then rehydrated and then it becomes interactive. In summation, this results in a slower TTI.