Next.js Dynamic SSG Sinhala Guide | getStaticPaths & getStaticProps Tutorial

Next.js Dynamic SSG Sinhala Guide | getStaticPaths & getStaticProps Tutorial

ආයුබෝවන් යාළුවනේ! Next.js වල Dynamic SSG බලය තේරුම් ගනිමු!

මේ වෙනකොට Web Development වල Next.js කියන්නේ ගොඩක් දෙනෙක් අතර ජනප්‍රිය වෙලා තියෙන Framework එකක්. ඒකට ප්‍රධානම හේතුව තමයි Server-Side Rendering (SSR) සහ Static Site Generation (SSG) වගේ දේවල් ඉතා පහසුවෙන් මේකෙන් කරගන්න පුළුවන් වීම. මේකෙන් අපේ Web Application එකේ Performance එක සහ SEO (Search Engine Optimization) ගොඩක් වැඩි දියුණු කරගන්න පුළුවන් වෙනවා.

හැබැයි අපි සාමාන්‍යයෙන් SSG ගැන කතා කරනකොට හිතන්නේ Blog Post වගේ, අලුතින් Pages එකතු නොවෙන, Static Content තියෙන Web Sites ගැන. නමුත් Dynamic Content තියෙන Web Sites (උදාහරණයක් විදියට Products ගොඩක් තියෙන E-commerce Site එකක්, එහෙමත් නැත්නම් Blog Posts දහස් ගණනක් තියෙන Blog එකක්) Build Time එකේදී කොහොමද Static විදියට generate කරන්නේ? මෙන්න මේ ප්‍රශ්නයට පිළිතුර තමයි Next.js වල තියෙන getStaticPaths සහ getStaticProps කියන Functions දෙක.

අද අපි මේ Guide එකෙන් බලමු, මේ Functions දෙකෙන් කොහොමද Dynamic Content තියෙන Pages Build Time එකේදී Static විදියට Generate කරගන්නේ කියලා. ඒ වගේම fallback options ගැනයි, ඒවයින් වෙන දේවල් සහ Best Practices ගැනත් අපි විස්තරාත්මකව කතා කරනවා. එහෙනම් අපි පටන් ගමු!

1. getStaticProps කියන්නේ මොකක්ද? (What is getStaticProps?)

මුලින්ම අපි getStaticProps කියන්නේ මොකක්ද කියලා පොඩ්ඩක් මතක් කරගමු. මේ Function එකෙන් වෙන්නේ Build Time එකේදී Page එකක් Pre-render කරන්න අවශ්‍ය Data Fetch කරගන්න එක. මේක Page එකේ Component එකට Props විදියට යවනවා. මේක හැම විටම Server-side එකේදී විතරයි Run වෙන්නේ, Client-side එකේදී නෙවෙයි. ඒ වගේම Production Build එකක් හදනකොට විතරයි Run වෙන්නේ.

// pages/about.js

function About({ data }) {
  return (
    <div>
      <h1>About Us</h1>
      <p>{data.content}</p>
    </div>
  );
}

export async function getStaticProps() {
  // Build Time එකේදී Data Fetch කරනවා
  const res = await fetch('https://api.example.com/about');
  const data = await res.json();

  return {
    props: { data },
    // revalidate: 60 // Optional: Every 60 seconds, Next.js will try to re-generate the page if a request comes in.
  };
}

export default About;

මේ Code එකේදී, getStaticProps Function එකෙන් 'https://api.example.com/about' කියන API එකෙන් Data අරගෙන, Page එක Render කරනකොට 'data' කියන Prop එක විදියට About Component එකට යවනවා. මේ Page එක Build Time එකේදී සම්පූර්ණයෙන්ම HTML විදියට Generate වෙනවා.

2. Dynamic Routes සහ SSG (Dynamic Routes and SSG)

දැන් හිතන්න, අපිට Blog Post ගොඩක් තියෙනවා කියලා. ඒ හැම Post එකකටම තියෙන්නේ වෙන වෙනම URL එකක්. උදාහරණයක් විදියට /posts/1, /posts/2, /posts/my-first-post වගේ. Next.js වල මේ වගේ Dynamic Pages හදන්න පුළුවන් pages/posts/[id].js වගේ File Structure එකක් පාවිච්චි කරලා.

මේ වගේ තැනකදී අපි හිතමු getStaticProps විතරක් පාවිච්චි කරනවා කියලා. එතකොට Next.js දන්නේ නැහැ Build Time එකේදී [id] කියන තැනට මොන මොන Values ද එන්න ඕනේ කියලා. Post 1000ක් තියෙනවා නම්, Next.js දන්නේ නැහැ Post 1000ටම Pages Generate කරන්න ඕනේ කියලා. මෙන්න මේ ප්‍රශ්නයට විසඳුම තමයි getStaticPaths.

3. getStaticPaths යොදාගැනීම (Using getStaticPaths)

getStaticPaths කියන Function එකේ ප්‍රධානම වැඩේ තමයි Next.js ට කියන එක, මේ Dynamic Page එකට Build Time එකේදී Pre-render කරන්න ඕනේ මොන මොන Paths ද කියලා. මේකත් Build Time එකේදී Server-side එකේදී විතරයි Run වෙන්නේ.

getStaticPaths Function එකෙන් Return කරන්න ඕනේ Object එකක්. ඒකේ paths කියන Property එකට Array එකක් දෙනවා. ඒ Array එකේ තියෙන්නේ Pre-render කරන්න ඕනේ Paths. ඒ වගේම fallback කියන Property එකත් Return කරන්න ඕනේ. මේක ගැන අපි පස්සේ කතා කරමු.

ප්‍රායෝගික උදාහරණයක්: Blog Posts Pre-rendering

හිතන්න අපිට Blog Posts ටිකක් තියෙනවා, ඒක API එකකින් ගන්න පුළුවන් කියලා.

// pages/posts/[id].js

import { useRouter } from 'next/router';

function Post({ post }) {
  const router = useRouter();

  // Fallback: true වෙනකොට Page එක තාම Generate වෙනවා නම් මේක පෙන්වන්න පුළුවන්
  if (router.isFallback) {
    return <div>Loading post details...</div>;
  }

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
}

export async function getStaticPaths() {
  // 1. හැම Post එකකම ID ටික ගන්නවා
  const res = await fetch('https://jsonplaceholder.typicode.com/posts');
  const posts = await res.json();

  // 2. ඒ ID ටික 'paths' Array එකට හැරෙව්වා. (උදා: { params: { id: '1' } } )
  const paths = posts.map((post) => ({
    params: { id: post.id.toString() }, // 'id' එක String එකක් වෙන්න ඕනේ
  }));

  // 3. 'paths' සහ 'fallback' Return කරනවා
  return {
    paths,
    fallback: false, // අපි මේක ගැන පහලින් කතා කරමු
  };
}

export async function getStaticProps({ params }) {
  // 1. 'params.id' එක පාවිච්චි කරලා අදාළ Post එකේ Data ගන්නවා
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
  const post = await res.json();

  // 2. 'props' විදියට Post එක Page එකට යවනවා
  return {
    props: { post },
  };
}

export default Post;

Code එක පැහැදිලි කිරීම:

  • getStaticPaths:
    • මුලින්ම අපි Sample API එකකින් (jsonplaceholder.typicode.com/posts) හැම Post එකකම Data ටික ගන්නවා.
    • ඊට පස්සේ ඒ Data එකෙන් id ටික extract කරලා, Next.js ට ඕන කරන format එකට ({ params: { id: '...' } }) හදනවා. මෙතනදී id එක String එකක් විදියට තියෙන්න ඕනේ.
    • අන්තිමට, හදාගත්ත paths Array එකයි fallback Property එකයි Return කරනවා. මේ උදාහරණයට අපි fallback: false කියලා දීලා තියෙනවා.
  • getStaticProps:
    • මේ Function එකට context Object එකක් ලැබෙනවා. ඒක ඇතුළේ params කියන Property එක තියෙනවා. අපේ Dynamic Route එක [id] නිසා, params.id එකට අදාළ Post එකේ ID එක ලැබෙනවා.
    • ඒ ID එක පාවිච්චි කරලා, අදාළ Post එකේ Data API එකෙන් Fetch කරගන්නවා.
    • Fetch කරගත්ත post Object එක props විදියට Post Component එකට යවනවා.

මේ විදියට Production Build එකක් හදනකොට (npm run build) Next.js විසින් getStaticPaths Run කරලා, ඒකෙන් Return කරන හැම Path එකකටම වෙන වෙනම Static HTML File එකක් Generate කරනවා. ඒ HTML File එකට Data එක ගන්නේ getStaticProps වලින්.

4. Fallback Options (fallback: true, false, blocking)

getStaticPaths Function එකෙන් Return කරන fallback කියන Property එක ගොඩක් වැදගත්. ඒකෙන් කියවෙන්නේ, paths Array එකේ සඳහන් කරලා නැති Paths (URLs) වලට Next.js හැසිරෙන්නේ කොහොමද කියලා.

a. fallback: false

fallback: false දාලා තියෙනවා නම්, getStaticPaths එකෙන් Return කරන paths වල තියෙන Pages ටික විතරයි Build Time එකේදී Generate වෙන්නේ. ඒ paths වල නැති වෙනත් Page එකකට Request එකක් ආවොත්, Next.js විසින් 404 Page එකක් පෙන්වනවා.

ප්‍රයෝජන:

  • සියලුම Pages ගණන ස්ථාවරයි (උදා: About Us, Contact Us වගේ).
  • සියලුම Pages Build Time එකේදී Generate වෙන නිසා, Client-side Navigation එක ඉතා වේගවත්.

අවාසි:

  • අපිට Build කරන්න ඕන Pages ගොඩක් තියෙනවා නම්, Build Time එක ගොඩක් වැඩි වෙන්න පුළුවන්.
  • අලුතින් Data එකතු වෙනකොට (උදා: අලුත් Blog Post එකක් දැම්මොත්), ඒකට අලුතින් Build එකක් දාන්න වෙනවා.

උදාහරණය:

// pages/posts/[id].js
// ... other code ...

export async function getStaticPaths() {
  const paths = [
    { params: { id: '1' } },
    { params: { id: '2' } },
  ]; // මේවා විතරයි Generate වෙන්නේ

  return {
    paths,
    fallback: false, // වෙනත් ID එකකට ගියොත් 404
  };
}

// ... other code ...

b. fallback: true

fallback: true දාලා තියෙනවා නම්, Build Time එකේදී getStaticPaths එකෙන් Return කරන Paths ටික විතරක් Generate වෙනවා. හැබැයි, paths වල නැති, නමුත් වලංගු (valid) Dynamic Path එකකට Request එකක් ආවොත්, Next.js විසින්:

  • මුලින්ම 'fallback' (Loading) Page එකක් පෙන්වනවා. මේක router.isFallback කියන එකෙන් detect කරන්න පුළුවන්.
  • ඒ අතරේ Server එකේදී අලුත් Page එක generate කරනවා.
  • Page එක generate උනාට පස්සේ, Client-side එකෙන් ඒ Data එක Fetch කරගෙන Full Page එක Load කරනවා.
  • ඊට පස්සේ අලුතින් Generate වෙච්ච Page එක Cache කරනවා. ඊළඟ වතාවේ ඒ Page එකට Request එකක් ආවොත්, ඒක Fast (Static) විදියට Load වෙනවා.

ප්‍රයෝජන:

  • ගොඩක් Pages තියෙන Web Sites වලට ගොඩක් හොඳයි. Build Time එක අඩු කරගන්න පුළුවන්.
  • අලුතින් Content එකතු උනත්, ඒකට Build එකක් දාන්න ඕන නැහැ. Usersලා Request කරනකොටම Auto Generate වෙනවා.

අවාසි:

  • පළමු වතාවට Page එකකට යනකොට පොඩි Loading Time එකක් තියෙන්න පුළුවන්.

උදාහරණය:

// pages/posts/[id].js

import { useRouter } from 'next/router';

function Post({ post }) {
  const router = useRouter();

  // Page එක තාම Generate වෙනවා නම් මේක පෙන්වනවා
  if (router.isFallback) {
    return <div><h1>පොඩ්ඩක් ඉන්න, Post එක Load වෙනවා...</h1></div>;
  }

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
}

export async function getStaticPaths() {
  // අපි මුල් Post 20 විතරක් Build Time එකේදී Generate කරමු
  const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=20');
  const posts = await res.json();

  const paths = posts.map((post) => ({
    params: { id: post.id.toString() },
  }));

  return {
    paths,
    fallback: true, // මේක වැදගත්
  };
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
  const post = await res.json();

  // Post එකක් නැත්නම් notFound: true දාන්න පුළුවන්
  if (!post.id) {
    return {
      notFound: true,
    };
  }

  return {
    props: { post },
  };
}

export default Post;

c. fallback: 'blocking'

fallback: 'blocking' කියන්නේ fallback: true වගේමයි. හැබැයි මේකේදී Loading State එකක් පෙන්වන්නේ නැහැ. Request එකක් ආවොත්, Next.js විසින් Server එකේදී අදාළ Page එක Generate කරලා, ඒක Generate වෙනකම් Request එක Block කරලා තියෙනවා. Page එක සම්පූර්ණයෙන්ම Generate උනාට පස්සේ තමයි Client එකට යවන්නේ. ඒ නිසා User ට දැනෙන්නේ සාමාන්‍ය SSR Page එකක් Load වෙනවා වගේ.

ප්‍රයෝජන:

  • Loading State එකක් පෙන්වන්න ඕන නැති, User Experience එකට වැඩි Focus එකක් දෙන අවස්ථාවලට හොඳයි.
  • fallback: true වගේම Build Time එක අඩුයි, Dynamic Content වලට හොඳයි.

අවාසි:

  • පළමු වතාවට Page එකකට යනකොට, Page එක Generate වෙනකම් User ට සුළු ප්‍රමාදයක් (delay) වෙන්න පුළුවන්. (fallback: true වගේ Loading Spinner එකක් නැති නිසා, User ට හිතෙන්න පුළුවන් Site එක Slowයි කියලා.)

උදාහරණය:

// pages/posts/[id].js
// ... other code ...

export async function getStaticPaths() {
  const paths = [
    { params: { id: '1' } },
    { params: { id: '2' } },
  ]; 

  return {
    paths,
    fallback: 'blocking', // මේක වැදගත්
  };
}

// ... other code ...

5. Best Practices & Common Issues (හොඳම ක්‍රම සහ දෝෂ නිවැරදි කිරීම)

fallback option එක තෝරාගැනීම:

  • fallback: false:
    • ඔබේ Web Site එකේ Pages ගණන ස්ථාවර නම් (blog posts, products වගේ දේවල් අලුතින් දවසට ගොඩක් add වෙන්නේ නැත්නම්).
    • සියලුම Pages Build Time එකේදී generate කරන්න පුළුවන් Build Time එකක් තියෙනවා නම්.
    • SEO සඳහා ඉතාමත් හොඳයි.
  • fallback: true:
    • ගොඩක් විශාල Pages ගණනක් තියෙන Web Sites (eCommerce Sites, විශාල Blog Sites වගේ) වලට හොඳම විසඳුම.
    • අලුතින් Content එකතු වෙනකොට Auto Generate වෙන්න ඕන නම්.
    • මුලින්ම Pages වලට යනකොට Loading State එකක් පෙන්වන්න කැමති නම්.
  • fallback: 'blocking':
    • fallback: true වගේම විශාල Sites වලට හොඳයි.
    • හැබැයි Loading State එකක් පෙන්වන්න කැමති නැත්නම්.
    • Usersලාට Seamless Experience එකක් දෙන්න ඕන නම්, හැබැයි පළමු Request එකේදී පොඩි ප්‍රමාදයක් දරාගන්න පුළුවන් නම්.

Troubleshooting සහ Tips:

  • Build Output එක බලන්න: npm run build අණ දීලා Build එක දානකොට, Next.js විසින් Generate කරන Pages ගණන console එකේ පෙන්වනවා. ● (SSG) කියලා පෙන්නන ඒවා Build Time එකේදී Generate වෙච්ච Pages. λ (SSR) කියන්නේ Serverless Function එකක් විදියට Server එකේ Generate වෙන Pages.
  • getStaticPaths වල params: params Object එකේ තියෙන හැම Value එකක්ම String එකක් වෙන්න ඕනේ. Numeric ID එකක් නම් .toString() කරලා දෙන්න.
  • Data Fetching Errors: getStaticProps හෝ getStaticPaths වල Data Fetch කරනකොට Error එකක් ආවොත්, Build එක Fail වෙන්න පුළුවන්. Error Handling (try...catch) දාන්න පුරුදු වෙන්න.

Incremental Static Regeneration (ISR) / revalidate: getStaticProps Function එකෙන් revalidate Property එකක් Return කරලා, generate වෙච්ච Static Page එකක් නියමිත කාලයකට පස්සේ (උදා: තප්පර 60කට පස්සේ) අලුත් Data එකකින් Refresh වෙන්න සලස්වන්න පුළුවන්. මේකෙන් Build එකක් නැතුවම Static Pages Update කරගන්න පුළුවන්.

// in getStaticProps
return {
  props: { post },
  revalidate: 60, // Page එක තප්පර 60කට පස්සේ re-generate කරන්න උත්සාහ කරයි
};

notFound: true: getStaticProps එකේදී Data එකක් හම්බුනේ නැත්නම් (උදා: id එකට අදාළ Post එකක් නැත්නම්), return { notFound: true } කියලා දෙන්න පුළුවන්. එතකොට Next.js විසින් 404 Page එකක් පෙන්වනවා.

// in getStaticProps
if (!post) {
  return {
    notFound: true,
  };
}

නිගමනය (Conclusion)

ඉතින් යාළුවනේ, Next.js වල getStaticPaths සහ getStaticProps කියන Functions දෙක පාවිච්චි කරලා කොහොමද Dynamic Content තියෙන Web Sites වුණත් Static Site Generation (SSG) විදියට හදන්න පුළුවන් කියලා අපි අද මේ Guide එකෙන් ඉගෙන ගත්තා. මේකෙන් අපේ Web Application එකේ Performance එක, Scalability එක සහ SEO Capabilities ගොඩක් වැඩි කරගන්න පුළුවන්.

විශේෂයෙන්ම fallback options (false, true, blocking) ගැන අවබෝධය කියන්නේ ගොඩක් වැදගත් දෙයක්. ඔබේ Project එකේ අවශ්‍යතාවයට අනුව නිවැරදි fallback option එක තෝරාගැනීමෙන් ඔබට ඉතා කාර්යක්ෂම සහ User-friendly Next.js Application එකක් හදන්න පුළුවන් වෙනවා.

දැන් ඔයාට පුළුවන් මේ දැනුම පාවිච්චි කරලා ඔයාගේම Next.js Project එකක Dynamic SSG Features ටිකක් Implement කරන්න. මොකද Theory එකට වඩා Practice එක ගොඩක් වැදගත්. මේ ගැන ඔයාට මොනවා හරි ගැටළු තියෙනවා නම්, එහෙමත් නැත්නම් ඔයාගේ අත්දැකීම් ගැන කියන්න පුළුවන් නම්, පහළින් Comment එකක් දාගෙන යන්න. තවත් අලුත් Technical Article එකකින් ඉක්මනටම හම්බවෙමු! තෙරුවන් සරණයි!