0%

NextJS Review

About Next.js

  1. React is a JavaScript library for building interactive user interfaces.
  2. Next.js is a React framework that gives you building blocks to create web applications.

From JavaScript to React

  1. Rendering user interfaces
    • Browser reads HTML to create DOM( an object representation of the HTML elements, acts an bridge between code and the UI)
    • You can use DOM methods and a programming language to listen to user events and manipulation the DOM by selecting, adding, updating, and deleting elements in the UI.
  2. Updating the UI with JavaScript and DOM methods
    • HTML represents the initial page content, DOM represents the updated page content, so they can be different
    • Imperative programming gives steps, declarative programming gives the result
    • React is a declarative UI library: you can tell React what you want to happen to the user interface, and React will figure ou the steps how to update the DOM on your behalf
  3. Getting started with React
    • Use the following script to include React in your page
      1
      2
      <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
      <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    • react is the core React library
    • react-dom provides DOM-specific methods that enable you to use React with the DOM
    • You cannot directly write HTML in JavaScript, you need to do so with JSX
    • JSX is a syntax extension for JavaScript that allows you to describe your UI in a familiar HTML-like syntax. Apart from the three JSX rules, you do not need to learn any new symbols or syntax outside of HTML and JavaScript
    • Three rules of JSX:
      • Return a single root element
      • Close all the tags: self-closing tags like <img> should be <img />
      • Use camelCase all most of the things
    • Browsers do not understand JSX, so you need to provide a JavaScript compiler to transform JSX code into regular JavaScript. Also use <script type="text\jsx"> instead of <script> to tell the compiler that the code is JSX
      1
      2
      <!-- Include the Babel compiler -->
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    • ReactDOM.render(element, container[, callback])
  4. Essential JavaScript for React: omitted
  5. React Core Components
    • Components
    • Props
    • State
  6. Building UI with components
    • UI can be broken into smaller building blocks called components
    • Components allow you to build self-contained, reusable snippets of code
    • Components are JavaScript functions that return UI elements
    • React components should be capitalized and wrapped with angle brackets
    • Nesting components is possible
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      <script type="text/jsx">
      const app = document.getElementById('app');
      const Header = () => {
      return (
      <h1> Hello, world!</h1>
      );
      }
      const HomePage = () => {
      return (
      <div>
      <Header />
      <p>Welcome to my website!</p>
      </div>
      );
      );
      }
      ReactDOM.render(<HomePage />, app);
      </script>
  7. Displaying data with props
    • You can pass data to components using props
    • props is an object
    • Use curly braces to access variable in JSX
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      <script type="text/jsx">
      const app = document.getElementById('div1');
      const HomePage = () => {
      const list = [1, 2, 3];
      const props = {
      title: "Hello world!",
      info: "This is a test page."
      }
      return (
      <div>
      <Header {...props}/>
      <ol>
      {list.map((item) => {
      <!-- List item should has an unique key property -->
      return (<li key={item}>{item}</li>);
      })}
      </ol>
      </div>
      )
      }
      const Header = (props) => {
      return (
      <div>
      <h1>{props.title}</h1>
      <p>{props.info}</p>
      </div>
      );
      }
      ReactDOM.render(<HomePage />, app);
      </script>
  8. Adding interactivity using State
    • Use const[state, updateState] = React.useState(initialState) to create a state variable and update it
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      <script type="text/jsx">
      const app = document.getElementById('div1');
      const HomePage = () => {
      const [likes, setLikes] = React.useState(0);
      const handleClick1 = () => {
      setLikes(likes + 1);
      }
      const handleClick2 = () => {
      setLikes(0);
      }

      const props = {
      title: "Hello world!",
      info: "This is a test page."
      }
      return (
      <div>
      <Header {...props}/>
      <button onClick={handleClick1}>Likes = {likes}</button>
      <button onClick={handleClick2}>Reset Likes</button>
      </div>
      )
      }
      const Header = (props) => {
      return (
      <div>
      <h1>{props.title}</h1>
      <p>{props.info}</p>
      </div>
      );
      }
      ReactDOM.render(<HomePage />, app);
      </script>

From React to Next.js

  1. Get Next.js in your project: npm install react react-dom next
    • The original html
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      <html>
      <body>
      <div id="app"></div>

      <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
      <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

      <script type="text/jsx">
      const app = document.getElementById("app")

      function Header({ title }) {
      return <h1>{title ? title : "Default title"}</h1>
      }

      function HomePage() {
      const names = ["Ada Lovelace", "Grace Hopper", "Margaret Hamilton"]
      const [likes, setLikes] = React.useState(0)

      function handleClick() {
      setLikes(likes + 1)
      }

      return (
      <div>
      <Header title="Develop. Preview. Ship. 🚀" />
      <ul>
      {names.map((name) => (
      <li key={name}>{name}</li>
      ))}
      </ul>

      <button onClick={handleClick}>Like ({likes})</button>
      </div>
      )
      }

      ReactDOM.render(<HomePage />, app)
      </script>
      </body>
      </html>
    • The Next.js file
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      import { useState } from "react";

      const Header = (props) => {
      return (
      <div>
      <h1>{props.title}</h1>
      <p>{props.paragraph}</p>
      </div>
      );
      }

      const HomePage = () => {
      const[likes, setLikes] = useState(0);

      const list = [1, 2, 3, 4];

      const props = {
      title:"Hello World!",
      paragraph:"Welcome to this test page"
      };

      const clickHandler1 = () => {
      setLikes(likes + 1);
      }

      const clickHandler2 = () => {
      setLikes(0);
      }

      return (
      <div>
      <Header {...props}/>
      <ol>
      {list.map((item) => {
      return <li key={item}>{item}</li>
      })}
      </ol>
      <button onClick={clickHandler1}>Increase Likes</button>
      <button onClick={clickHandler2}>Reset Likes</button>
      <div>Likes: {likes}</div>
      </div>
      );
      }

      export default HomePage;
    • Add the above code into a index.js file in the pages folder
    • Add the following code to package.json
      1
      2
      3
      "scripts": {
      "dev": "next dev",
      },
    • Next.js uses fast refresh, so when you make a change to the code and save, the page will be automatically updated

How Next.js Works

  1. Development and Production Environments

    • In development environment, Next.js supports TypeScript, ESLint integration, Fast Refresh, etc.
    • In the production stage, Next.js optimizes for the end-users
    • The Next.js compiler
      • Next.js handles code transformation and underlying infrastructure to make it easier for an application to go to production
      • Next.js has a compiler written in Rust, and SWC, a platform that can be used for compilation, minification, bundling, etc.
  2. Compiling

    • Code in JSX, TypeScript, modern version of JavaScript needs to be compiled into JavaScript before browsers can understand them
    • Compilation happens during the development states when you edit your code, and as part of the build step to prepare your application for production
  3. Minifying

    • Developers write code that is optimized for human readability
    • Minification is the process of removing unnecessary code formatting and comments without changing the code's functionality
  4. Bundling

    • Developers break up their application into modules, components, and functions that can be used to build larger pieces of their application
    • Bundling is the process of resolving the web of dependencies and merging the files into optimized bundles for the browser, with the goal of reducing the number of requests for files when a user visits a web page
  5. Code splitting

    • Developers usually split their application into multiple pages that can be accessed from different URLs, each of these pages becomes a unique entry point into the application
    • The goal of code splitting is to improve the application's initial load time by only loading the code required to run that page
    • Each file inside the pages/ directory will be code split into its own JavaScript bundle during the build step
    • Any code shared between pages will also split into another bundle to avoid re-downloading the same code
  6. Build Time and Runtime

    • Build time is the name given to a series of steps that prepare your application code for production
    • Code is transformed into production-optimized files ready to be deployed to servers and consumed by users during build time, including HTML files, JavaScript code for rendering pages on the server, JavaScript code for making pages interactive on the client, CSS files
    • Runtime refers to the period of time when your application runs in response to a user's request, after your application has been build and deployed
  7. Client and server: omitted

  8. Rendering

    • Rendering is the process to convert the code you write in React into the HTML representation of your UI
    • It can take place on the server or on the client, ahead of time at build time, or on every request at runtime
    • Three types of rendering methods are available with Next.js: Server-side rendering, static site generation, and client-side rendering
    • Pre-rendering: server-side rendering and static site generation, because fetching external data and transformation of React components into HTML happens before the result is sent to the client, Next.js pre-renders every page by default
    • Client-side rendering: browsers receive an empty HTML shell from the server with the JavaScript instructions to construct the UI
    • Server-side rendering: the HTML page is generated on a server for each request. The generated HTML, JSON data, and JavaScript instructions to make the page interactive are then sent to the client
    • Static site generation: the HTML is generated on the server, content is generated once, at build time, when the application is deployed, and the HTML is stored in a CDN and re-used for each request
  9. CDNs and the Edge

    • Your application code can be distributed to origin servers, CDNS(content delivery networks), and the Edge
    • Origin servers: the main computer that stores and runs the original version of your application code
    • CDNS: store static content in multiple locations around the world and are placed between the client and the origin server (closer cached result to the client)
    • The Edge: a generalized concept for the fringe of the network, closest to the user, Edge can cache static contents, and also run code

Create a Next.js App

  1. Install Node.js
  2. Run npx create-next-app app-name --use-npm to create a Next.js app
    • The command is create-next-app
    • app-name is the name of your app
    • --use-npm tells the CLI to bootstrap the app using npm
    • Use --ts to create a TypeScript app
  1. In Next.js, a page is a React Component exported from a file in the pages directory
  2. Pages are associated with a route based on their file name:
    • pages/index.js is associated with the / route
    • pages/posts/first-post.js is associated with the /posts/first-post route
  3. Use Link component to navigate between pages in Next.js
    • Very similar to the a tag in HTML
    • Allows users to do client-side navigation inside an Next.js app and accepts props that give better control over the navigation behavior
    • If you want to navigate to a page that is outside of the Next.js app, use the a tag
    • If you want to add properties to a link, wrap an a tag inside a Link component, and add the properties to the a tag
      1
      2
      import Link from "next/link";
      <Link href="URL">Display Text</Link>
    • It is also possible to use dynamic routes, the file name should include [variable] to represent the dynamic route, and use userRouter().query to get that variable
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      // this is in the pages/posts/[pid].js
      import Link from "next/link";
      import { useRouter } from 'next/router'

      const Header = (props) => {
      return (
      <div>
      <h1>Post {props.pid}</h1>
      </div>
      );
      }

      const Post = () => {
      const props = useRouter().query;
      return (
      <div>
      <Header {...props} />
      <div>
      <Link href="/">Back to Home page.</Link>
      </div>
      </div>
      );
      }

      export default Post;
    • Link is client-side navigation, the browser only re-render the part that is changed, if you use a tag, the browser will reload the whole page

Assets, Metadata, and CSS

  1. Assets
    • Next.js serve static assets under the public directory
    • The public directory is also useful for robots.txt, Google site verification, and any other static assets
    • URL pattern: for public/profile.jpg, the URL will be /profile.jpg in the app
  2. The Image Component
    • You can use the image tag to import images
    • next/image is an extension of the HTML img tag, it supports for image optimization by default (resizing, optimizing, and serving images in modern formats)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      import Image from "next/image";

      const ProfileFigure = () => {
      return (
      <Image
      src="/profile.jpg"
      alt="Picture of the author"
      width={200}
      height={200}
      />

      );
      }

      const Profile = () => {
      return (
      <div>
      <h1>Profile page</h1>
      <ProfileFigure />
      </div>
      );
      }

      export default Profile;
  3. Metadata
    • Add head to a page
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      import Head from "next/head";

      const Profile = () => {
      return (
      <div>
      <Head>
      <title>Profile</title>
      <link rel="icon" href="/favicon.ico" />
      </Head>
      <h1>Profile page</h1>
      </div>
      );
      }

      export default Profile;
  4. Third-party scripts
    • Method one: use HTML script tag in the Head component
    • Method two: use the Script component in next/script, the strategy attribute controls when the third-party script should load, the onLoad attribute is used to run any JavaScript code immediately after the script has finished loading
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      import Script from "next/script";

      const Profile = () => {
      return (
      <div>
      <Head>
      <title>Profile</title>
      <link rel="icon" href="/favicon.ico" />
      </Head>
      <h1>Profile page</h1>
      <Script
      src="https://www.google-analytics.com/analytics.js"
      strategy="lazyOnload"
      onLoad={() =>
      console.log(`script loaded correctly, window.FB has been populated`)
      }
      />
      </div>
      );
      }
  5. CSS