Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Next.js App Router

Next.js App Router

Yosuke Kurami

April 30, 2024
Tweet

More Decks by Yosuke Kurami

Other Decks in Programming

Transcript

  1. About me - id: @Quramy (GitHub, X) - ॴଐ: גࣜձࣾϦΫϧʔτ

    
 (ΞϓϦέʔγϣϯιϦϡʔγϣϯ G) - ৬छ: ϑϩϯτΤϯυΤϯδχΞ
  2. Next.js App Router is Կ - Next.js ʹ͓͚Δ৽͍͠ΞϓϦέʔγϣϯ։ൃελΠϧͷ͜ͱ - ඪ४Ͱ

    React Server Components (ҎԼ RSC) ٴͼ Server Actions (ҎԼ SA) ͕ར༻Մೳ
  3. App Router ࠾༻ʹࢸͬͨഎܠ - ର৅Ҋ݅: ݁ࠗྖҬ(θΫγΟΛ΍͍ͬͯΔͱ͜Ζ) ʹ͓͚Δ৽نࣄۀ - ಉྖҬͷଞϓϩμΫτͰ͸ Next.js

    Pages Router Λ࢖ͬͨ։ൃΛߦͬ ͍ͯΔͨΊɺApp Router ͷ࢖͍৺஍Λຯݟͯ͠Έ͍ͨ 
 → Quramy ΋Ұຕט·ͤͯ΋Β͏͜ͱʹ - ։ൃظؒ: 2023.6݄ - 2023.12݄ - ϑϩϯτΤϯυن໛: ໿40ϖʔδ, 180 Component
  4. App Router ʹର͢Δॴײ 2023.6 ʙ 2023.12 ·Ͱͷ໿̒ϲ݄ؒͷ։ൃظؒΛ௨ͨ͡ App Router ʹର

    ͢Δॴײ - ϙδςΟϒ: - Data Fetching ؔ࿈ʹ͍ͭͯɺैདྷΑΓ΋௚ײతͳ࣮૷͕ՄೳͰ͋Δɻ 
 ʮBFF ͷͨΊͷ API ΤϯυϙΠϯτʯͳͲͷதؒ੒Ռ෺ʹ͔͔Δઃ ܭɾ࣮૷ίετ͕࡟ݮ͞ΕΔ - νϡʔχϯάΛߦ͍ͬͯͳ͍ঢ়ଶͰ΋ɺे෼ʹߴ଎ͳΞϓϦέʔγϣ ϯΛߏஙͰ͖ͨ
  5. App Router ʹର͢Δॴײ 2023.6 ʙ 2023.12 ·Ͱͷ໿̒ϲ݄ؒͷ։ൃظؒΛ௨ͨ͡ App Router ʹର

    ͢Δॴײ - ωΨςΟϒ: - पลΤίγεςϜ(e.g. Styling, UI Lib, Form lib, ςετ) ͕ RSC ʹ௥͍ ͍͍ͭͯͳ͍ - ͱ͸͍͑χʔζ͸͋ΔͷͰɺ͕࣌ؒղܾ͍ͯ͘͠ྨͷ࿩ͱࢥ͏
  6. શମతͳΞʔΩςΫνϟ CloudFront EKS Cluster k8s namespace Frontend SVC Backend API

    SVC RDS Next.js Spring Boot AWS Cloud - Πϯϑϥ: AWS (EKS) - Backend API: Spring Boot - Frontend: Next.js (ϝΠϯϢʔεέʔε͸ SSR) 

  7. ϑϩϯτΤϯυελοΫ ओͳ Dependencies Data Fetching RSC / Server Actions HTTP

    Client WHATWG Fetch (undichi) API Client Open API Generator ελΠϦϯά (CSS) CSS Modules UI ϥΠϒϥϦ - UI State Management jotai Form ϥΠϒϥϦ - Scaffolding hygen Component Χλϩά @storybook/react Unit Testing Jest Component Testing Jest + RTL E2E Testing Playwright
  8. ϑϩϯτΤϯυελοΫ Data Fetching App Router ͷ࠾༻͸ Data Fetching ʹ RSC

    / SA Λ༻͍Δ͜ͱΛҙຯ͍ͯ͠ Δ(ٯʹ͜ΕΒΛ࢖Θͳ͍ͷͰ͋Ε͹ɺٕज़ݕূͷҙຯ͕ബΕͯ͠·͏) - ʮσʔλΛදࣔ͢ΔʯʮσʔλΛߋ৽͢ΔʯͷͲͪΒͰ͋ͬͯ΋ɺSC / SA Ͱ׬݁͢Δ - SWR ΍ tRPCɺApollo Client ͷΑ͏ͳ Data Fetch ϥΠϒϥϦΛෆཁͱͰ ͖ΔͨΊɺඪ४Խָ͕ - SC / SA ͱ΋ʹʮReact ͷ࢖͍ํʯͷ࿩Ͱ͔͠ͳ͍ɻԾʹ Next.js Ͱͳ ͔ͬͨͱͯ͠΋Ԡ༻ͷޮ͘஌ࣝͱͳΔ͸ͣ
  9. ϑϩϯτΤϯυελοΫ ελΠϦϯά(CSS) Runtime CSS in JS ܥ͕ݢฒΈ RSC Ͱಈ࡞͠ͳ͍ͨΊɺݕ౼࣌఺(2023.6݄) Ͱ࠷΋ރΕ͍ͯͨ

    CSS Modules Λ࠾༻ - ΋͍͠·બ୒͢ΔͷͰ͋Ε͹ Zero Runtime CSS in JS Λ΋͏গ͠ݕ౼͠ ͍͔ͯͨ΋ - ϏϧυπʔϧνΣʔϯ͕ա౉ظͰ͋Δ͜ͱΛߟ͑Δͱ PandaCSS ͷΑ͏ ͳɺτϥϯεύΠϧʹ৵ऻ͠ͳ͍Ξϓϩʔνͷ΋ͷΛબͼ͍ͨ
  10. ϑϩϯτΤϯυελοΫ UI State Management State management ʹ jotai Λ࠾༻ -

    RSC Ͱ͸খཱࣗ͘͞෼ࢄͳ CC ಉ͕࢜૬ޓʹ࿈ܞ͢ΔੈքʹͳΔͷͰ͸ʁ 
 ͱ͍͏༧ײ͕͋ͬͨ - ྫ: Component X ͕ Viewport ʹަࠩ࣌ɺ Component A ͷදࣔঢ়ଶ͕มԽ - Pages Router ͷ৔߹ɺX ͱ A ྆ํΛؚΜͩҰݸͷComponent ͱͯ͠ه ड़͍ͯͨ͠Γ͢Δ => useState ͚ͩͰԿͱ͔ͯ͠͠·͏͜ͱ΋Ͱ͖ͨ - App Router Ͱ X / A ͕ CC ͱͯ͠෼ࢄ഑ஔ͞ΕΔͱɺͦ͏͸͍͔ͳ͘ͳΔ ͷͰ͸?
  11. Page Component Component A ෦෼ Component X ෦෼ const [hoge,

    setHoge] = useState(true) hoge Λࢀর setHoge Λࢀর Page Component (Async SC) Component A (CC) Component X (CC) hoge Λࢀর hoge Λߋ৽ ͜ͷ component Λ SC ʹ͢ΔͷͰ͋Ε͹ Hooks ͸ར༻Ͱ͖ͳ͍ State ͢΂͕ͯ CC ͷੈք SC / CC Λؾʹ͢Δੈք ※ ͨͩͷσʔλදࣔ෦෼ ※ ͨͩͷσʔλදࣔ෦෼ (SC) ϑϩϯτΤϯυελοΫ UI State Management
  12. ϑϩϯτΤϯυελοΫ UI State Management - jotai + Next.js Λ࢖͏্Ͱͷॾ஫ҙ: -

    SSR ࣌ʹ atomFamily ͕ϝϞϦϦʔΫ͢ΔͨΊɺ͓૟আ͕ඞཁ 
 https://jotai.org/docs/utilities/family#caveat-memory-leaks import { type Atom } from 'jotai' import { atomFamily as atomFamilyiDelegate } from 'jotai/utils' export function atomFamily<Param, AtomType extends Atom<unknown>>( initializeAtom: (param: Param) => AtomType, areEqual?: (a: Param, b: Param) => boolean, ) { const delegate = atomFamilyiDelegate<Param, AtomType>(initializeAtom, areEqual) return new Proxy(delegate, { apply: (createAtom, _, [param]: [Param]) => { if (typeof document !== 'undefined') { return createAtom(param) } const atomItem = createAtom(param) queueMicrotask(() => createAtom.remove(param)) return atomItem }, }) }
  13. ϑϩϯτΤϯυελοΫ ͦͷଞ Կ΋࠾༻͠ͳ͔ͬͨܥ౷ - Form ϥΠϒϥϦ - ͍ΘΏΔ react-hook-form ͳͲͷܥ౷

    
 ը໘ೖྗཁ͕݅ϥδΦϘλϯ/νΣοΫϘοΫεͷΈɻͦ΋ͦ΋ϥΠϒϥϦ͕ෆཁͳ ϨϕϧͩͬͨΊ - UI Component ϥΠϒϥϦ - બఆ͍ͯ͠Δ༨༟͕ͳ͔ͬͨͱ͍͏ফۃతͳཧ༝ 
 RSC ͱ૬ੑͷྑ͍ UI Component ϥΠϒϥϦ͕͋Ε͹஌Γ͍ͨͰ͢ʂ
  14. ύϑΥʔϚϯε/Ωϟογϡઓུ ͳͥ Next.js ͷ Cache Λར༻͍ͯ͠ͳ͍͔: - ΞϓϦέʔγϣϯಛੑ্ɺData / Full

    Route Cache ʹର͢Δ hit rate ͕ߴ͘ͳΒͳ͍͜ͱ ͕Θ͔͓ͬͯΓɺΩϟογϡΛؤுΔࢫຯ͕গͳ͔ͬͨ - EKS Pod ؒͰ Cache Λڞ༗͢Δ࢓૊Έʹ͍ͭͯະݕ౼ - σϑΥϧτͰ͸ Data Cache, Full Route Cache ͸ϑΝΠϧγεςϜ্ʹӬଓԽ͞Ε Δɻ͢ͳΘͪ Container Local ͳ σʔλͱͳΔ 
 ͜ͷͨΊɺ Custom Cache Handler + ElastiCache ͳͲΛ࢖ͬͯɺӬଓԽํࣜΛ AWS ϑϨϯυϦͳ΋ͷʹมߋ͢Δඞཁ͕͋Δ - https://nextjs.org/docs/app/api-reference/next-con fi g-js/ incrementalCacheHandlerPath
  15. ύϑΥʔϚϯε/ଌఆ Next.js Cache ͸ফۃతͰ͋ͬͯ΋ɺ࣮ͦͦ͜͜༻తͳύϑΥʔϚϯε ಉྖҬͰͷ Pages Router ͳϓϩμΫτͱൺֱ͢Δͱɺ΍͸Γ First Load

    JavaScript ͷϘϦϡʔϜʹѹ౗తͳ͕ࠩग़Δ 
 (App Router Ҋ݅͸ґଘϥΠϒϥϦ͕গͳ͍ͨΊɺʮͦΕ͸ͦ͏ʯͱ΋ݴ͑Δ͚Ͳ) - App Router Ҋ݅: ໿ 200 kB 
 Pages Router Ҋ݅: ໿1,720 kB
  16. ࡉཻ౓ͳςετ - શͯͷ Component Ͱ Storybook ͷ ϑΝΠϧ (.stories) ࡞੒Λڧ੍͓ͯ͘͠

    - RSC ͷςετํ๏ʹ͍ͭͯ: - ඇಉظͳ SC ʹ͍ͭͯ͸ɺ Container / Presentation Ͱ෼ׂ͓͖ͯ͠ɺStorybook ΍ jest Ͱ࣮ߦ͞ΕΔͷ͸ Presentational ͳ෦෼ͷΈʹ͓ͯ͘͠ 
 ※ ৄࡉ: React Server Component ͷςετͱ Container / Presentation Separation - ͢΂ͯͷ Story ʹରͯ͠ɺjest + RTL Ͱ composeStories & render ͷಈ࡞อূΛ͓ͯ͘͠ - Storybook 8 ͷ experimentalRSC ͸࢖͍ͬͯͳ͍ 
 ※ ։ൃ౰ॳ͸ Storybook 7.x ͩͬͨͱ͍͏ͷ΋͋Δ͕ɺSC Λ ແཧ΍Γؾຯʹ CC ͱͯ͠ ѻ͍ͬͯΔ͜ͱࣗମ͕Πέͯͳ͍ͱࢥ͍ͬͯΔͨΊ
  17. ૈཻ౓ͳςετ - Playwright ʹΑΔ E2E Λ࣮ࢪ - DB ͷ Seed

    + Spring Boot ͷىಈ + next start Λ͢΂ͯ CI Ͱ Service ࣮ߦ ͢ΔΑ͏ʹ͍ͯ͠Δ - Pros: E2E ͱͯ͠͸ਖ਼͍࢟͠ - Cons: CI ͕ॏ͍ͨ. SA ΛҰ౓࣮ߦͯ͠͠·͏ͱ DB ͷঢ়ଶ͕มߋ͞ΕΔ ͨΊɺFlaky Λ౿ΜͰ΋ Playright ͰಉҰ URL ʹϦτϥΠͯ͠΋ҙຯ͕ແ ͍ - Next.js ͷ Experimental Test Proxy ͸ར༻͍ͯ͠ͳ͍
  18. ૈཻ౓ͳςετ - Next Server ͷڍಈͱີʹ࿈ಈ͢ΔՕॴ͸ E2E ଆͰಈ࡞Λ୲อ͢ΔΑ͏ ʹ͍ͯ͠Δ - ςετγφϦΦͷྫ:

    - લఏ: SA Ͱ revalidatePaths Λ༻͍ͯ Router Cache Λύʔδ͍ͯ͠Δ - γφϦΦ: ϖʔδදࣔ -> SA ࣮ߦͯ͠ը໘ભҠ -> ϒϥ΢βόοΫ - ֬ೝ؍఺: ϒϥ΢βόοΫޙͷදࣔͰ͸ Router Cache ͕࠷৽Խ͞Εͯ ͍Δ͔ʁ
  19. App Router ʹऔΓ૊Ή্Ͱॏཁͱ ࢥ͏͜ͱ - App Router Ҋ݅Λ௨ͯ͠গͣͭ͠ཧղ͖ͯͨ͜͠ͱୡ: - RSC

    ͷϝϯλϧϞσϧ - σʔλϑΣονͷཻ౓ - HTML / CSS ஌ࣝͷॏཁੑ
  20. RSC ͷϝϯλϧϞσϧ ·ͣ͸ϑϩϯτΤϯυͷ։ൃऀશһ͕ RSC ʹ೴ΛΞοϓσʔτ͢΂͖ - RSC (App Router) ͸

    Pages Router Ͱͷ SSR ͱຊ࣭తʹҙຯ͕ҟͳΔ - ʮSC ͸ࣄલܭࢉͰ͋ΔʯΛୟ͖ࠐΜͰ͓͘ - ࢀߟʹͳΔ΋ͷ - uhyo ͞Μͷهࣄ: https://zenn.dev/uhyo/articles/react-server- components-multi-stage
  21. σʔλϑΣονͷཻ౓ - Pages Router ࣌୅ʹʮࣄલॲཧʯʹ૬౰͍ͯͨ͠΋ͷ: 
 getServerSideProps or getStaticProps -

    ͜ΕΒ͸ɺPage ୯Ґͷ Component ʹ͔͠࡞༻Ͱ͖ͳ͔ͬͨ - → gSSP Ͱར༻͢Δ API ͷઃܭ͕ϢʔεέʔεʹҾ͖ͣΒΕΔ
  22. σʔλϑΣονͷཻ౓ - App Router Ͱ͸ SC ͕σʔλͷऔಘͱ͍͏ࣄલॲཧΛ୲͍ͬͯΔ - σʔλऔಘ͕ page

    ୯ҐͰ͋Δඞཁ͕ແ͍. ຤୺ͷ Component Ͱɺͦ ͷ Component ͕ඞཁͳσʔλΛ௚઀ϑΣονͰ͖Δ - Ϧιʔεࢤ޲ʹج͍ͮͨ API ઃܭͱ਌࿨͢Δ - ࡉཻ౓ API ͱ͓͍ͯͨ͠ํ͕ɺNext.js ͷ Data Cache ʹ΋ࡌͤ΍͍͢ ͸ͣ
  23. HTML / CSS ͷ஌ࣝ - HTML + CSS ͷ஌ࣝ͸ෆඞཁͳ CC

    Λ࡟ݮ͢Δ্Ͱ΋ॏཁ - ྫ: ΧϧʔηϧͬΆ͍ݟͨ໨ͷίϯϙʔωϯτ - CC ͷ JavaScript ॻ͔ͳͯ͘΋ɺCSS ͷ scroll-snap Ͱ࣮ݱͰ͖·͢Α Ͷʁ - https://web.dev/blog/interop-2022