Skip to content

k435467/hands-on-nextjs

Repository files navigation

My notes

Practice the nextjs tutorial.

root
    components
        //  react components

    lib
        // our own ts lib

    pages
        // page views
        _app.tsx     // for global styling
        index.tsx    // path '/'

    posts
        // for posts .md data

    public
        // assets

    styles
        // global and utils css

    package-lock.json
    package.json
    tsconfig.json

Create a Next.js App

requirements:

  • Node.js > 10.13

Create a Next.js app

npx create-next-app nextjs-blog --use-npm --example "https://github.com/vercel/next-learn-starter/tree/master/learn-starter"

Run the dev server

cd nextjs-blog
npm run dev

Navigate Between Pages

Pages are associated with a route based on their file name. A page is a React Component exported from them.

  • pages/index.js is associated with the / route.
  • pages/posts/first-post.js is associated with the /posts/first-post route.

Link Component

import Link from "next/link";
<h1 className="title">
  Read{" "}
  <Link href="/posts/first-post">
    <a>this page!</a>
  </Link>
</h1>

It is client-side navigation,which means that the page transition happens using JS . The browser does not do a full refresh. Also see: Code splitting and prefetching.

Note: If we need to link to external page outside the Next.js app, just use an <a> tag without <Link>

Note: If we need to add attributes, add it to the <a> tag, not to the <Link> tag.

Assets, Metadata, and CSS

Assets and Images

  • public/images directory
  • lazy loaded
  • resizing & optimizing
import Image from "next/image";

const YourComponent = () => (
  <Image
    priority // the image is preloaded with this attribute, otherwise it is lazy loaded.
    src="/images/profile.jpg" // Route of the image file
    height={144} // Desired size with correct aspect ratio
    width={144} // Desired size with correct aspect ratio
    alt="Your Name"
  />
);

Metadata and Head

import Head from "next/head";
export default function FirstPost() {
  return (
    <>
      <Head>
        <title>First Post</title>
      </Head>
      <h1>First Post</h1>
    </>
  );
}

CSS Sytling

Styled-JSX

pages/index.js

Write CSS directly in .js files.

<style jsx>{`

`}</style>

CSS Module

It scope styles at the component level.

  • Import the CSS file and assign a name to it, like styles
  • Use styles.container as the className

components/layout.js

import styles from "./layout.module.css";

export default function Layout({ children }) {
  return <div className={styles.container}>{children}</div>;
}

For multiple components. styles/utils.module.css

Important: To use CSS Module, the CSS file name must end with .module.cs.

Global Styles

To load global CSS files, create a file called pages/_app.js with the following content:

import "../styles/global.css";

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

Important: Need to restart the dev server when we add pages/_app.js.

Styling Tips

  • Using classnames library to toggle classes
  • Customizing PostCSS Config. Wailwind CSS.
  • Using Sass

Pre-rendering and Data Fetching

  • 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.

Static Generation with Data using getStaticProps

getStaticProps runs at build time in prodution, and we can fetch external data and send it as props to the page.

export default function Home(props) { ... }

export async function getStaticProps() {
  // Get external data from the file system, API, DB, etc.
  const data = ...

  // The value of the `props` key will be
  //  passed to the `Home` component
  return {
    props: ...
  }
}

Fetching Data at Request Time with getServerSideProps

export async function getServerSideProps(context) {
  return {
    props: {
      // props for your component
    },
  };
}

Its parameter (context) contains request specific parameters.

Client-side Rendering with SWR Hook

highly recommended.

  • handles caching
  • revalidation
  • focus tracking
  • refetching on interval
import useSWR from "swr";

function Profile() {
  const { data, error } = useSWR("/api/user", fetch);

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;
  return <div>hello {data.name}!</div>;
}

Dynamic Routes

Staticlly generate pages with paths that depend on external data. This enables dynamic URLs in Next.js.

image: How to Statically Generate Pages with Dynamic Routes

API Routes

Serverless functions. By creating a function inside the pages/api directory.

// pages/api/hello.js

// // req = HTTP incoming message, res = HTTP server response
// export default function handler(req, res) {
//   // ...
// }

export default function handler(req, res) {
  res.status(200).json({ text: "Hello" });
}
  • Do Not Fetch an API Route from getStaticProps or getStaticPaths
  • Preview Mode: When writing a draft on a headless CMS and want to preview the draft immediately, and let Next.js to render these pages at request time instead of build time.
  • Dynamic API Routes

Deploying Your Next.js App

  • Custom Domains
  • Environment Variables

Develop, Preview, Ship. Preview deployment for every push by creating a new pull request.

TypeScript

  • touch tsconfig.json
  • starting/restarting the dev server
  • follow the instructions to install TypeScript
  • starting the dev server again
npx create-next-app --ts
# or
yarn create next-app --typescript