Dark mode
Core Concepts
Concept | Description | Key Features |
---|---|---|
Next.js | React-based framework | SSR/API routes, ไฟล์ app/ , โหมด Hybrid rendering |
Vercel | เครื่องมือ build หลัก | Hot Module Replacement, Build เร็ว, Plugin ecosystem |
React Hooks | รูปแบบการเขียน React components | useState() function, useContext() , Custom hooks |
Next.js Routing | การแชร์และการขยาย configuration | Extend projects, Share components, Unified config |
Automatic Imports | การนำเข้าอัตโนมัติ | Components, Hooks, React APIs |
File-based Routing | ระบบ routing จากโครงสร้างไฟล์ | app/ directory, Dynamic routes, Route middleware |
Key Features
คุณสมบัติ | รายละเอียด | ตัวอย่าง |
---|---|---|
File-based Routing | สร้างเส้นทางอัตโนมัติจากโครงสร้างไฟล์ | app/about/page.tsx → /about |
Server-side Rendering | การแสดงผลฝั่งเซิร์ฟเวอร์ | ใช้ fetch() สำหรับดึงข้อมูลใน SSR |
Static Site Generation | การสร้างเว็บไซต์แบบสแตติก | คำสั่ง next build และ next export |
Automatic Imports | นำเข้า components/hooks อัตโนมัติ | ใช้ useRouter() โดยไม่ต้อง import |
App Directory | ระบบโมดูลสำหรับเพิ่มความสามารถ | app/ , pages/ , components/ |
Hybrid Rendering | ผสมผสาน SSR, SSG และ CSR ในแอปเดียว | export const dynamic = 'force-static' |
DevTools | เครื่องมือพัฒนาที่มีในตัว | React Developer Tools |
API Routes | สร้าง API endpoints ฝั่งเซิร์ฟเวอร์ | ไฟล์ใน app/api/ จะกลายเป็นเส้นทาง API |
Middleware | การจัดการความปลอดภัยของเส้นทาง | ไฟล์ middleware.ts ใน root directory |
State Management | การจัดการสถานะ | useState , useReducer , หรือ libraries ภายนอก |
Getting Started
- Installation
ติดตั้ง Next.js และ dependencies ที่จำเป็นด้วย package manager ที่คุณเลือก:
bash
npx create-next-app@latest
npm run dev
bash
pnpm create next-app
pnpm run dev
bash
yarn create next-app
yarn dev
bash
bun create next-app
bun run dev
- Run Development Server
เริ่มต้น development server สำหรับการพัฒนาแบบ real-time:
bash
npm run dev
- Build for Production
สร้างไฟล์สำหรับ production ที่ optimize แล้ว:
bash
npm run build
Configuration
Next.js ใช้ไฟล์ next.config.js
สำหรับการกำหนดค่า ตัวเลือกหลัก:
ตัวเลือก | คำอธิบาย | ตัวอย่าง |
---|---|---|
reactStrictMode | เปิดใช้งาน React Strict Mode | true |
output | โหมดการ export (static/standalone) | 'standalone' |
images | การตั้งค่าการปรับรูปภาพ | { domains: [...] } |
env | ตัวแปรสภาพแวดล้อม | { API_URL: process.env.API_URL } |
experimental | คุณสมบัติทดลอง | { appDir: true } |
compiler | ตัวเลือกคอมไพลเลอร์ | { styledComponents: true } |
Example Config
js
// next.config.js
module.exports = {
reactStrictMode: true,
output: 'standalone',
images: {
domains: ['example.com'],
},
env: {
API_URL: process.env.API_URL,
},
experimental: {
appDir: true,
},
compiler: {
styledComponents: true,
},
}
TypeScript Support
For TypeScript, create a next-env.d.ts
file:
ts
/// <reference types="next" />
/// <reference types="next/image-types/global" />
Directory Structure
โครงสร้างไดเรกทอรีมาตรฐานของ Next.js:
app/
: เก็บ page components และ layouts (App Router)pages/
: สร้าง routes อัตโนมัติจากไฟล์ (Pages Router)components/
: เก็บ reusable componentspublic/
: เก็บ static filesstyles/
: เก็บ global styles
my-next-app/
├── app/
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Home page
│ └── about/
│ └── page.tsx # About page
├── components/
│ ├── Header.tsx
│ └── Footer.tsx
├── pages/
│ ├── _app.tsx # Custom App component
│ └── api/
│ └── hello.ts # API route
├── public/
│ └── favicon.ico
├── styles/
│ └── globals.css
└── next.config.js # Next.js configuration
Deployment
Deployment Targets
Target | Command | Config | Output Directory |
---|---|---|---|
Vercel | Automatic | None needed | N/A |
Node.js | next build + next start | output: 'standalone' | .next |
Static | next build + next export | output: 'export' | out/ |
Docker | docker build | Dockerfile | Image |
Edge | Automatic | runtime: 'edge' | N/A |
Implementation Examples
bash
# Just push to connected Git repository
# Automatic deployments configured in Vercel
bash
npm run build
npm run export
# Outputs to out/ directory
dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:18-alpine AS runner
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
EXPOSE 3000
CMD ["npm", "start"]
js
// pages/api/hello.js
export const config = {
runtime: 'edge'
}
export default function handler(request) {
return new Response('Hello from edge!')
}
Pages and Routing
Next.js สร้างเส้นทางอัตโนมัติจากโครงสร้างไดเรกทอรี pages/
Concept | Description | Example |
---|---|---|
Basic Route | เส้นทางพื้นฐานจากไฟล์ | pages/index.tsx → / |
Dynamic Route | เส้นทางแบบไดนามิกด้วยพารามิเตอร์ | pages/users/[id].tsx → /users/123 |
Nested Route | เส้นทางแบบซ้อนจากโฟลเดอร์ | pages/products/index.tsx → /products |
jsx
// pages/index.tsx
export default function HomePage() {
return <div>Home Page</div>
}
jsx
// pages/users/[id].tsx
export default function UserPage({ params }) {
return <div>User ID: {params.id}</div>
}
jsx
// pages/about.tsx
export default function AboutPage() {
return <div>หน้าเกี่ยวกับเรา</div>
}
Layer
คุณสมบัติ | คำอธิบาย | การกำหนดค่า |
---|---|---|
Extends | แชร์ components/config | next.config.js |
Presets | การตั้งค่าล่วงหน้า | extends: ['@next/ui'] |
Modules | เพิ่มความสามารถ | modules: [] |
js
// next.config.js
module.exports = {
extends: ['github:owner/repo']
}
js
// next.config.js
module.exports = {
modules: ['@next/image']
}
js
// my-layer/next.config.js
module.exports = {
components: {
dirs: ['~/components']
}
}
View
คุณสมบัติ | คำอธิบาย | ตัวอย่าง |
---|---|---|
Templates | โครงสร้างเลย์เอาต์ | app/layout.tsx |
Components | องค์ประกอบ UI ที่นำกลับมาใช้ใหม่ได้ | components/ |
Pages | องค์ประกอบเส้นทาง | pages/ |
Dynamic Imports | การโหลดแบบล่าช้า | import('~/components/HeavyComponent') |
jsx
// app/layout.tsx
export default function Layout({ children }) {
return (
<div>
<AppHeader />
{children}
<AppFooter />
</div>
)
}
jsx
// pages/about.tsx
import dynamic from 'next/dynamic'
const Component = dynamic(() => import('~/components/HeavyComponent'))
export default function AboutPage() {
return <Component />
}
js
// next.config.js
module.exports = {
app: {
pageTransition: { name: 'page', mode: 'out-in' }
}
}
Styling
Method | Description | Configuration |
---|---|---|
CSS Modules | สไตล์แบบเฉพาะที่ | *.module.css |
Sass | ภาษา CSS ขั้นสูง | npm install -D sass |
CSS-in-JS | สไตล์แบบฝั่งไคลเอนต์ | npm install -D styled-components |
css
/* components/Button.module.css */
.button {
background: #00dc82;
}
jsx
// pages/about.tsx
import styles from '../styles/about.module.scss'
export default function AboutPage() {
return <div className={styles.container}>Content</div>
}
jsx
// components/Button.tsx
import styled from 'styled-components'
const Button = styled.button`
background: #00dc82;
`
export default Button
SEO and Meta
Next.js มี utilities สำหรับจัดการ SEO และ meta tags:
Head
component: สำหรับตั้งค่า meta tags พื้นฐานnext/head
: สำหรับ meta tags ของโซเชียลมีเดียnext-sitemap
: สร้าง sitemap.xml อัตโนมัติ- Meta tags จะถูก inject ใน SSR/SSG mode
เทคนิค | คำอธิบาย | การนำไปใช้ |
---|---|---|
Basic Meta | เมตาแท็กพื้นฐาน | SEO ทั่วไป |
Social Meta | OpenGraph/Twitter cards | การแชร์บนโซเชียล |
Sitemap | การสร้างแผนผังเว็บไซต์ | การจัดทำดัชนีโดยเสิร์ชเอนจิน |
jsx
// pages/about.tsx
import Head from 'next/head'
export default function AboutPage() {
return (
<div>
<Head>
<title>หน้าแรก</title>
<meta name="description" content="คำอธิบายเว็บไซต์" />
<meta name="keywords" content="next, react, javascript" />
</Head>
<div>หน้าเกี่ยวกับเรา</div>
</div>
)
}
jsx
// pages/about.tsx
import Head from 'next/head'
export default function AboutPage() {
return (
<div>
<Head>
<title>หน้าแรก | เว็บไซต์ของฉัน</title>
<meta property="og:title" content="หน้าแรก | เว็บไซต์ของฉัน" />
<meta property="og:description" content="คำอธิบายเว็บไซต์สำหรับ social media" />
<meta property="og:image" content="https://example.com/image.jpg" />
</Head>
<div>หน้าเกี่ยวกับเรา</div>
</div>
)
}
js
// next.config.js
module.exports = {
sitemap: {
hostname: 'https://example.com',
routes: ['/', '/about']
}
}
Data Fetching
วิธี | คำอธิบาย | เหมาะสำหรับ |
---|---|---|
getStaticProps | การดึงข้อมูลสำหรับ SSG | การเรนเดอร์แบบสแตติก |
getServerSideProps | การดึงข้อมูลสำหรับ SSR | การเรนเดอร์แบบเซิร์ฟเวอร์ |
fetch | การร้องขอ API แบบแมนนวล | การเรียก API แบบแมนนวล |
jsx
// pages/about.tsx
export const getStaticProps = async () => {
const data = await fetch('https://api.example.com/data')
return {
props: {
data: await data.json()
}
}
}
jsx
// pages/about.tsx
export const getServerSideProps = async () => {
const data = await fetch('https://api.example.com/data')
return {
props: {
data: await data.json()
}
}
}
jsx
// pages/about.tsx
import fetch from 'isomorphic-unfetch'
export default function AboutPage() {
const [data, setData] = useState(null)
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data))
}, [])
return <div>Data: {data}</div>
}
State Management
Next.js มีวิธีการจัดการ state หลายแบบ:
วิธีการ | คำอธิบาย | เมื่อไหร่ควรใช้ |
---|---|---|
React Hooks | useState , useReducer | สถานะภายในคอมโพเนนต์ |
Context API | createContext , useContext | สถานะที่แชร์ระหว่างคอมโพเนนต์ |
Server Components | ดึงข้อมูลจากเซิร์ฟเวอร์ | ข้อมูลที่ไม่เปลี่ยนแปลงบ่อย |
URL Search Params | เก็บสถานะใน URL | การกรองข้อมูล, การแบ่งหน้า |
External Libraries | Zustand, Redux | สถานะระดับแอปพลิเคชันที่ซับซ้อน |
jsx
// components/Counter.js
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
)
}
jsx
// context/ThemeContext.js
import { createContext, useContext } from 'react'
const ThemeContext = createContext('light')
export function ThemeProvider({ children }) {
return (
<ThemeContext.Provider value="dark">
{children}
</ThemeContext.Provider>
)
}
export function useTheme() {
return useContext(ThemeContext)
}
jsx
// pages/products.js
import { useRouter } from 'next/router'
export default function Products() {
const router = useRouter()
const { page = '1' } = router.query
return (
<div>
<p>Current Page: {page}</p>
<button onClick={() => router.push(`?page=${Number(page) + 1}`)}>
Next Page
</button>
</div>
)
}
Environment Variables
การจัดการ environment variables ใน Next.js:
- ตัวแปรสาธารณะ (public): เข้าถึงได้ทั้งฝั่ง client และ server
- ตัวแปรส่วนตัว (private): เข้าถึงได้เฉพาะฝั่ง server
- runtimeConfig: สำหรับการกำหนดค่าที่สามารถ override ได้
- ควรเก็บค่าลับในไฟล์
.env
ที่ไม่ถูก commit
ประเภทตัวแปร | การใช้งาน | ตัวอย่าง |
---|---|---|
Public | เข้าถึงได้ฝั่งไคลเอนต์ | NEXT_PUBLIC_API_BASE |
Private | เฉพาะฝั่งเซิร์ฟเวอร์ | DATABASE_URL |
Runtime Config | การเข้าถึงแบบ type-safe | runtimeConfig |
sh
# Public (client-side)
NEXT_PUBLIC_API_BASE=https://api.example.com
# Private (server-only)
DATABASE_URL=postgres://user:pass@localhost:5432/db
js
// next.config.js
module.exports = {
runtimeConfig: {
apiSecret: '', // Can be overridden by NEXT_API_SECRET
public: {
apiBase: '/api' // NEXT_PUBLIC_API_BASE
}
}
}
jsx
// pages/about.tsx
import { useRuntimeConfig } from 'next/config'
export default function AboutPage() {
const config = useRuntimeConfig()
// Client-side
const apiBase = config.public.apiBase
// Server-side (API routes)
// const apiSecret = config.apiSecret
}
Optimization
Next.js provides built-in optimizations:
Technique | Description | Implementation |
---|---|---|
Image Optimization | Automatic resizing/formatting | next/image component |
Font Optimization | Automatic font subsetting | next/font |
Script Optimization | Async/defer script loading | next/script |
Lazy Loading | On-demand component loading | dynamic() import |
Code Splitting | Automatic per-route splitting | Built-in |
ISR | Incremental Static Regeneration | revalidate in getStaticProps |
jsx
import Image from 'next/image'
export default function Avatar() {
return (
<Image
src="/profile.jpg"
alt="Profile"
width={500}
height={500}
priority // Preload important images
/>
)
}
jsx
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
export default function MyApp() {
return (
<div className={inter.className}>
My styled text
</div>
)
}
jsx
import dynamic from 'next/dynamic'
const HeavyComponent = dynamic(
() => import('../components/HeavyComponent'),
{
loading: () => <p>Loading...</p>,
ssr: false // Disable server-side render
}
)
export default function Page() {
return <HeavyComponent />
}
Best Practices
โครงสร้างโปรเจค
องค์ประกอบ | ตำแหน่งที่เก็บ | ตัวอย่าง |
---|---|---|
หน้าเว็บหลัก | app/ | app/page.tsx |
คอมโพเนนต์ | components/ | components/Button.tsx |
ฮุค | hooks/ | hooks/useAuth.ts |
ยูทิลิตี้ | utils/ หรือ lib/ | utils/api.ts |
ประสิทธิภาพ
เทคนิค | คำอธิบาย | ตัวอย่าง |
---|---|---|
การปรับรูปภาพ | ใช้ next/image | import Image from 'next/image' |
Static Generation | ใช้ getStaticProps | เหมาะสำหรับข้อมูลที่ไม่เปลี่ยนแปลงบ่อย |
ISR | อัปเดตข้อมูลแบบค่อยเป็นค่อยไป | revalidate: 60 (วินาที) |
Code Splitting | โหลดโค้ดเมื่อจำเป็น | dynamic() import |
jsx
// pages/products.js
export async function getStaticProps() {
const res = await fetch('https://.../products')
const products = await res.json()
return {
props: { products },
revalidate: 60 // ISR: อัปเดตทุก 60 วินาที
}
}
jsx
import dynamic from 'next/dynamic'
const HeavyComponent = dynamic(
() => import('../components/HeavyComponent'),
{ loading: () => <p>Loading...</p> }
)
ความปลอดภัย
ข้อควรระวัง | วิธีป้องกัน |
---|---|
ข้อมูลผู้ใช้ | ตรวจสอบข้อมูลก่อนใช้งาน |
คีย์ลับ | ใช้ environment variables |
CORS | กำหนดนโยบายที่เหมาะสม |
XSS | ทำความสะอาดข้อมูลก่อนแสดงผล |
การพัฒนา
เครื่องมือ | การใช้งาน |
---|---|
TypeScript | สำหรับตรวจสอบประเภทข้อมูล |
ESLint | ตรวจสอบคุณภาพโค้ด |
Prettier | จัดรูปแบบโค้ดอัตโนมัติ |
Jest | ทดสอบหน่วยงาน |
Playwright | ทดสอบ End-to-End |