Table of Contents

Pengenalan
Apa itu Next.js

Next.js adalah sebuah React framework yang dibuat untuk mengatasi masalah client-side rendering yang dimiliki React.

Kapan Menggunakan Next.js

Sebuah halaman website yang dibuat menggunakan React ‘terasa ringan’ karena tampilan website sangat interaktif. Selain itu, saat data berubah, React dengan efisien akan mengupdate bagian dari halaman website yang memang perlu diupdate tanpa perlu reload satu halaman penuh.

Untuk mendapatkan itu semua, client harus load semua file JavaScript sebelum konten halaman ditampilkan. Jika file JS cukup besar maka waktu yang dibutuhkan untuk load pertama kali juga menjadi lebih lama.

Masalah lain dari client-side rendering adalah SEO, ada kemungkinan web crawler berusaha mengindex halaman yang belum selesai dirender sepenuhnya (karena waktu load yang lama). Dan menganggap web tersebut blank.

Kedua masalah diatas dapat diselesaikan dengan teknik pre-rendering. Yaitu halaman HTML dan file JavaScript di generate sebelum dikirim ke client.

Server Side Rendering (SSR)

Sesuai namanya proses render terjadi di server dan bukan di client,  server mengubah package React dan JavaScript menjadi HTML setiap kali browser memanggil halaman tersebut. Teknik cache menggunakan CDN dapat diterapkan untuk mempersingkat waktu akses

Static Site Generator (SSG)

Pada sistem static site generator, setiap browser memanggil halaman tersebut, server tidak perlu men-generate HTML lagi. Alasannya, server melakukan generate halaman HTML pada tahap build, yaitu tahap konversi kode program menjadi website utuh.

Penggunaan SSG lebih direkomendasikan karena bisa mempercepat proses loading halaman pada browser.

Pun demikian, Anda sebenarnya bisa menggunakan jenis pre-rendering yang berbeda untuk tiap halaman website. Misalnya, SSG digunakan untuk Landing Page, sementara SSR digunakan untuk Homepage.

Jadi reactjs sebenarnya kurang memenuhi standard jika digunakan untuk membuat sebuah website public dimana harus memenuhi SEO dan Fast Load disitulah next.js akan berperan.

Fitur
  1. Routing Pages

    Pada Next.js, semua file halaman pada folder pages juga merupakan file routingnya. Artinya, Anda tidak perlu membuat file routing yang berbeda untuk setiap halaman.

    Dengan demikian, waktu yang diperlukan untuk menulis kode program jadi lebih singkat. Dampak positifnya, project yang dibangun akan cepat selesai.

  2. Built-in CSS Support

    Anda bisa mengimpor CSS dari file JavaScript karena karena Next.js memiliki fitur build in CSS support yang canggih.

    Next.js menggunakan tag secara default sehingga semua skrip CSS di dalam tag tersebut dapat dipisahkan untuk halaman tertentu. Dengan begitu, Anda tidak perlu menulis ulang skrip CSS pada file halaman.

  3. Layout Component

    Next.js memungkinkan Anda untuk memecah konstruksi halaman menjadi sekumpulan komponen. Nantinya, setiap komponen dapat digunakan kembali pada halaman lain dengan mudah.

    Contohnya, Anda bisa menggunakan komponen header yang sama untuk semua halaman website tanpa perlu menulis skrip header berulang kali.

  4. Image Optimization

    Next.js menggunakan komponen gambar next/image, yang merupakan penyempurna dari komponen HTML . Hal ini menyebabkan Next.js lebih cocok untuk ekosistem website modern.

    Pasalnya, komponen tersebut dapat melakukan resize gambar sesuai dengan konfigurasi yang ditetapkan browser. Ukuran gambar jadi lebih responsif terhadap perangkat yang digunakan untuk membuka website.

  5. Font Optimization

    Secara default, Next.js akan mengatur inline font CSS secara otomatis pada tahap build. Hal tersebut dapat mempercepat proses mengenalkan (deklarasi) font.

    Hasilnya, waktu yang dibutuhkan sebuah halaman untuk memuat teks hingga akhirnya semua konten dapat dimunculkan jadi lebih singkat.

  6. Script Optimization

    Komponen script pada Next.js memungkinkan Anda mengatur prioritas loading pada script pihak ketiga.

    Sebagai contoh, Anda punya tiga script yaitu analisis konten, pengelola iklan, dan widget media sosial. Anda bisa mengatur analisis konten yang jadi prioritas utama dengan menempatkannya pada baris teratas.

    Hal tersebut dapat mempercepat loading website dan mencegah konten tidak muncul di website.

  7. Static File Serving

    Next.js dapat menyiapkan file statis pada folder public. Gunanya, untuk memudahkan Anda ketika memanggil dan menggunakan file statis tersebut pada halaman tertentu.

    Contohnya, pada file gambar, Anda bisa langsung memanggil bahkan mengatur ukuran gambar tersebut di setiap halaman yang dikehendaki. Jadi, Anda tidak perlu mengunggah beberapa gambar yang sama dalam berbagai ukuran.

  8. Fast Refresh

    Fast Refresh adalah fitur Next.js yang memungkinkan sebuah halaman melakukan refresh sesaat setelah mendeteksi perubahaan script.

    Fitur ini bermanfaat bagi developer, karena Anda tidak perlu lagi merefresh browser untuk melihat hasil setiap menulis atau mengubah script.

    Selain delapan fitur yang disebutkan di atas, Next.js juga membawa fitur-fitur bawaan React.js yang bisa Anda gunakan tanpa adanya permasalahan dukungan sama sekali.

Persiapan
  1. Visual Studio Code
  2. Terminal
  3. Nodejs + NPM/yarn
Installasi

Mirip dengan create-react-app. Untuk membuat sebuah aplikasi Next.js kita bisa gunakan package create-next-app.

				
					npx create-next-app my-blog
cd my-blog
				
			

Jalankan

				
					npm run dev
				
			

Hasilnya akan seperti gambar berikut.

Implementasi Project Baru

Setelah membuat project Next.js, saatnya membuat halaman baru dan melakukan navigasi antar halaman.

Navigasi

Sistem routing pada Next.js adalah page-based, artinya setiap halaman memiliki alamat url (slug) sesuai dengan nama file dari halaman tersebut.

Contoh:

  1. Halaman pages/about.js dapat diakses dengan alamat url /about
  2. Halaman pages/posts/my-post.js dapat diakses dengan alamat url /posts/my-post

Hal ini berbeda dengan aplikasi React dimana untuk membuat sistem routing kita harus gunakan package tambahan seperti react-router-dom.

Membuat Page Baru

Buat sebuah folder pada folder pages dengan nama posts kemudian buat sebuah file baru dengan nama index.tsx.

pages/posts/index.tsx

				
					import styles from '@/styles/Home.module.css'
export default function IndexPost() {
    return (<>
        <main className={styles.main}>
            <div className={styles.grid}>
                <div className={styles.card}>            
                    <h3>What is Lorem Ipsum?</h3>
                    <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
                </div>
                <div className={styles.card}>            
                    <h3>Why do we use it?</h3>
                    <p>t is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).</p>
                </div>
            </div>
        </main>
    </>);
}
				
			
Update index.tsx

Update code halaman pages/index.js menjadi seperti ini:

				
					import Head from 'next/head'
import Link from 'next/link'
import { Inter } from '@next/font/google'
import styles from '@/styles/Home.module.css'

const inter = Inter({ subsets: ['latin'] })

export default function Home() {
  return (
    <>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main className={styles.main}>
        <h1 className={styles.title}>Welcome to My Blog</h1>
        <div className={styles.grid}>
          <div className={styles.card}>
            <Link href="/posts">
              <h3>All Post</h3>
              <p>Read All Post</p>
            </Link>
          </div>
        </div>
      </main>
    </>
  )
}

				
			

Sama seperti reactjs untuk membuat link antar halaman kita bisa gunakan component Link yang sudah disediakan oleh Next.js. Jadi kita tidak gunakan tag link .

Component Link ini juga akan mengaktifkan client-side navigation, dimana proses peralihan dari satu halaman ke halaman lain dilakukan oleh JavaScript dan bukan browser

Hasilnya seperti di bawah ini.

Layout Component

Kita bisa membuat sebuah shared component yang bisa digunakan pada semua halaman lain dengan menggunakan Layout atau yang istilah lain sering digunakan yaitu Template.

Buat sebuah folder dengan nama components kemudian buat beberapa file baru:

  1. navbar.tsx
  2. layout.js
  3. footer.tsx

Kenapa kita menggunakan .js pada layout.js, karena jika menggunakan .tsx ada warning error pada Visual Code

pages/components/navbar.js

				
					export default function Navbar() {
    return (<>
        <h1>Navbar</h1>
    </>);
}
				
			

pages/components/layout.js

				
					import Head from 'next/head'
import { Inter } from '@next/font/google'
import styles from '@/styles/Home.module.css'
import Navbar from './navbar'
import Footer from './footer'

const inter = Inter({ subsets: ['latin'] })

export default function Layout({ children }) {
  return (
    <>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main className={styles.main}>
        <Navbar />
        <div className='container'>{children}</div>
        <Footer />
      </main>
      <Footer />
    </>
  )
}
				
			

pages/components/footer.js

				
					export default function footer() {
    return (<>
        <h1>Footer</h1>
    </>);
}
				
			

Lalu update kembail index.tsx

				
					import Layout from './components/layout'
import Link from "next/link";
import styles from '@/styles/Home.module.css'

export default function Home() {
  return (<>
      <Layout>
        <h1 className={styles.title}>Welcome to My Blog</h1>
        <div className={styles.grid}>
          <div className={styles.card}>
            <Link href="/posts">
              <h3>All Post</h3>
              <p>Read All Post</p>
            </Link>
          </div>
        </div>
      </Layout>
  </>)
}

				
			

Hasilnya seperti di bawah ini.

Styles

Penggunaan styles pada next.js mirip seperti react.js

  1. import ‘../styles/mystyle.css’
  2. import styles from ‘@styles/mystyle.module.css’;

Namun ada penambahan filtur styles-jsx, seperti di bawah ini

 

				
					import styles from '@/styles/Home.module.css'
import Layout from '../components/layout'
export default function IndexPost() {
    return (<>
        <Layout>
            <div className={styles.grid}>
                <div className={styles.card}>            
                    <h3>What is Lorem Ipsum?</h3>
                    <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
                </div>
                <div className={styles.card}>            
                    <h3>Why do we use it?</h3>
                    <p>t is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).</p>
                </div>
            </div>
        </Layout>
        <style jsx>{`
            p {
                color: red;
            }
        `}</style>
    </>);
}
				
			

Sedangkan jika ingin menerapkan sebuah style ke semua halaman, gunakan Global Styles.

Untuk melakukannya dapat disesuaikan pada file styles/global.css.

Asset & Image Optimization

Asset

Untuk menghandle asset seperti file gambar kita bisa simpan di dalam folder public.

Kita bisa akses file gambar cukup dengan menggunakan nama file tanpa path (relative path).

				
					<img decoding="async" src="/next.svg" alt="My Image" className="logo" />
				
			

Image Optimization

next/image, adalah ekstensi dari elemen HTML, yang dikembangkan untuk web modern. Mencakup berbagai pengoptimalan kinerja dalam membantu mencapai Data Web yang baik. Skor ini merupakan ukuran penting dari pengalaman pengguna di situs web Anda, dan diperhitungkan dalam peringkat pencarian Google. Berikut cara penggunaannya.

				
					import Image from 'next/image'
import logo from '@/public/next.svg'

export default function Navbar() {
    return (<>
        <Image width="100"
            src={logo} alt="logo"
        />
    </>);
}
				
			
Data Fetching

Next.js menggunakan function yang berbeda untuk proses data fetching pada setiap teknik pre-rendering:

  1. Untuk SSG kita gunakan function getStaticProps.
  2. Untuk SSR kita gunakan function getServerSideProps.

Pada bagian ini kita akan buat demo fetch data dari sebuah API menggunakan pre-rendering SSG.

Menyiapkan API

Kita bisa gunakan package json-server untuk membuat API.

Install json-server

				
					npm install -g json-server 
				
			

Buat sebuah file dengan nama db.json.

				
					{
    "posts": [{
        "id": 1,
        "title": "His mother had always taught him",
        "body": "His mother had always taught him not to ever think of himself as better than others. He'd tried to live by this motto. He never looked down on those who were less fortunate or who had less money than him. But the stupidity of the group of people he was talking to made him change his mind.",
        "userId": 9,
        "tags": [
            "history",
            "american",
            "crime"
            ],
        "reactions": 2
    },{
        "id": 2,
        "title": "He was an expert but not in a discipline",
        "body": "He was an expert but not in a discipline that anyone could fully appreciate. He knew how to hold the cone just right so that the soft server ice-cream fell into it at the precise angle to form a perfect cone each and every time. It had taken years to perfect and he could now do it without even putting any thought behind it.",
        "userId": 13,
        "tags": [
        "french",
        "fiction",
        "english"
        ],
        "reactions": 2
    },{
        "id": 3,
        "title": "Dave watched as the forest burned up on the hill.",
        "body": "Dave watched as the forest burned up on the hill, only a few miles from her house. The car had been hastily packed and Marta was inside trying to round up the last of the pets. Dave went through his mental list of the most important papers and documents that they couldn't leave behind. He scolded himself for not having prepared these better in advance and hoped that he had remembered everything that was needed. He continued to wait for Marta to appear with the pets, but she still was nowhere to be seen.",
        "userId": 32,
        "tags": [
            "magical",
            "history",
            "french"
        ],
        "reactions": 5
    },
    {
        "id": 4,
        "title": "All he wanted was a candy bar.",
        "body": "All he wanted was a candy bar. It didn't seem like a difficult request to comprehend, but the clerk remained frozen and didn't seem to want to honor the request. It might have had something to do with the gun pointed at his face.",
        "userId": 12,
        "tags": [
            "mystery",
            "english",
            "american"
        ],
        "reactions": 1
    }]
}
				
			

Kemudian jalankan perintah berikut ini untuk start server

				
					json-server --watch db.json --port 3001
				
			
Implementasi getStaticProps

Ubah file pages/posts/index.js

				
					import Link from "next/link";
import styles from '@/styles/Home.module.css'
import Layout from '../components/layout'
export default function IndexPost({ externalPostData }) {
    return (<>
        <Layout>
            <div className={styles.grid}>
                {externalPostData.map((data) => {
                    return (
                        <div className={styles.card} key={data.id}>
                            <Link href={`details/${data.id}`}>
                            <h3>{data.title}</h3>
                            </Link>
                            <p>{data.body}</p>
                        </div>
                    );
                })}
            </div>
        </Layout>
        <style jsx>{`
            p {
                color: red;
            }
        `}</style>
    </>);
}

export async function getStaticProps() {
    const apiURL = "http://localhost:3001/posts";
    const response = await fetch(apiURL);
    const data = await response.json();
    return {
        props: {
          externalPostData: data,
        },
    };
}
				
			

Fetch data berhasil ditampilkan dengan dengan route /posts namun saat diklik route selanjutnya posts/id akan menampilkan error 404 dikarenakan kita belum membuat route dinamis untuk posts.

Dynamic Routes/ URLs

Dengan dynamic routes kita bisa buat halaman berdasarkan external data seperti dari API.

Kita akan gunakan function bernama getStaticPaths untuk generate path yang dibutuhkan.

Buat sebuah file dengan nama [id].js di dalam folder pages/posts.

				
					import Layout from '../components/layout'
export default function Post({postData}) {    
    return (
      <Layout>
        <h1>{ postData.title }</h1>
        <p>{ postData.body }</p>
      </Layout>
    );
}
export async function getStaticPaths() {
    const res = await fetch('http://localhost:3001/posts')
    const posts = await res.json()
  
    const paths = posts.map((post) => ({
        params: { id: post.id.toString() },
    }))
  
    return { paths, fallback: false }
  }
export async function getStaticProps({params}) {
    const apiURL = `http://localhost:3001/posts/${params.id}`;
    const response = await fetch(apiURL);
    const data = await response.json();
    return {
        props: {
          postData: data,
        },
    };
}