Next.js Code Splitting & Dynamic Imports | Bundle Optimization Sinhala Guide

Next.js Code Splitting & Dynamic Imports | Bundle Optimization Sinhala Guide

ආයුබෝවන්, හැමෝටම! 👋 අද අපි කතා කරන්න යන්නේ Next.js එක්ක වැඩ කරන ඔයාලට අනිවාර්යයෙන්ම දැනගන්න ඕන වැදගත් මාතෘකාවක් ගැන. ඒ තමයි Code Splitting සහ Bundle Optimization. වෙබ් අඩවියක් හරි ඇප් එකක් හරි හදනකොට, ඒක කොච්චර වේගෙන් load වෙනවද කියන එක User Experience එකට සහ SEO (Search Engine Optimization) එකට ගොඩක් බලපානවා, නේද?

ඉතින්, Next.js කියන්නේ performance ගැන ගොඩක් හිතලා හදපු Framework එකක්. ඒකේ තියෙන විශේෂ හැකියාවක් තමයි Automatic Code Splitting. මේකෙන් වෙන්නේ ඔයාලා ලියන කෝඩ් එක පොඩි පොඩි කෑලි වලට කඩලා, අවශ්‍ය වෙලාවට විතරක් load කරන එක. මේ නිසා Initial Load Time එක ගොඩක් අඩු වෙනවා.

මේ tutorial එකෙන් අපි:

  • Next.js වල Code Splitting කියන්නේ මොකක්ද කියලා හොඳට තේරුම් ගන්නවා.
  • next/dynamic කියන විශේෂ feature එක පාවිච්චි කරලා, අපේ components අවශ්‍ය වෙලාවට විතරක් load කරගන්න හැටි ඉගෙන ගන්නවා (Dynamic Imports).
  • ඔබේ ඇප් එකේ bundle size එක analyze කරන්නේ කොහොමද කියලා බලනවා.
  • අවසානයේදී, Best Practices කිහිපයක් සහ පොදු ගැටළු වලට විසඳුම් ගැන කතා කරනවා.

එහෙනම්, අපි පටන් ගමු!

Next.js වල Code Splitting කියන්නේ මොකක්ද?

සරලවම කියනවා නම්, Code Splitting කියන්නේ ඔබේ JavaScript කෝඩ් එක එකම ලොකු ගොඩකට (Single Bundle) දාන්නේ නැතුව, අවශ්‍ය තැන් වලට වෙන වෙනම පොඩි පොඩි කෑලි වලට (Chunks) කඩලා තියෙන එකට. මේකෙන් වෙන්නේ, වෙබ් ඇප් එකක් load වෙනකොට, මුලින්ම පෙන්වන්න ඕන දේවල් වලට අදාළ කෝඩ් එක විතරක් load කරලා, ඉතුරු ටික පස්සේ load කරන්න පුළුවන් වෙන එක.

හිතන්නකෝ, ඔයාලා ගොඩක් විශාල වෙබ් අඩවියක් හදනවා කියලා. ඒකේ ගොඩක් pages තියෙන්න පුළුවන්, ගොඩක් components තියෙන්න පුළුවන්. සාමාන්‍යයෙන්, මේ හැම කෝඩ් එකක්ම එක ලොකු JavaScript file එකකට දැම්මොත්, මුල් page එක load වෙන්න ගොඩක් වෙලා යනවා. මොකද Browser එකට සිද්ධ වෙනවා ඒ ලොකු file එකම download කරලා, parse කරලා, execute කරන්න. මේක User Experience එකට එච්චර හොඳ නැහැ.

Next.js මේක කරන්නේ කොහොමද?

Next.js Framework එකේදී, Automatic Code Splitting කියන feature එක build-in විදියටම එනවා. මේකෙන් වෙන්නේ:

  • Pages based Code Splitting: Next.js වල හැම page එකක්ම (pages/ directory එකේ තියෙන) වෙනම JavaScript bundle එකක් විදියට compile වෙනවා. ඒ කියන්නේ, User කෙනෙක් Home Page එකට යනකොට, Home Page එකට අදාළ කෝඩ් එක විතරයි download වෙන්නේ. Contact Page එකට ගියාම, Contact Page එකේ කෝඩ් එක download වෙනවා. මේකෙන් මුලින්ම load වෙන bundle එකේ ප්‍රමාණය ගොඩක් අඩු වෙනවා.
  • Dynamic Imports: Pages වලට අමතරව, ඔයාලට ඕන නම් ඔබේ components පවා අවශ්‍ය වෙලාවට විතරක් load වෙන්න සලස්වන්න පුළුවන්. මේකට අපි next/dynamic කියන එක පාවිච්චි කරනවා. මේ ගැන අපි තව ටිකකින් විස්තරාත්මකව කතා කරමු.

මේ Code Splitting නිසා, ඔබේ ඇප් එකේ Initial Load Time එක ගොඩක් අඩු වෙනවා. ඒ වගේම, Browser එකට download කරන්න තියෙන JavaScript ප්‍රමාණය අඩුවෙන නිසා, වෙබ් අඩවිය වේගවත්ව වැඩ කරනවා. මේක SEO වලටත් ගොඩක් වැදගත්, මොකද Google වගේ Search Engines වේගවත් වෙබ් අඩවි වලට කැමැත්තක් දක්වනවා.

Dynamic Imports (next/dynamic) හරහා Bundle Size අඩු කරගමු

Next.js වල Automatic Code Splitting එකෙන් Pages Level එකේදී bundle size එක manage කරනවා වගේම, අපිට තව දුරටත් අපේ components වලටත් මේ හැකියාව පාවිච්චි කරන්න පුළුවන්. ඒකට තමයි අපි next/dynamic කියන utility එක පාවිච්චි කරන්නේ. මේකෙන් අපිට පුළුවන්, යම්කිසි component එකක් මුලින්ම Page එක load වෙනකොටම load කරන්නේ නැතුව, අවශ්‍ය වෙලාවට (උදා: User කෙනෙක් බොත්තමක් click කලාම, හෝ Page එකේ පහළට scroll කලාම) load වෙන්න සලස්වන්න.

next/dynamic වැඩ කරන්නේ කොහොමද?

next/dynamic කියන්නේ Client-side only component එකක් විදියට Load වෙන Components හදන්න පාවිච්චි කරන React.lazy සහ Suspense වල Next.js version එකක් වගේ දෙයක්. මේකෙන් පුළුවන් ඔබේ component එක වෙනම JavaScript chunk එකක් විදියට build කරලා, run-time එකේදී load කරන්න.

ප්‍රායෝගික උදාහරණයක්: Large Component එකක් Dynamic විදියට Load කරමු

හිතන්න, ඔයාලට HeavyChart කියලා component එකක් තියෙනවා කියලා. මේකෙන් ලොකු chart library එකක් (උදා: Chart.js) import කරනවා, ඒ නිසා මේ component එකේ bundle size එක ටිකක් වැඩියි. හැබැයි මේ Chart එක හැම වෙලේම පෙන්වන්නේ නැහැ, සමහරවිට User කෙනෙක් 'Show Analytics' වගේ බොත්තමක් click කලාම විතරයි පෙන්වන්නේ.

සාමාන්‍යයෙන් මේ component එක import කරන්නේ මෙහෙමයි:

import HeavyChart from '../components/HeavyChart';

function Dashboard() {
  return (
    <div>
      <h1>Your Dashboard</h1>
      <HeavyChart />
    </div>
  );
}

export default Dashboard;

මේ විදියට import කලාම, HeavyChart component එකට අදාළ කෝඩ් එක Dashboard Page එක load වෙනකොටම bundle එකට එකතු වෙනවා. හැබැයි, අපිට ඕන මේක අවශ්‍ය වෙලාවට විතරක් load වෙන්න.

අපි මේක next/dynamic පාවිච්චි කරලා වෙනස් කරමු:

import dynamic from 'next/dynamic';
import React from 'react'; // React import කරන්න ඕන useState පාවිච්චි කරන නිසා

// HeavyChart component එක dynamic විදියට import කරනවා
const DynamicHeavyChart = dynamic(() => import('../components/HeavyChart'), {
  loading: () => <p>Loading chart...</p>, // Component එක load වෙනකන් පෙන්වන දේ
  ssr: false, // මේක Client-side එකේ විතරක් load කරන්න කියන එක (Optional, නමුත් මේ වගේ components වලට වැදගත්)
});

function Dashboard() {
  // state එකක් පාවිච්චි කරමු chart එක පෙන්වන්නද නැද්ද කියලා තීරණය කරන්න
  const [showChart, setShowChart] = React.useState(false);

  return (
    <div>
      <h1>Your Dashboard</h1>
      <button onClick={() => setShowChart(true)}>Show Analytics Chart</button>

      {showChart && <DynamicHeavyChart />}
    </div>
  );
}

export default Dashboard;

මේ කෝඩ් එකෙන් මොකක්ද වෙන්නේ?

  1. dynamic(() => import('../components/HeavyChart')): මේකෙන් Next.js ට කියනවා, HeavyChart component එක වෙනම JavaScript chunk එකක් විදියට compile කරන්න කියලා. ඒ වගේම, ඒක load කරන්නේ DynamicHeavyChart component එක render වෙන වෙලාවේ විතරයි.
  2. loading: () => <p>Loading chart...</p>: HeavyChart component එක load වෙනකන් User ට පෙන්වන්න පුළුවන් Loading Indicator එකක් මෙතනින් දෙන්න පුළුවන්. මේකෙන් User Experience එක හොඳ වෙනවා.
  3. ssr: false: මේක ගොඩක් වැදගත්. ssr: false කියලා දුන්නම Next.js ට කියනවා මේ component එක Server Side Rendering (SSR) වෙලාවේදී render කරන්න එපා කියලා. ඒක Client-side එකේදී විතරක් render කරන්න කියලා. Chart libraries වගේ Client-side APIs (like window object) පාවිච්චි කරන components වලට මේක අත්‍යවශ්‍යයි, මොකද SSR වෙලාවේදී window object එකක් නැති නිසා errors එන්න පුළුවන්.

මේ විදියට Dynamic Imports පාවිච්චි කලාම, Dashboard Page එක මුලින්ම load වෙනකොට HeavyChart එකේ කෝඩ් එක download වෙන්නේ නැහැ. User කෙනෙක් 'Show Analytics Chart' බොත්තම click කලාම විතරයි, ඒ component එකේ කෝඩ් එක network එකෙන් fetch කරලා, render කරන්නේ. මේකෙන් Initial Load Time එක සැලකිය යුතු මට්ටමකින් අඩු කරගන්න පුළුවන්.

Bundle Size Analysis සහ Debug කිරීම

ඔයාලා Dynamic Imports පාවිච්චි කලාට පස්සේ, ඇත්තටම Bundle Size එක අඩු වුණාද කියලා බලන්න ඕන, නේද? ඒ වගේම, ඔබේ Next.js ඇප් එකේ bundle size එක වැඩියි නම්, ඒකට හේතුව මොකක්ද කියලා හොයාගන්නත් මේ Tools උදව් වෙනවා. මේකට පාවිච්චි කරන්න පුළුවන් ප්‍රධානම Tool එක තමයි @next/bundle-analyzer.

@next/bundle-analyzer පාවිච්චි කරමු

මේක Webpack Bundle Analyzer එකේ Next.js version එකක්. මේකෙන් ඔබේ bundle එකේ තියෙන හැම module එකකම size එක Visualized map එකක් විදියට පෙන්වනවා. මේක install කරගන්න මුලින්ම:

npm install --save-dev @next/bundle-analyzer
# or
yarn add --dev @next/bundle-analyzer

ඊට පස්සේ, next.config.js file එක මේ විදියට වෙනස් කරන්න:

/** @type {import('next').NextConfig} */
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});

const nextConfig = {
  reactStrictMode: true,
};

module.exports = withBundleAnalyzer(nextConfig);

දැන් ඔයාලට පුළුවන් මේක run කරන්න:

ANALYZE=true npm run build
# or
ANALYZE=true yarn build

Build එක ඉවර වුණාට පස්සේ, ඔබේ Browser එකේ නව Tab කිහිපයක් විවෘත වෙයි. ඒ Tab වලට ඔබේ Client-side සහ Server-side bundles වල interactive map එකක් පෙනෙයි. මේ map එකෙන්, ඔබේ bundle එකේ වැඩිම ඉඩක් ගන්න modules මොනවද කියලා පැහැදිලිව බලාගන්න පුළුවන්.

මේ Map එක කියවන්නේ කොහොමද?

  • ලොකුම box (කොටු) තමයි ඔබේ bundle එකේ වැඩිම ඉඩක් අරගෙන තියෙන modules.
  • මේවා click කරලා තව විස්තර බලන්න පුළුවන්.
  • මේකෙන් ඔබට පුළුවන්, අනවශ්‍ය imports, duplicate libraries, නැත්නම් dynamic import කරන්න පුළුවන් ලොකු components මොනවද කියලා හඳුනාගන්න.

Common Issues සහ Debugging Tips

  • Component එක Client-side එකේ විතරක් render වෙන්න ඕනද?ssr: false නැතුව Client-side APIs (like window, document) පාවිච්චි කරන components render කරන්න හැදුවොත් "ReferenceError: window is not defined" වගේ errors එන්න පුළුවන්. මේ වගේ වෙලාවට dynamic(() => import('...'), { ssr: false }) කියලා දෙන්න මතක තියාගන්න.
  • Loading States හරියට පෙන්නනවාද?Dynamic component එකක් load වෙනකන් User ට මොකුත්ම නොපෙන්නුවොත්, ඒක User Experience එකට හොඳ නැහැ. loading: () => <p>Loading...</p> කියන option එක පාවිච්චි කරලා Loading Spinner එකක් වගේ දෙයක් පෙන්වන්න.
  • Preloading Strategies:Next.js වලට dynamic imports prefetch කරන්න පුළුවන්. ඒ කියන්නේ, User කෙනෙක් link එකක් උඩට mouse එක ගෙනාවම (hover කලාම) ඒ link එකට අදාළ page එකේ components prefetch කරන්න පුළුවන්. මේකෙන් User අදාළ page එකට ගියාම ඒක ගොඩක් වේගයෙන් load වෙනවා.

Best Practices සහ පොදු ගැටළු

Next.js වල Code Splitting සහ Dynamic Imports කියන features දෙක ගොඩක් ප්‍රයෝජනවත් වුණාට, ඒවා හරියට පාවිච්චි කරන්නේ නැත්නම්, අපිට බලාපොරොත්තු වෙන ප්‍රතිඵල නොලැබෙන්න පුළුවන්. මෙන්න ඒවා පාවිච්චි කරනකොට මතක තියාගන්න ඕන Best Practices කිහිපයක්:

  • අවශ්‍ය අවස්ථාවලදී පමණක් Dynamic Imports පාවිච්චි කරන්න:හැම component එකක්ම dynamic import කරන්න යන්න එපා. පොඩි components, නිතර පෙන්වන components dynamic import කිරීමෙන් තේරුමක් නැහැ, සමහරවිට ඒකෙන් bundle size එක ටිකක් වැඩි වෙන්නත් පුළුවන් (overhead එකක් නිසා). Dynamic imports පාවිච්චි කරන්න ඕන:
    1. විශාල Third-party Libraries පාවිච්චි කරන components වලට.
    2. මුලින්ම පෙන්වන්න අවශ්‍ය නැති, User interaction එකකින් පස්සේ පෙන්වන components වලට (උදා: Modals, Popups, Large Charts, Admin Panels).
    3. Page එකේ පහළට ගියාම විතරක් පෙන්වන components වලට (Lazy Loading).
  • SSR (Server-Side Rendering) ගැන සැලකිලිමත් වෙන්න:Client-side APIs (window, document) පාවිච්චි කරන components නම් අනිවාර්යයෙන්ම ssr: false කියන option එක dynamic import එකට දෙන්න. එහෙම නැත්නම්, SSR වෙලාවේදී errors එන්න පුළුවන්. ඒ වගේම, යම් component එකක content එක SEO වලට වැදගත් නම්, ssr: false දෙන එකෙන් ඒ component එකේ content එක Search Engines වලට index කරන්න බැරි වෙන්න පුළුවන්. ඒ නිසා මේ වගේ වෙලාවලදී හොඳට හිතලා බලන්න. සමහර වෙලාවට Google වගේ crawlers JavaScript execute කරන නිසා මේක ගැටලුවක් නොවෙන්න පුළුවන්, නමුත් සියලුම Search Engines එහෙම කරන්නේ නැහැ.
  • Loading State එකක් පෙන්වන්න:Dynamic component එකක් load වෙන අතරතුර User ට හිස් තිරයක් පෙන්වනවාට වඩා, ලස්සන Loading Spinner එකක් හරි "Loading..." වගේ message එකක් හරි පෙන්වීමෙන් User Experience එක වැඩි දියුණු වෙනවා.
  • Preloading හෝ Prefetching ගැන හිතන්න:Next.js Link component එකට built-in prefetching එකක් තියෙනවා, ඒකෙන් pages වලට අදාළ JavaScript bundles prefetch කරනවා. Dynamic components වලටත් custom preloading logic එකක් implement කරන්න පුළුවන්, User කෙනෙක් component එක අවශ්‍ය වෙන්න කලින් ටිකකට කලින්ම ඒක load කරන්න (උදා: User කෙනෙක් button එකක් උඩට mouse එක ගෙනාවම).
  • Bundle Analyzer නිතරම පාවිච්චි කරන්න:ඔබේ ඇප් එකේ development කරන අතරතුරේදී, නිතරම @next/bundle-analyzer පාවිච්චි කරලා bundle size එක analyze කරන්න. මේකෙන් අලුතින් එකතු වෙන ලොකු dependencies හඳුනාගෙන, ඒවා dynamic import කරන්න පුළුවන්ද කියලා බලන්න පුළුවන්.

පොදු ගැටළු (Common Issues):

  • Flickering Content: Dynamic component එකක් load වුණාට පස්සේ Layout Shift එකක් වගේ වෙන්න පුළුවන්. මේකෙන් User Experience එක බිඳ වැටෙන්න පුළුවන්. මේකට විසඳුමක් විදියට, loading state එකේදී component එකට Fixed Height / Width එකක් වගේ දෙයක් දෙන්න පුළුවන්.
  • SEO Issues (ssr: false භාවිතා කරන විට): ssr: false එක්ක load වෙන components වල content එක Server එකේදී render වෙන්නේ නැති නිසා, Search Engine Crawlers වලට ඒ content එක දකින්න බැරි වෙන්න පුළුවන්. SEO වලට ගොඩක් වැදගත් වන content එකක් dynamic import කරනවා නම්, මේ ගැන හොඳට හිතලා බලන්න.
  • Over-optimizing: හැම component එකක්ම dynamic import කරන්න හදන එකෙන් කෝඩ් එකේ complexity එක වැඩි වෙන්න පුළුවන්. සමහර වෙලාවට මේකෙන් performance වැඩි වෙනවා වෙනුවට අඩු වෙන්නත් පුළුවන් (network requests වැඩි වීමක් නිසා).

අවසානයට

ඉතින් යාලුවනේ, අද අපි Next.js වල Code Splitting සහ Bundle Optimization ගැන ගොඩක් දේවල් ඉගෙන ගත්තා. ඔබේ වෙබ් ඇප් එකක Initial Load Time එක අඩු කරලා, User Experience එක වැඩි දියුණු කරන්න මේ Concepts කොච්චර වැදගත්ද කියලා දැන් ඔයාලට තේරෙන්න ඇති. විශේෂයෙන්ම, next/dynamic කියන feature එක පාවිච්චි කරලා, විශාල components අවශ්‍ය වෙලාවට විතරක් load කරගන්න හැටි සහ @next/bundle-analyzer පාවිච්චි කරලා bundle එක analyze කරගන්න හැටිත් අපි බැලුවා.

මතක තියාගන්න, හොඳ performance එකක් කියන්නේ හොඳ User Experience එකක් සහ හොඳ SEO එකක් කියන එකයි. ඒ නිසා, මේවා ඔබේ Next.js Project වලට apply කරලා බලන්න. විශේෂයෙන්ම, Production Project එකකට deploy කරන්න කලින්, ඔබේ bundle size එක analyse කරන එක ගොඩක් වැදගත්.

මේ ගැන ඔයාලගේ අදහස්, ප්‍රශ්න, නැත්නම් ඔයාලගේ Projects වලදී මේවා පාවිච්චි කරලා ලබපු අත්දැකීම් පහළින් Comment කරන්න. අපි කතා කරමු! තවත් මේ වගේම වැදගත් Tutorial එකකින් හමුවෙමු! සුභ දවසක්! ✨