This is a starter template for Learn Next.js.
Chapter Link: https://nextjs.org/learn/basics/create-nextjs-app
nvm use 18
npx create-next-app@latest nextjs-blog --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/learn-starter"
Chapter Link: https://nextjs.org/learn/basics/navigate-between-pages
- depends on file system
- root of pages in
./pages
folder of project - folders and file name represent the routing
Link
component ofnext/link
to navigate- acts like
a
element, but route needs to be set manually - difference being that it's fully client side (i.e. not fetching from server)
- see
pageurl
in wagtail templates - or
url
in django templates
- acts like
Refs:
- https://nextjs.org/docs/pages/building-your-application/routing
- https://nextjs.org/docs/pages/api-reference/components/link
Chapter Link: https://nextjs.org/learn/basics/assets-metadata-css
public
folder for assets- sample route would be
/images/profile.jpg
forpublic/images/profile.jpg
- for images, leverage
Image
component ofnext/image
- handles optimization (e.g. size, format)
Refs.:
- Usage: https://nextjs.org/docs/pages/building-your-application/optimizing/images
- API: https://nextjs.org/docs/pages/api-reference/components/image
Head
component available fromnext/head
e.g. to modify page title
Refs.:
- risk of render blocking avoided with
Script
component ofnext/script
strategy
to define how important the script is:beforeInteractive
afterInteractive
lazyOnload
onLoad
prop to execute extra JS after loading
Refs.:
- usage: https://nextjs.org/docs/pages/building-your-application/optimizing/scripts
- API: https://nextjs.org/docs/pages/api-reference/components/script
- with extra file matching component name
components/Button.module.css
components/Button.js
import styles from './Button.module.css'
withincomponents/Button.js
- Regular stylesheets and global CSS files are still supported
- in case of installation via node
- e.g. global import:
import 'bootstrap/dist/css/bootstrap.css'
withinpages/_app.js
- e.g. component level:
import '@reach/dialog/styles.css'
Refs:
- Tailwind: https://nextjs.org/docs/pages/building-your-application/styling/tailwind-css
- Tailwind example: https://github.com/vercel/next.js/tree/canary/examples/with-tailwindcss
Motivation: example for component-level styles and creating a container component
- layout component to carry styling to serve as container for children components
components/layout.js
components/layout.module.css
- connect CSS via
import styles from './layout.module.css';
in JS file - and mount to JSX HTML element via
className={styles.container}
container
being defined in the CSS file- next creates unique class names on app level
- global styles can only be imported in
_app.js
Motivation: Remove more of the boilerplate example code
- usage of constant to render sth
meta
tags inside of<Header>
layout which will be included in children (if used in/as children)- ternary JSX fragment pattern depending on
home
flag
- clsx to toggle classes https://www.npmjs.com/package/clsx
.success {
color: green;
}
.error {
color: red;
}
import styles from './alert.module.css';
import { clsx } from 'clsx';
export default function Alert({ children, type }) {
return (
<div
className={clsx({
[styles.success]: type === 'success',
[styles.error]: type === 'error',
})}
>
{children}
</div>
);
}
- Customizing PostCSS Config and 3. tailwind
- manipulation of the CSS shipped to the client such that
- vendor prefixes are set (distinguish whose CSS it actually is)
- collisions are voided
npm install -D tailwindcss autoprefixer postcss
-D
for --save-dev (separate from prod package)
- SASS
npm install -D sass
Ref.:
- postcss https://www.youtube.com/watch?v=WhCXiEwdU1A
- styling tech in general https://www.youtube.com/watch?v=ouncVBiye_M
Lesson goals:
- pre-rendering feature
- static and server side rendering
- static generation with data and without
- getStaticProps Step: https://nextjs.org/learn/basics/data-fetching/setup
a) static rendering
Complete static HTML can be hosted by e.g. nginx
typical: Marketing pages
b) server side rendering
creates the HTML for each request
- run some of the js in the background and return some of the app as html
- each way, saves time on client side to render vs pure react app
- use static if not much dynamic elements are present (i.e. data is updated)
- static/server side can be configured on page level
- example to get data from the filesystem and include it into our component
export async function getStaticProps() {
const allPostsData = getSortedPostsData(); // external calls
return {
props: {
allPostsData,
},
};
}
- Within the component module, above the functional component:
- convention name
getStaticProps
- returns
{props: { <prop name>: <prop value>}}
or short{props: {variableName}}
(Object Property Shorthand) - runs only on the server side (that's why we were able to use nodes API)
- runs on every request in
dev
mode - runs once at build time
- can only be exported from a page
We could just as well do an external API call instead of reading files from the local file system
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from an external API endpoint
const res = await fetch('..');
return res.json();
}
or DB calls
import someDatabaseSDK from 'someDatabaseSDK'
const databaseClient = someDatabaseSDK.createClient(...)
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from a database
return databaseClient.query('SELECT posts...')
}
Ref.:
- to fetch non-static data
You should use getServerSideProps only if you need to pre-render a page whose data must be fetched at request time.
export async function getServerSideProps(context) {
// magic
return {
props: {
// props for your component
},
};
}
Ref.:
- use case: dashboard, it's private, we will need creds before we can render anything
SWR
Next.js way of what we could do withuseEffect
Ref.:- [Client-side data fetching with SWR] (https://nextjs.org/docs/pages/building-your-application/data-fetching/client-side#client-side-data-fetching-with-swr)
Node specific details:
- fs is a Node.js module that let's you read files from the file system.
- path is a Node.js module that let's you manipulate file paths.
- matter is a library that let's you parse the metadata in each markdown file.
Chapter Link: https://nextjs.org/learn/basics/dynamic-routes
- dynamic paths need a
[id].js
within a subfolder - it contains
- the React component on how to render the data
getStaticPaths
to tell next.js what paths do exists- and
getStaticProps
to tell next.js what to render on each dynamic route
- runs with every request in
dev
- runs once at build time in
prod
- expects
paths
to be of[{params: {id: 'theActualId'},...]
format
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}
Ref.:
export async function getStaticProps({params}) {
const postData = await getPostData(params.id);
return {
props: {
postData,
}
};
}
- ... the utility function could do a DB query or an API query:
export async function getAllPostIds() {
// Instead of the file system,
// fetch post data from an external API endpoint
const res = await fetch('..');
const posts = await res.json();
return posts.map((post) => {
return {
params: {
id: post.id,
},
};
});
}
- in the case of markdown,
dangerouslySetInnerHTML
can be used - in combo with
remark
library - and
remark-html
- additionally
date-fns
was introduced for date formatting
- since we already have posts metadata (including the ide)
<Link href={
/posts/${id}}>{title}</Link>
- custom 404 page can be created within
pages
:pages/404
- same for 500
Ref.:
Chapter link: https://nextjs.org/learn/basics/api-routes
- offers independent API routes
- can be dynamic as well just like pages
- use cases
- can be used to save form input directly to the database
- preview route
- not to be used within
getStaticProps
,getStaticPaths
since we can avoid the HTTP traffic altogether with a utility function (i.e. which could be called by bothgetStatic*
and the API route handler)
// pages/api/hello.js
// accessable at http://localhost:3000/api/hello
export default function handler(req, res) {
res.status(200).json({ text: 'Hello' });
}
Chapter Link: https://nextjs.org/learn/basics/deploying-nextjs-app/
- create Vercel account
- connect Vercel to Github Account
- import repo
- deploy: https://nextjs-tut-blue.vercel.app/
- any new push will auto-magically trigger redeploy
-
https out of the box
-
custom domain can be mapped
-
admin interface for environment variables
-
PR preview
-
https://tailwindcss.com/ https://github.com/unicodeveloper/awesome-nextjs?search=1 https://nextjs.org/docs