Kodėl verta pereiti prie App Router
Kai Next.js komanda pristatė App Router kaip stabilią funkciją 13.4 versijoje, daugelis kūrėjų nusprendė palaukti. Ir tai buvo protinga – naujos technologijos pradžioje visada būna grublėtų kampų. Bet dabar, su Next.js 14, situacija kardinaliai pasikeitė. App Router tapo ne tik stabilesnis, bet ir žymiai greitesnis, o ekosistema pagaliau suspėjo prisitaikyti.
Pirmiausia, App Router leidžia naudoti React Server Components – tai ne tik naujas buzzword’as, bet realus būdas sumažinti JavaScript bundle’o dydį ir pagreitinti puslapio įkėlimą. Antra, naujasis routing’as yra intuityvesnis – katalogų struktūra tiesiogiai atspindi URL struktūrą, o specialūs failai kaip layout.tsx ar loading.tsx daro kodą daug organizuotesnį.
Bet svarbiausia – jei kuriate naują projektą, Pages Router jau atrodo kaip praeitis. Dokumentacija, nauji pavyzdžiai, bendruomenės dėmesys – viskas sukasi aplink App Router. Taip, migracija reikalauja pastangų, bet tai investicija į ateitį, ne tik į madingą technologiją.
Kas iš tikrųjų keičiasi
Pirmą kartą susidūrus su App Router, gali atrodyti, kad viskas pasikeitė. Bet realybėje daugelis koncepcijų išlieka tos pačios – tik jų implementacija skiriasi. Routing’as vis dar veikia pagal failų sistemą, tik dabar naudojami katalogai su specialiais failais, o ne atskiri failai kaip anksčiau.
Vienas didžiausių pokyčių – tai Server Components kaip default’as. Pages Router’yje visi komponentai buvo klientiniai, nebent naudojote getServerSideProps ar getStaticProps. Dabar situacija atvirkščia – visi komponentai yra serveriniai, nebent aiškiai pažymite juos su 'use client' direktyva. Tai iš pradžių gali suklaidinti, bet greitai suprasite, kad tai daug logiškesnis požiūris.
Data fetching’as taip pat pasikeitė. Atsisveikinome su getServerSideProps, getStaticProps ir getInitialProps. Vietoj to, tiesiog naudojate async/await tiesiogiai komponente. Skamba paprasčiau? Taip ir yra. Bet yra niuansų – pavyzdžiui, kaip cache’inti duomenis ar kaip elgtis su dinaminiais parametrais.
Nuo ko pradėti migraciją
Geriausia žinia – jums nereikia migruoti visko iš karto. Next.js 14 puikiai palaiko abi routing sistemas viename projekte. Tai reiškia, kad galite migruoti palaipsniui, puslapį po puslapio, o tai yra didžiulis palengvėjimas dideliems projektams.
Pradėkite nuo paprasčiausio puslapio. Tikrai ne nuo to, kuris turi sudėtingą autentifikaciją, daug API route’ų ir sąveikauja su trimis skirtingomis duomenų bazėmis. Pasirinkite kažką paprasto – gal „Apie mus” puslapį ar blog’o straipsnio šabloną. Tai leis jums suprasti naująją sistemą be didelio streso.
Štai kaip atrodo paprasčiausias migracijos pavyzdys. Senasis Pages Router puslapis:
„`javascript
// pages/about.js
export default function About() {
return
}
„`
Naujasis App Router puslapis:
„`javascript
// app/about/page.tsx
export default function About() {
return
}
„`
Matote? Pats komponentas identiškas. Skirtumas tik failo vietoje ir pavadinime. Bet kai pradėsite naudoti sudėtingesnes funkcijas, skirtumai taps akivaizdesni.
Layout’ai ir nested routing’as
Viena geriausių App Router savybių – tai layout’ų sistema. Pages Router’yje, jei norėjote turėti bendrą layout’ą keliems puslapiams, turėjote naudoti _app.js arba kurti custom wrapper’ius. Dabar viskas daug paprasčiau ir lankstesčiau.
Layout’as yra komponentas, kuris „apvynioja” visus puslapius tam tikrame kataloge ir visuose jo subkataloguose. Pavyzdžiui, jei turite app/dashboard/layout.tsx, jis bus naudojamas visiems puslapiams, esantiems dashboard kataloge.
Štai praktinis pavyzdys:
„`typescript
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
)
}
„`
Gražiausia, kad layout’ai gali būti nested – galite turėti root layout’ą, dashboard layout’ą, ir dar gilesnį settings layout’ą. Kiekvienas lygis prideda savo wrapper’į, ir React automatiškai optimizuoja re-rendering’ą, kad tik pasikeitusi dalis būtų atnaujinama.
Server ir Client komponentai – kur brėžti liniją
Tai vieta, kur daugelis kūrėjų susiduria su didžiausiais iššūkiais. Koncepcija paprasta: Server Components renderinami serveryje ir niekada nepasiekia kliento, o Client Components veikia naršyklėje. Bet praktikoje reikia gerai pagalvoti, kur dėti 'use client' direktyvą.
Pagrindinis principas – naudokite Server Components kiek įmanoma. Jie greitesni, mažesni, ir gali tiesiogiai pasiekti duomenų bazes ar API be jokių security rizikų. Client Components naudokite tik tada, kai tikrai reikia interaktyvumo – event handler’ių, state’o, browser API, ar React hooks.
Štai tipinė klaida, kurią mačiau ne kartą:
„`typescript
// BLOGAI – visas puslapis padaromas client component dėl vieno mygtuko
‘use client’
export default function ProductPage() {
const [liked, setLiked] = useState(false)
return (
Produktas
)
}
„`
Geriau būtų atskirti interaktyvią dalį:
„`typescript
// app/product/page.tsx (Server Component)
import { LikeButton } from ‘./LikeButton’
export default function ProductPage() {
return (
Produktas
)
}
// app/product/LikeButton.tsx (Client Component)
‘use client’
import { useState } from ‘react’
export function LikeButton() {
const [liked, setLiked] = useState(false)
return (
)
}
„`
Dabar tik mažas mygtukas yra client component, o visas kitas turinys lieka serveryje. Tai reiškia mažesnį JavaScript bundle’ą ir greitesnį puslapio įkėlimą.
Data fetching naujuoju būdu
Atsisveikinimas su getServerSideProps iš pradžių gali atrodyti bauginantis, bet naujas būdas iš tikrųjų yra paprastesnis. Tiesiog naudojate async/await tiesiogiai komponente:
„`typescript
// app/posts/page.tsx
async function getPosts() {
const res = await fetch(‘https://api.example.com/posts’)
return res.json()
}
export default async function PostsPage() {
const posts = await getPosts()
return (
{post.title}
))}
)
}
„`
Bet čia yra svarbus niuansas – kaip Next.js žino, ar cache’inti šiuos duomenis, ar ne? Pages Router’yje tai buvo aiškiai nurodoma per getStaticProps vs getServerSideProps. Dabar Next.js naudoja fetch API su papildomomis opcijomis:
„`typescript
// Cache’inti amžinai (kaip getStaticProps)
fetch(‘https://api.example.com/posts’, { cache: ‘force-cache’ })
// Niekada necache’inti (kaip getServerSideProps)
fetch(‘https://api.example.com/posts’, { cache: ‘no-store’ })
// Revalidate kas 60 sekundžių
fetch(‘https://api.example.com/posts’, { next: { revalidate: 60 } })
„`
Jei nenaudojate fetch (pavyzdžiui, naudojate Prisma ar kitą ORM), galite kontroliuoti cache’inimą per route segment config:
„`typescript
export const dynamic = ‘force-dynamic’ // kaip getServerSideProps
export const revalidate = 60 // revalidate kas 60 sek
„`
API routes ir Server Actions
API routes vis dar egzistuoja App Router’yje, bet jie dabar vadinasi Route Handlers ir yra šiek tiek kitaip organizuoti. Vietoj pages/api, dabar naudojate app/api su specialiu route.ts failu.
Štai kaip migruoti paprastą API endpoint’ą:
„`typescript
// Senasis būdas: pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: ‘Labas’ })
}
// Naujasis būdas: app/api/hello/route.ts
export async function GET() {
return Response.json({ message: ‘Labas’ })
}
„`
Bet tikroji naujovė – tai Server Actions. Tai funkcijos, kurias galite iškviesti tiesiogiai iš formos ar event handler’io, ir jos automatiškai vykdomos serveryje. Nereikia kurti atskiro API endpoint’o!
„`typescript
// app/actions.ts
‘use server’
export async function createPost(formData: FormData) {
const title = formData.get(‘title’)
// Čia galite tiesiogiai rašyti į duomenų bazę
await db.post.create({ data: { title } })
}
// app/new-post/page.tsx
import { createPost } from ‘../actions’
export default function NewPost() {
return (
)
}
„`
Tai atrodo kaip magija, bet iš tikrųjų Next.js automatiškai sukuria API endpoint’ą už jūsų. Ir viskas veikia net be JavaScript – progressive enhancement!
Kas toliau ir kaip išvengti spąstų
Migracija į App Router nėra sprint’as – tai marathon’as. Ir tai visiškai normalu. Daugelis projektų veiks su hibridine sistema mėnesius, o gal net metus. Svarbiausia – nepulti į paniką ir neskubėti.
Keli praktiniai patarimai, kurie man padėjo:
Pirma, sukurkite aiškų planą. Nesistenkite migruoti visko iš karto. Identifikuokite puslapius pagal sudėtingumą ir pradėkite nuo paprasčiausių. Tai leis jums išmokti naują sistemą be didelės rizikos.
Antra, investuokite laiko į TypeScript. App Router su TypeScript yra daug malonesnis patyrimas – automatinis type inference’as route parametrams, geresnė IDE parama, mažiau klaidų runtime’e.
Trečia, neskubėkite visur dėti 'use client'. Tai pati dažniausia klaida. Jei kažkas neveikia, pirmiausia pagalvokite, ar tikrai reikia client component’o, ar gal galite perorganizuoti kodą.
Ketvirta, atidžiai stebėkite bundle size’ą. Vienas iš pagrindinių App Router privalumų – mažesnis JavaScript bundle’as. Bet jei netinkamai naudojate client components, galite gauti priešingą efektą.
Ir paskutinis patarimas – nebijokite eksperimentuoti. Sukurkite test branch’ą, pabandykite migruoti vieną puslapį, pažiūrėkite kaip jaučiasi. Next.js dokumentacija dabar yra puiki, o bendruomenė labai aktyvi. Jei užstrigsite, tikrai rasite pagalbos.
App Router nėra tobulas – vis dar yra edge case’ų, kai Pages Router būtų paprastesnis sprendimas. Bet bendra kryptis aiški – tai ateitis Next.js ekosistemoje. Ir kuo anksčiau pradėsite mokytis, tuo lengviau bus ateityje. Nebijokite klysti, eksperimentuokite, ir svarbiausia – mėgaukitės procesu. Galiausiai, tai tik įrankiai, kurie turi padėti mums kurti geresnes aplikacijas.
