Next.js _app.js | Global Layouts | Sinhala Tutorial | NextJS Guide SL

ආයුබෝවන් හැමෝටම! 👋 අද අපි කතා කරන්න යන්නේ Next.js වලින් අපේ Web Application එක තව ටිකක් Smart සහ Efficient කරගන්න පුළුවන් සුපිරි feature එකක් ගැන. ඒ තමයි _app.js
file එක සහ ඒකෙන් Global Layouts හදන හැටි. Next.js එක්ක වැඩ කරනවා නම්, මේක නැතුව Web App එකක් හදනවා කියන්නේ පොඩි අඩුවක් වගේ තමයි දැනෙන්නේ. ඒ නිසා අපි මේක හරියටම ඉගෙන ගමු.
ඇයි මේ _app.js
අපිට වැදගත්?
- අපේ Application එකේ හැම Page එකකටම පොදු Layout එකක් (උදා: Header, Footer, Navigation Bar) එකතු කරන්න පුළුවන්. ඒ කියන්නේ, එක තැනකින් වෙනස් කළොත්, හැම තැනටම බලපානවා. පට්ට නේද?
- Page එකක් navigate වෙනකොටත් (උදා: Home page එකෙන් About page එකට යනකොට) Layout එක ඒ විදියටම තියාගන්න පුළුවන් (persisting layout between page changes). ඒකෙන් user experience එක ගොඩක් හොඳ වෙනවා.
- Global CSS files inject කරන්න. ඒ කියන්නේ, අපේ App එක පුරාම වැඩ කරන Styles එක තැනකින් control කරන්න පුළුවන්.
- Data fetching logic එකක් හෝ state management library එකක් (Redux, Zustand වගේ) App එකටම initialize කරන්න.
අද මේ Guide එකෙන් අපි, _app.js
කියන්නේ මොකක්ද, ඒක කොහොමද වැඩ කරන්නේ, ඒක පාවිච්චි කරලා Global Layout එකක් හදාගන්නේ කොහොමද වගේ දේවල් Practical විදියටම කරලා බලමු. එහෙනම්, අපි පටන් ගමු!
Next.js වල _app.js
කියන්නේ මොකක්ද?
සරලවම කිව්වොත්, _app.js
කියන්නේ Next.js Application එකක හැම Page එකක්ම Initialize වෙන තැන. ඒ කියන්නේ, ඔබ හදන ඕනෑම Page Component එකක් render වෙන්න කලින්, _app.js
file එකේ define කරලා තියෙන Component එක ඇතුළේ තමයි render වෙන්නේ. Next.js Application එකක් load වෙනකොට, මුලින්ම load වෙන්නේ මේ _app.js
file එකයි.
Next.js framework එක විසින් මේ _app.js
file එකට props දෙකක් යවනවා:
Component
: මේක තමයි දැනට active වෙලා තියෙන Page Component එක. උදාහරණයක් විදියට ඔබ/about
කියන URL එකට ගියොත්,Component
prop එකට ලැබෙන්නේpages/about.js
file එකේ තියෙන Component එක.pageProps
: මේක තමයිgetStaticProps
හෝgetServerSideProps
වගේ data fetching functions වලින් අදාළ Page Component එකට යවන props.
සාමාන්යයෙන්, ඔබ Next.js project එකක් පටන් ගත්තාම, pages/_app.js
file එකක් auto-generate වෙලා තියෙනවා මේ වගේ:
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default MyApp;
දැන් බලන්න, මේක ඇතුළේ තමයි අපේ Component
එක render වෙන්නේ. ඒ කියන්නේ, අපිට ඕන නම්, මේ <Component {...pageProps} />
වටේට අපිට ඕන කරන ඕනෑම wrapper Component එකක් දාන්න පුළුවන්. අන්න එතනින් තමයි Global Layout එකක් කියන concept එක එන්නේ.
Global Layout එකක් හදමු! (Practical Example)
දැන් අපි බලමු _app.js
පාවිච්චි කරලා කොහොමද අපේ Next.js Application එකට පොදු Header එකක් සහ Footer එකක් එක්ක Global Layout එකක් හදාගන්නේ කියලා.
පියවර 1: Layout Components හදාගනිමු
මුලින්ම, අපි අපේ Header, Footer, සහ Layout Component එක හදාගනිමු. Project root එකේ components
කියලා folder එකක් හදලා ඒක ඇතුළේ මේ files ටික හදන්න.
components/Header.js
import Link from 'next/link';
function Header() {
return (
<header style={{ background: '#333', color: 'white', padding: '1rem', textAlign: 'center' }}>
<nav>
<Link href="/" style={{ color: 'white', margin: '0 10px' }}>Home</Link>
<Link href="/about" style={{ color: 'white', margin: '0 10px' }}>About</Link>
<Link href="/contact" style={{ color: 'white', margin: '0 10px' }}>Contact</Link>
</nav>
<h1>අපේ සුපිරි Web App එක</h1>
</header>
);
}
export default Header;
components/Footer.js
function Footer() {
return (
<footer style={{ background: '#f0f0f0', padding: '1rem', textAlign: 'center', marginTop: '20px' }}>
<p>© {new Date().getFullYear()} Our Awesome App. All rights reserved.</p>
</footer>
);
}
export default Footer;
දැන් මේ Header එකයි, Footer එකයි wrap කරන්න Layout Component එකක් හදමු.
components/Layout.js
import Header from './Header';
import Footer from './Footer';
function Layout({ children }) {
return (
<div>
<Header />
<main style={{ minHeight: '70vh', padding: '20px' }}>
{children}
</main>
<Footer />
</div>
);
}
export default Layout;
මේ Layout Component එකට children
කියන prop එකක් ලැබෙනවා. මේ children
එක තමයි අපේ එක් එක් Page Components වෙන්නේ. හරිද?
පියවර 2: _app.js
එක update කරමු
දැන් අපි අපේ pages/_app.js
file එකේ වෙනසක් කරමු. ඒක ඇතුළේ <Layout>
Component එකට <Component {...pageProps} />
එක wrap කරමු.
pages/_app.js
import '../styles/globals.css';
import Layout from '../components/Layout';
function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
export default MyApp;
අන්න එච්චරයි! දැන් ඔබේ Next.js Application එකේ ඕනෑම page එකක් load කරලා බලන්න. හැම page එකකම උඩින් Header එකයි, යටින් Footer එකයි automatically එනවා. Page එකෙන් Page එකට යනකොටත් Layout එක ඒ විදියටම තියෙනවා මිසක් reload වෙන්නේ නැහැ. සුපිරි වැඩක් නේද?
පියවර 3: Pages කිහිපයක් හදමු
මේ Layout එක වැඩ කරනවද කියලා බලන්න Pages කිහිපයක් හදමු.
pages/index.js
export default function Home() {
return (
<div>
<h2>Home Page එකට සාදරයෙන් පිළිගනිමු!</h2>
<p>මේක තමයි අපේ App එකේ Home page එක. Global Layout එක වැඩ කරනවා.</p>
</div>
);
}
pages/about.js
export default function About() {
return (
<div>
<h2>About Us Page එක</h2>
<p>අප ගැන තොරතුරු මෙතනින් දැනගන්න පුළුවන්.</p>
</div>
);
}
දැන් npm run dev
කරලා browser එකේ බලන්න. /
, /about
, /contact
වගේ pages වලට ගියාම Header එකයි Footer එකයි persist වෙනවා ද කියලා. එහෙම වෙනවා නම් වැඩේ සාර්ථකයි!
_app.js
සහ Global CSS
_app.js
file එක Global CSS styles add කරන්නත් පාවිච්චි කරන්න පුළුවන්. උදාහරණයක් විදියට, Next.js project එකක් හදනකොට automatically create වෙන styles/globals.css
file එක _app.js
එකට import කරලා තියෙන්නේ මේ නිසයි.
import '../styles/globals.css';
// ...rest of the code
මේ විදියට CSS import කළාම, ඒ styles Application එකේ හැම Page එකකටම apply වෙනවා. SCSS/Sass වගේ CSS pre-processors පාවිච්චි කරනවා නම්, ඒකත් මේ විදියටම import කරන්න පුළුවන් (next.config.js
file එකේ අවශ්ය configurations එක්ක).
වැදගත් දේවල් සහ Best Practices
_app.js
vs _document.js
Next.js වල තව විශේෂ file එකක් තියෙනවා, ඒ තමයි _document.js
. මේ දෙක ගොඩක් අය පටලවා ගන්නවා. ඒ නිසා අපි පැහැදිලිවම මේක තේරුම් ගමු.
_app.js
: මේක Client Side සහ Server Side දෙකේම run වෙනවා. Application එකේ common Component wrappers, Global Styles, State management initialization වගේ දේවල් වලට තමයි පාවිච්චි කරන්නේ._document.js
: මේක Server Side එකේ විතරයි run වෙන්නේ. HTML document එකේ මූලික structure එක customize කරන්න (<html>
,<body>
, custom fonts, meta tags වගේ) තමයි මේක පාවිච්චි කරන්නේ.<body>
tag එක ඇතුළට දාන කිසිම application logic එකක්_document.js
එකට දාන්න එපා. ඒ වගේම,_document.js
එක ඇතුළේ Event Handlers හෝ State වගේ දේවල් වැඩ කරන්නේ නැහැ. ඒ දේවල් වලට_app.js
තමයි පාවිච්චි කරන්නේ.
සරලව කිව්වොත්, _document.js
කියන්නේ HTML boilerplate එක. _app.js
කියන්නේ ඒ boilerplate එක ඇතුළේ අපේ App එක දුවන තැන.
Error Handling
ඔබට _app.js
ඇතුළේ global error handling (උදා: Sentry වගේ tools integrate කරන්න) කරන්නත් පුළුවන්. ComponentDidCatch
lifecycle method එක (Class Component එකක් නම්) හෝ ErrorBoundary
component එකක් පාවිච්චි කරලා මේක කරන්න පුළුවන්.
// Example of an Error Boundary (can be a separate component)
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.error("Caught error in ErrorBoundary:", error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>අයියෝ! මොකක් හරි වැරැද්දක් වුණා.</h1>;
}
return this.props.children;
}
}
// In _app.js
// import ErrorBoundary from '../components/ErrorBoundary';
// ...
// function MyApp({ Component, pageProps }) {
// return (
// <Layout>
// <ErrorBoundary>
// <Component {...pageProps} />
// </ErrorBoundary>
// </Layout>
// );
// }
State Persistence
අපි _app.js
පාවිච්චි කරලා Global Layout එකක් හැදුවම, Layout එක ඇතුළේ තියෙන Component වල state, pages අතරේ navigate වෙනකොටත් persist වෙනවා. ඒ කියන්නේ, Layout එකේ තියෙන Component එකක state එකක් වෙනස් වුණොත්, ඔබ page එකක් navigate කළත් ඒ state එක එහෙම්මම තියෙනවා.
උදාහරණයක් විදියට, ඔබ Layout එකේ Header එක ඇතුළේ Search Bar එකක් හැදුවොත්, ඒ Search Bar එකේ type කරන text එක, pages අතරේ මාරු වෙනකොටත් delete වෙන්නේ නැහැ. මේක තමයි "persisting layout state" කියන්නේ. මේක ගොඩක් වෙලාවට අපිට වාසියක් වුණත්, සමහර වෙලාවට debug කරන්න ටිකක් අමාරු වෙන්න පුළුවන්, මොකද pages re-render වුණත්, Layout Component එක re-render වෙන්නේ නැති නිසා. ඒ නිසා මේ ගැන අවධානයෙන් ඉන්න ඕනේ.
Global Context/State Management
React Context API, Redux, Zustand වගේ state management libraries Next.js Application එකටම apply කරන්න හොඳම තැන තමයි _app.js
. ඒකෙන් පුළුවන් මුළු App එකටම පොදු state එකක් හදන්න.
// In pages/_app.js
import '../styles/globals.css';
import Layout from '../components/Layout';
import { UserProvider } from '../contexts/UserContext'; // Assuming you have a UserContext
function MyApp({ Component, pageProps }) {
return (
<UserProvider>
<Layout>
<Component {...pageProps} />
</Layout>
</UserProvider>
);
}
export default MyApp;
නිගමනය
ඉතින් යාලුවනේ, _app.js
කියන්නේ Next.js වලින් Web Application එකක් හදනකොට අපිට ලැබෙන සුපිරි power tool එකක්. මේක හරියට පාවිච්චි කළොත් Application එකේ maintainability, user experience, සහ performance ගොඩක් වැඩි කරගන්න පුළුවන්. Global Layouts, CSS management, State management initialization, Error handling වගේ ගොඩක් දේවල් එක තැනකින් control කරන්න මේක අපිට අවස්ථාව දෙනවා.
අපි අද ඉගෙන ගත්ත දේවල් ටික ආයෙත් මතක් කරගමු:
_app.js
කියන්නේ Application එකේ හැම Page එකක්ම initialize වෙන තැන.Component
සහpageProps
කියන props දෙක මේකට ලැබෙනවා.- Header, Footer වගේ දේවල් එක්ක Global Layout එකක්
_app.js
ඇතුළේ define කරන්න පුළුවන්. - Global CSS import කරන්නත් මේක තමයි හොඳම තැන.
_app.js
සහ_document.js
අතර වෙනස හොඳින් තේරුම් ගන්න.
දැන් ඔබ _app.js
ගැන හොඳ අවබෝධයක් ඇති කියලා මම හිතනවා. මේක ඔබේ Next.js project වලට implement කරලා බලන්න. මොකද, theory විතරක් මදි, practice එක තමයි වැදගත්. ඔබේ අත්දැකීම් කොහොමද, මොන වගේ Global Layouts ද ඔබ හැදුවේ කියලා පහළින් comment එකක් දාන්න. අපි ඒ ගැන කතා කරමු!
තවත් අලුත් දෙයක් අරගෙන ඉක්මනටම හම්බෙමු! සුභ දවසක්! 👋