nextjs - deptno/deptno.github.io GitHub Wiki
next.js
- client side cache λ₯Ό κ°μ§ server μμ λ°μμ¨ μ»΄ν¬λνΈλ€μ μ¬νμ©νλ€
- partial rendering
- client navigation μ΄ μΌμ΄λ κ²½μ° ν΄λΉ μ»΄ν¬λνΈ λΆλΆλ§μ μλ‘ κ·Έλ¦°λ€
- directory μ page.tsx κ° μμ΄μΌ λΌμ°ν μ΄ κ°λ₯ν΄μ§λ€
- route groups
-
(name)
directory - url ꡬ쑰μ μν₯μ μ£Όμ§ μκ³
layout
λ± κ³΅ν΅ μ»΄ν¬λνΈ μ¬μ©μ κ°λ₯νκ² νλ€ - λ€λ₯Έ route groups μ κ°μ λΌμ°νΈ(url) μ μμ±νλ κ²½μ° μλ¬λ‘ κ°μ£Όλλ€
- route groups κ°μ navigation μ full page load κ° λ°μνλ€
-
- dynamic route
-
/[name]/page.tsx
μ κ²½μ°({params}: {params: { name: string }})
μ λ°κ² λλ€ - catch all segments
-
/[...name]/page.tsx
name μ΄ νλμ λμ€κ° μλλΌ μ¬λ¬ λμ€μΈ κ²½μ°μλ λ§€μΉλλ€ ({params}: {params: { name: string[] }})
-
- optional catch all segments
-
/[...name]/page.tsx
name
μ΄ μλ/
μ κ²½μ°μλ λ§€μΉλλ€
-
-
- page.tsx λ κΈ°λ³Έμ μΌλ‘ server component μ§λ§
'use-client'
λ₯Ό ν΅ν΄ client component μ¬μ©μ΄ κ°λ₯ - layout.tsx
- μ€μ²©κ°λ₯
- subtree μμ μ¬μ¬μ©
- subtree λΌμ°ν μ re-render λμ§ μλλ€
- root layout μ΄ μλλΌλ©΄ optional
- root layout (μ΅μμ layout.tsx) λ required
- root layout (μ΅μμ layout.tsx) λ , νκ·Έλ₯Ό ν¬ν¨ν΄μΌνλ€
- root layout μ κ²½μ°λ server component λ§κ°λ₯νλ€ λλ¨Έμ§λ client component λ‘ νμ©μ΄ κ°λ₯νλ€
- fetch κ° κ°λ₯νλ€
- layout fetch λ μμμκ² μ λ¬λ μ μμ§λ§ children μμ μ€λ³΅ ν¨μΉλ₯Ό νλλΌλ next.js κ° νΌν¬λ¨Όμ€ μν₯ μμ΄ μ€λ³΅μ μ κ±°νμ¬ μ²λ¦¬
- template.tsx
- client component λ‘ μΆμΈ‘λλ€
- μμΉμμΌλ‘λ layout μ child
- λ§μ°¬κ°μ§λ‘ μ€μ²©μ΄ κ°λ₯νλ€
- navigation μ μ¬μ¬μ©λλ layout κ³Ό λ¬λ¦¬ mount μμ λ§λ€ λ€μ instance ν λλ€
- λ μ€ νλλ₯Ό μ°λ κ²μ΄λΌλ©΄ layout μ΄ λ κΆμ₯λλ€
- navigation
- - server and client components, μΆμ² λ¨
- useRouter - client components
- μ‘°κ±΄μ΄ μλμ hard navigation μ΄ μΌμ΄λλ κ²½μ° loading.tsx κ° νΈμΆλ¨
- server components λ client side μμ cached λλ€
-
useRouter().refresh()
λ₯Ό ν΅ν΄ invaliding μ΄ κ°λ₯νλ€
-
- μ»΄ν¬λνΈκ° viewport μμ λ€μ΄μ€λ©΄ κΈ°λ³Έμ μΌλ‘ prefetch λλ€ - prefetch λ default κ° true - dynamic route μ κ²½μ°μλ loading.tsx λ§ λ¨Όμ prefetch
- cache
- if cache soft, navigation
- static route
- dynamic route
- [path] κ° λ³νμ§ μμ κ²½μ°
- back/forward navigation
- if cache is invalidated, hard navigation
- if cache soft, navigation
- next.js λ focus and scroll management λ₯Ό ν¨
tbd
- parallel routes - 2 page λ₯Ό νλ²μ κ·Έλ¦°λ€(e.g. dashboard)
yarn dlx create-next-app@latest --experimental-app [project]
cd [project]
corepack enable
yarn set version stable
yarn config set nodeLinker pnpm # νμλ μλ, κΈ°λ³Έμ node_modules
yarn # migrate to yarn 3.x
- server component μ¬λ¬κ³³μμ κ°μ data fetch λ μΊμλ₯Ό ν΅ν΄ 곡μ λμ΄ νλ²λ§ fetch κ° μΌμ΄λλ€
- client component μμ server component λ₯Ό λ λλ§ν μ μλ€
- client component μμ children μΌλ‘ server component λ₯Ό λ°μμ λ λλ§νλ€
- server component μμλ client component λ λλ§μ΄ κ°λ₯νλ€
- client component λ μ΅μλ¨μ
'use client'
λλ ν°λΈ μ μΈμ΄ νμνλ€- κΈ°μ‘΄ λ§μ λΌμ΄λΈλ¬λ¦¬λ€μ λλ ν°λΈκ° μμΌλ―λ‘ server component μμ μ¬μ©νλ κ²½μ° λνμ΄ νμνλ€
- μλ κΈ°λ₯μ μ¬μ©ν¨μΌλ‘μ¨ λμ λ λλ§μ μ¬μ©ν μ μλ€
- dynamic function
- server component
- cookies()
- headers()
- client component -> μ¬μ© κΆκ³ (loading.ts)
- useSearchParams()
- server component
- dynamic data fetching
- dynamic
- no-store
- revalidate: 0
- dynamic
- μ 리 | rendering | data fetching | dynamic functions | |-----------|---------------|-------------------| | static | cached | no | | dynamic | cached | yes | | dynamic | not cached | yes | | dynamic | not cached | yes |
- dynamic function
export const dynamic = 'auto'
// 'auto' | 'force-dynamic' | 'error' | 'force-static'
yarn add -D tailwindcss postcss autoprefixer
yarn tailwindcss init -p # -p λ postcss μ€μ μΆκ°
cat app/globals.css << EOF # hello
@tailwind base;
@tailwind components;
@tailwind utilities;
EOF
cat tailwind.config.js << EOF
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{ts,tsx}",
"./pages/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
EOF
yarn add daisyui
cat tailwind.config.js << EOF
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{ts,tsx}",
"./pages/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
],
theme: {
extend: {},
},
plugins: [
require('daisyui'),
],
}
EOF
- [email protected] standalone μ μ© ν
- image size: 465 -> 363 Mb μΌλ‘ λΉ μ§ -> 22% down
- memory usage: @ λ website μ νλ² μ μ νμ μν
- 69@129Mi -> 24@65->83Mi
- 69@117Mi -> 25@64->108Mi
- μ΅μ νκ° μ‘°κΈ λ λ€μ΄κ°λκ±΄μ§ λ©λͺ¨λ¦¬ μ¬μ©λμ΄ λΉ μ§
signin μ λλ₯΄λ©΄ μ λλ‘ λμνμ§ μλμ΄μ λΈλΌμ°μ μμλ μλ λ©μμ§κ° μ°νλ€
next dev --turbo
[400] /api/auth/providers (194ms)
[400] /api/auth/_log (30ms)
[400] /api/auth/error (97ms)
μλλ λΈλΌμ°μ μμ μ°νλ λ‘κ·Έ
Error: This action with HTTP GET is not supported by NextAuth.js
--turbo
μ΅μ
μ λΉΌλ λμνλ€. dynamic route μͺ½μ λ¬Έμ κ° μλ κ²μΌλ‘ 보μΈλ€. λ²μ μ 보λ₯Ό μΆκ°ν΄ λλ€.
"next": "13.1.6",
"next-auth": "^4.19.2",
μ°Έμ‘°κ° srcλ‘ κ±Έλ¦°κ±΄μ§ νμΈν΄μ μμ ν κ²
./node_modules/.store/next-auth-virtual-8ec2bd5fde/node_modules/next-auth/src/core/lib/assert.ts:134:27
Type error: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Adapter<boolean>'.
No index signature with a parameter of type 'string' was found on type 'Adapter<boolean>'.
132 | "useVerificationToken",
133 | "getUserByEmail",
> 134 | ].filter((method) => !adapter[method])
| ^
135 |
136 | if (missingMethods.length) {
137 | return new MissingAdapterMethods(