# 1. What is getStaticProps && getStaticPaths
# getStaticProps
- Purpose: Primarily used for fetching static data at build time, which is then pre-rendered into HTML.
- Execution Timing: By default, getStaticProps runs only once at build time, with subsequent requests serving the data fetched during this build.
- Application Scenarios:
- SSG: In static site generation, getStaticProps provides necessary data for each page, optimizing SEO and load performance.
- ISR: By specifying a revalidate option, getStaticProps supports incremental static regeneration, allowing pages to be updated periodically after deployment without rebuilding the entire site.
# getStaticPaths
- Purpose: Used for dynamic route pages, guiding Next.js on how to generate static pages for dynamic routes at build time.
- Execution Timing: Runs at build time to pre-generate pages based on the returned paths.
- Application Scenarios:
- Dynamic Routes: For pages with dynamic routes (e.g., pages/posts/[id].js), getStaticPaths determines which ids should be pre-rendered into static pages.
- Integration with getStaticProps: Once getStaticPaths specifies certain paths, each path is then pre-rendered using getStaticProps to fetch the corresponding data.
# :light_bulb_on: Considerations
- Difference from getServerSideProps: getStaticProps fetches data at build time, suitable for data that changes infrequently; getServerSideProps, on the other hand, fetches data on every request, suitable for scenarios requiring real-time data.
- Data Updates: To update data on pages pre-rendered with getStaticProps, you can trigger a site rebuild or utilize ISR for updates.
- Page-Level Only: Both getStaticProps and getStaticPaths can only be used in page components, not within child components.
# 2. Deep understanding getStaticProps
// pages/products.tsx
import React from "react";
interface Product {
id: number;
name: string;
description: string;
price: number;
}
interface ProductsPageProps {
products: Product[];
}
const ProductsPage: React.FC<ProductsPageProps> = ({ products }) => {
return (
<div>
<header>
<h1>Our Products</h1>
</header>
<main>
<ul>
{products.map((product) => (
<li key={product.id}>
<h2>{product.name}</h2>
<p>{product.description}</p>
<strong>${product.price}</strong>
</li>
))}
</ul>
</main>
</div>
);
};
export const getStaticProps = async () => {
// Simulating fetching data from an external API
const res = await fetch("<https://fakestoreapi.com/products>");
const products: Product[] = await res.json();
console.log("Fetched products at build time with getStaticProps");
return {
props: {
products,
},
};
};
export default ProductsPage;
- **Page Component (**ProductsPage): This component is responsible for rendering the products page. It receives an array of products as a prop, iterating over the array to display each product's name, description, and price.
- Data Fetching with getStaticProps: The getStaticProps function fetches data from an external API, in this case, a list of products. This function runs at build time, pre-fetching the data needed to render the products page.
- Props Structure: The fetched data is structured under the props key and passed to the ProductsPage component. This approach ensures that the component has access to the product data when it's rendered.
- Static Generation: By utilizing getStaticProps, Next.js pre-renders the products page with the fetched data at build time. The resulting static page includes all product information, ready to be served immediately to users, enhancing the page's load time and SEO.
# Benefits
- Improved Load Time: Since the data is fetched at build time and the page is pre-rendered, users experience faster page loads.
- SEO Optimization: The pre-rendered page includes all product information in the HTML, making it easily indexable by search engines.
- Build-time Data Fetching: Fetching data at build time is efficient for data that doesn't change frequently, reducing the need for real-time API calls on each request.
# Invocation Timing
During next build Execution:
- getStaticProps is called once during the build process (next build). This means that for each page, getStaticProps fetches data and generates static HTML and a corresponding JSON file. These files can then be directly deployed to a CDN.
When getStaticPaths Returns fallback as Not false:
- For dynamic route pages, getStaticProps is used alongside getStaticPaths. If getStaticPaths sets fallback to true or 'blocking', getStaticProps will be invoked to generate static pages for new path requests that were not generated at build time.
When Using revalidate:
- When the object returned by getStaticProps includes a revalidate property, Incremental Static Regeneration (ISR) is enabled. The revalidate property specifies the interval at which the page data should be updated. Within this interval, the page will not be regenerated. Once surpassed, the next page request will trigger a re-generation of the page.
# :light_bulb_on:JSON File and Data Access
At build time, Next.js generates not only static HTML files but also corresponding JSON files for pages using getStaticProps. This JSON file contains the return value of getStaticProps. It enables Next.js to quickly load data from the JSON file during client-side navigation (e.g., through next/link or next/router), instead of reloading the entire page, thus achieving fast client-side route transitions.
Example of a JSON file:
{
"pageProps": {
"content": "Hello World"
},
"__N_SSG": true
}
Here, the **N_SSG flag indicates that this is a page generated through static generation, distinct from the **N_SSP flag used for pages generated through Server-Side Rendering (SSR), to differentiate between the data fetching methods.
# Key Takeaways:
getStaticProps offers an efficient method for data fetching and page pre-rendering, particularly suited for scenarios where content updates infrequently. By leveraging static generation, incremental generation for dynamic routes, and ISR, Next.js applications can combine the high performance of static files with the flexibility of dynamic content, optimizing both user experience and SEO.
- Server-Side Execution: getStaticProps operates exclusively on the server, ensuring no part of its code ends up in the client-side JavaScript bundle.
- Direct Server-Side Code: Within getStaticProps, you can write server-side code to access the file system via the fs module, query databases, or include sensitive information like API keys, all securely without exposing any of it to the client-side browser.
- Page-Specific and Pre-rendering Only: getStaticProps is exclusive to page components and cannot be used in regular presentation components. It's designed for pre-rendering pages at build time, not for client-side data fetching.
- Return Object Structure: getStaticProps must return an object containing a props key, which itself is an object. This structure ensures the returned data can be passed as props to the page component.
- Build Time and Development Mode Execution: getStaticProps runs at build time for static generation. In development mode (npm run dev), getStaticProps executes on every request, ensuring developers have up-to-date data while working on the application.
# 3. Deep understanding `getStaticPaths
# :light_bulb_on: Using getStaticPaths
getStaticPaths is mainly used to build static pages in dynamic routes, which simply means that a dynamic route can be converted to multiple static pages by getStaticPaths.
- pages/get-static-paths/[id].tsx
function GetStaticPaths({ post }: { post: string }) {
return (
<div>
<h1>Post: {post}</h1>
</div>
);
}
export async function getStaticPaths() {
const response = await fetch("https://jsonplaceholder.typicode.com/posts");
const data = await response.json();
const paths = new Array(100).fill(null).map((_, i) => ({
params: { id: String(i + 1) },
}));
console.log("Generated paths:", paths);
return { paths, fallback: true };
}
export async function getStaticProps({ params }: { params: { id: string } }) {
console.log("Fetching data for post:", params);
return { props: { post: `Post content for ${params.id}` } };
}
export default GetStaticPaths;
Here is a simple dynamic route, with getStaticPaths we can define the matching route values for this dynamic route, matching the parameters in the dynamic route with the params parameter in paths[number]. Here are the getStaticPaths and getStaticProps related parts of the next.js steps to convert it to a static page.
- Invoke next build: Initiates the page data collection process in Next.js.
- Detect Dynamic Routes: Next.js calls getStaticPaths for pages with dynamic routes to obtain paths for static generation.
- Iterate paths: Each path from the getStaticPaths return value is matched with its corresponding dynamic route.
- Generate Static Pages: Matches lead to the static generation process for each route.
- Execute getStaticProps: The params from each path are passed to getStaticProps, which fetches data for the page.
- Create HTML and JSON: The data returned from getStaticProps is used to produce HTML and JSON files for each static page.
So the above code will generate 10 static pages [1-10].html and 10 JSON files [1-10].json in next build, the generated files can be viewed under .next/server/pages/.
# :light_bulb_on: Understanding getStaticPaths Operation:
Static Resources: The posts document, along with associated JavaScript files (e.g., _app, framework, main, and webpack runtime), are downloaded. These scripts include the code for the entire application and are essential for the page to function correctly.
JSON Data Fetching: Alongside the static resources, there are JSON files named 1.json, 2.json, 3.json, etc. These files are fetched dynamically and correspond to the data for each post.
When using getStaticPaths, Next.js statically pre-renders pages at build time based on the paths returned from this function.
Each path corresponds to a page that can be accessed by a user, and for dynamic routes (like posts), Next.js generates a JSON file for each path.
These JSON files contain the data needed to hydrate the page with content on the client side after the initial HTML has been loaded.
The presence of 1.json, 2.json, and 3.json indicates that three posts have been pre-rendered, and their data is available for the application to use when rendering the pages client-side.
When a user navigates to a specific post, the corresponding JSON file is fetched, which provides the data necessary to render the page fully with all the post details.
# :light_bulb_on: Understanding the fallback Parameter in Next.js
The fallback parameter in getStaticPaths is a crucial feature for handling dynamic routes in Next.js applications. It determines the behavior of the application when a user accesses a route that hasn't been pre-rendered into a static page. There are three possible values for fallback: false, true, and blocking, each affecting the page access differently:
# fallback: false
- This is the default behavior where only the paths specified in getStaticPaths are pre-rendered at build time.
- Accessing a non-existent page, such as /get-static-paths/11 when it's not defined in getStaticPaths, results in a 404 error page.
- Suitable for applications where the set of valid paths is known and static.
- 使用場景:
- 需要預渲染的路徑較少
- 不經常添加新頁面
# fallback: true
- The path returned by getStaticProps will be rendered to html by getStaticProps at build time.
- When a user navigates to a page that doesn't exist within the pre-rendered paths, instead of immediately presenting a 404 error, Next.js will render a fallback version of the page. This is especially relevant when the fallback key in getStaticPaths is set to true. During this time, if you want to display a loading state, you can use router.isFallback to check if the fallback is currently being displayed. Here's how you can integrate this into your component:
import { useRouter } from "next/router";
function MyComponent() {
const router = useRouter();
if (router.isFallback) {
// Render a loading state while the page is being statically generated
return <h1>Loading...</h1>;
}
// Render your page's content
}
- In the background, Next.js uses the page parameters to fetch data with getStaticProps, generates the static page and a JSON file, and then dynamically updates the page with the fetched data.
- On subsequent visits to the same path, the pre-rendered static page is served directly, mirroring the behavior of existing pages.
- This can be seen as a lazy build strategy, enabling on-demand static generation for paths not pre-rendered at build time.
# fallback: 'blocking'
- Similar to fallback: true, but with a critical difference: when accessing a non-existent page, the request waits for getStaticProps to finish fetching data and generating the static page before it is returned to the user.
- This eliminates the need for a second data request and ensures that users get a consistent, pre-rendered page on the first access, whether asynchronously (with true) or synchronously (with blocking).
Each fallback mode offers different advantages, depending on the specific needs of your application. fallback: false ensures fast performance and is suitable for known, unchanging routes. fallback: true offers flexibility and efficiency for applications with potentially infinite paths by generating pages on-demand. fallback: 'blocking' provides a seamless user experience by ensuring all users receive statically generated content, even if it means a slight delay on the first request to a non-pre-rendered path.
📌 Here there is a need to pay attention to the problem is getStaticPaths params in the parameter needs to be a string, otherwise it will lead to a failure to match, guess for next.js in the type judgment or map operation, this in the follow-up source code to understand in the learning.
# :light_bulb_on: Understanding getStaticProps and getServerSideProps in Next.js
It's crucial to recognize that getStaticProps and getServerSideProps are not interchangeable within the same page in Next.js. getStaticProps is tailored for Static Site Generation (SSG) scenarios, while getServerSideProps is designed for Server-Side Rendering (SSR) scenarios. Attempting to use both in a single page will trigger a Next.js warning: You cannot use getStaticProps or getStaticPaths with getServerSideProps To use SSG, please remove getServerSideProps.
From a design perspective, mixing them might seem logical: getStaticProps for fetching static data and getServerSideProps for dynamic data, with dynamic potentially overriding static. However, Next.js enforces a function singularity principle, advocating for clear separation of static and dynamic data fetching mechanisms to ensure optimal performance and predictability.
# :light_bulb_on: When to Use getStaticProps
The decision on when to utilize getStaticProps can be guided by the nature of the data on your page:
- Static Data Updates: If your page content updates are triggered by publishing actions, getStaticProps is the ideal choice. It's essential, however, to be mindful of data security and privacy concerns.
- Mix of Static and Dynamic Data: For pages containing both static and dynamic data, it's recommended to stick with getServerSideProps. This ensures that dynamic content is accurately rendered based on each request, maintaining up-to-date information and interaction.
In summary, while getStaticProps offers significant benefits for pages with data that doesn't change frequently, scenarios requiring real-time data should leverage getServerSideProps for its ability to fetch and render content server-side on each request. The choice between these data fetching methods hinges on the specific requirements of your Next.js application and the data it needs to present.
# Pre-rendering
- Nextjs will pre-generate the HTML for each page, instead of letting client-side Javascript generate the HTML. Each HTML generated is associated with the minimum JavaScript code required for that page. When the browser loads the page, its JavaScript code works and makes the page fully interactive. (This process is called hydration.)
# Two Forms of Pre-rendering
# Static generation:
- Static generation is the
pre-rendering
method where theHTML
pages are generated at build time. It offers excellent performance since the HTML is generated once and reused for each request. There are two scenarios inStatic Generation
:- Without Data: This is suitable for pages that do not require external data to be rendered. The
HTML
is generated at build time and can be cached and served by a CDN. - With Data: When the page content depends on external data (e.g., from a headless CMS), you can fetch this data at build time and generate the
HTML
based on that data. This approach is still static since the data fetching andHTML
generation happen once during the build process.- Incremental Static Regeneration (ISR): An enhancement to static generation with data, ISR allows pages to be regenerated on a per-request basis, at a defined interval, without needing to rebuild the entire site. This makes it possible to have updated data without sacrificing the benefits of static generation
- Without Data: This is suitable for pages that do not require external data to be rendered. The
# Server-Side Rendering (SSR)
- Data Fetching: SSR dynamically generates the HTML for each page on every request, which means it can always serve the most up-to-date content. It's particularly useful for pages that fetch data that changes frequently, ensuring that users always get the latest information.
- Dynamic Parameters Support: SSR is ideal for handling dynamic routes where the content of the page depends on parameters passed in the URL. The server can use these parameters to fetch specific data and render the page accordingly.
Use Cases | Static Generation | Server-Side Rendering |
Blogging Sites: - Content updates infrequently. - At build time, articles are fetched from a headless CMS to generate static pages for fast access. | E-commerce Sites: - Product information, prices, and stock levels change frequently. - SSR ensures that users see the most up-to-date product information. | |
Documentation Sites: - Technical documentation with relatively low update frequency. - Static pages are easy to cache and distribute, speeding up access. | Social Media Platforms: - User posts, comments, and other content are constantly updated. - SSR dynamically generates pages with the latest content, enhancing real-time interaction. |
# How to Enabling Static Generation
Static Generation is a pre-rendering technique in Next.js that allows for the generation of HTML pages at build time. The most straightforward way to enable Static Generation is by using getStaticProps
(for fetching page data) and getStaticPaths
(for pages with dynamic routes) within your pages.
# Production Server vs. Development Server
- Production Server: When you run the
next build
command to build your application, Next.js generates static HTML for every page that utilizesgetStaticProps
. These pages are rendered at build time and subsequently, each request serves these pre-rendered static pages without regenerating them. This means that once the build is complete, the page content will not change unless a rebuild is executed. - Development Server: In development mode (usually initiated with
npm run dev
oryarn dev
),getStaticProps
is executed on every request for the sake of convenience in development. This ensures that you see the most up-to-date data and page changes while developing. The development mode simulates the static generation of the production mode but ensures hot reloading after each file change, offering a smoother development experience.
# Fetching Data at Request Time
# Data Fetching with Dynamic Parameters and Client-Side Data Fetching
- Dynamic Parameter Support in Server-Side Rendering: Server-side rendering allows for dynamic data fetching based on request parameters, making it ideal for pages with dynamic routes. This flexibility enables the server to generate page content that specifically matches the parameters of each request.
- Client-Side Data Fetching: Data can also be fetched on the client-side using JavaScript, which is suitable for scenarios where page content needs to be updated in real-time based on user interactions. This approach allows web applications to fetch and render data reactively, enhancing the user experience with dynamic content.
# Combining Pre-rendering with Client-Side Data Fetching
By integrating pre-rendering techniques with client-side data fetching, developers can create applications that are both fast to load and highly interactive. Static content is pre-rendered at build time for quick initial display to users, while dynamic content is fetched and updated on the client-side as users interact with the application. This combination offers the best of both worlds: the performance benefits of static generation and the flexibility of dynamic, client-side data updates.