pre-rendering: on first page load the browser receives pre-rendered HTML to speed up loading / displaying
advantages:
example:
Disable JavaScript in your browser's developer tools settings and visit reactjs.org - you will still see content, though some interactivity will not work (e.g. dropdowns)
usual process for fetching data in a React app:
process with server-side rendering:
React framework that supports:
The next.js website has great materials: https://nextjs.org
npx create-next-app@latest
npx create-next-app@latest --ts
possible project structure:
npm run dev
to build a production version:
npm run build
to run it (on the server):
npm run start
possible only if no server-side rendering is needed (i.e. no getServerSideProps
)
change the build script in package.json to: next build && next export
then build the static version (to the out folder) via:
npm run build
Example page definition:
// pages/index.tsx
import type { NextPage } from 'next';
import Link from 'next/link';
import Head from 'next/head';
const Index: NextPage = () => (
<div>
<Head>
<title>Home</title>
</Head>
<Link href="/about">
<a>About Page</a>
</Link>
<p>Hello Next.js</p>
</div>
);
export default Index;
special components provided by next:
Link
: link inside a single-page applicationHead
: enables easily setting content of the page's <head>
elementdefining "global" content that is shared across all pages:
// _app.tsx
function MyApp({ Component, pageProps }: AppProps) {
return (
<div>
{/* fixed header content */}
<header>header content</header>
{/* variable content - defined by the route */}
<Component {...pageProps} />
{/* fixed footer content */}
<footer>footer content</footer>
</div>
);
}
Task: create further pages
in next.js we can define code that is executed at several different points:
when building, next.js will pre-render all entries in the pages
directory
some pages are pre-rendered without any additional input, others might be connected to data sources
special (asynchronous) functions that we can export from a page definition file:
getServerSideProps
(runs every time a page is requested)getStaticProps
(runs during build)can load data and pass them into the page components as props
are only executed on the build machine or server respectively → may read files or make direct database queries
The functionality of fetch will be polyfilled automatically
example: a page that loads a random joke from an API
import type { GetServerSideProps, NextPage } from 'next';
type JokeProps = { joke: string };
const Joke: NextPage<JokeProps> = (props) => (
<article>{props.joke}</article>
);
const getServerSideProps: GetServerSideProps<JokeProps> = async () => {
const url = 'https://api.chucknorris.io/jokes/random';
const res = await fetch(url);
const joke = (await res.json()).value;
return { props: { joke: joke } };
};
export default Joke;
export { getServerSideProps };
exercises:
we can query parameters from URLs like these:
/todos/3
/todos/?todoid=3
Route parameters are enclosed in square brackets in the file name, e.g. pages/todos/[id].js
Dynamically querying route parameters:
import { NextPage } from 'next';
import { useRouter } from 'next/router';
const TodoDetails: NextPage = () => {
const router = useRouter();
return (
<div>
<h1>detail view for todo {router.query.id}</h1>
</div>
);
};
export default TodoDetails;
pre-rendering pages based on a set of route parameters - via getStaticPaths
export const getStaticPaths: GetStaticPaths = () => {
const paths = [];
for (let i = 1; i <= 200; i++) {
paths.push({ params: { id: String(i) } });
}
return { paths, fallback: false };
};
getStaticPaths
returns an array describing the routes under the entry paths
- the entries are passed to getStaticProps
after implementing getStaticPaths
we can pre-render pages with dynamic routes
npm run build