Nuxt 4 — Fullstack Vue Framework cho Production 2026
Posted on: 4/26/2026 12:13:31 AM
Table of contents
- 1. Cấu trúc thư mục mới — Tách biệt app/ và server/
- 2. TypeScript — Tách biệt Type Projects
- 3. Data Fetching — useFetch Factories và Caching thông minh
- 4. Hybrid Rendering — ISR, SWR, Edge và Route Rules
- 5. Nitro — Universal Server Engine
- 6. Nuxt 4.4 — Các tính năng nổi bật mới nhất
- 7. Tối ưu Performance — Từ Build đến Runtime
- 8. Nuxt 4 vs Next.js 15 — So sánh thực tế
- 9. Migration từ Nuxt 3 lên Nuxt 4
- 10. Best Practices cho Production
- 11. Kết luận
Nếu bạn đang xây dựng ứng dụng web với Vue.js và cần một framework fullstack thực sự cho production — từ SSR, ISR, edge rendering cho đến TypeScript tối ưu — thì Nuxt 4 chính là câu trả lời năm 2026. Ra mắt stable vào tháng 7/2025 và liên tục cải thiện đến phiên bản 4.4 (tháng 3/2026), Nuxt 4 không chỉ là bản nâng cấp thông thường mà là sự tái cấu trúc toàn diện về kiến trúc dự án, data fetching, rendering strategy và developer experience. Bài viết này đi sâu vào mọi khía cạnh quan trọng của Nuxt 4 — từ cấu trúc thư mục mới, hybrid rendering, custom useFetch factories, cho đến chiến lược deploy edge với Nitro.
1. Cấu trúc thư mục mới — Tách biệt app/ và server/
Thay đổi lớn nhất và dễ nhận thấy nhất của Nuxt 4 là cấu trúc thư mục. Toàn bộ code ứng dụng client được chuyển vào thư mục app/, tách biệt hoàn toàn với server/, shared/, và các file cấu hình gốc.
my-nuxt-app/
├─ app/ # Code ứng dụng (client + universal)
│ ├─ assets/
│ ├─ components/
│ ├─ composables/
│ ├─ layouts/
│ ├─ middleware/
│ ├─ pages/
│ ├─ plugins/
│ ├─ utils/
│ ├─ app.vue
│ └─ app.config.ts
├─ shared/ # Code dùng chung client & server
│ ├─ types/
│ └─ utils/
├─ server/ # API routes, middleware server
│ ├─ api/
│ ├─ middleware/
│ └─ utils/
├─ public/
├─ content/
├─ nuxt.config.ts
└─ tsconfig.json # Chỉ cần 1 file duy nhất
Tại sao điều này quan trọng?
Trên Windows và Linux, file watcher hoạt động nhanh hơn đáng kể khi không phải theo dõi node_modules/ và .git/ cùng cấp với source code. IDE cũng phân biệt rõ ràng hơn giữa client code và server code, giúp autocompletion chính xác hơn. Dự án cũ vẫn hoạt động bình thường — migration không bắt buộc.
2. TypeScript — Tách biệt Type Projects
Nuxt 4 tạo ra các TypeScript project riêng biệt cho từng ngữ cảnh: app/, server/, shared/, và builder code. Điều này có nghĩa là khi bạn viết code trong server/api/, TypeScript sẽ chỉ gợi ý những API có sẵn trên server (Node.js APIs, database client...) mà không lẫn với DOM APIs hay Vue composables. Ngược lại, code trong app/ không nhìn thấy server utilities trừ khi chúng nằm trong shared/.
// shared/types/user.ts — dùng được ở cả client và server
export interface User {
id: number
name: string
email: string
role: 'admin' | 'editor' | 'viewer'
}
// server/api/users/[id].get.ts — chỉ chạy trên server
import type { User } from '~/shared/types/user'
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id')
// database query, server-only logic
return { user } satisfies { user: User }
})
// app/pages/users/[id].vue — chạy trên client (và SSR)
const { data: user } = await useFetch<User>(`/api/users/${route.params.id}`)
Chỉ cần một file tsconfig.json ở gốc dự án — Nuxt tự sinh ra các project references phù hợp. Trước đây nhiều dự án phải duy trì 2-3 tsconfig riêng biệt, giờ đã không cần nữa.
3. Data Fetching — useFetch Factories và Caching thông minh
Nuxt 4.4 giới thiệu createUseFetch và createUseAsyncData — cho phép tạo các phiên bản custom của useFetch với default options riêng. Đây là tính năng game-changer cho các dự án lớn khi cần gọi nhiều API khác nhau với base URL, headers, error handling riêng biệt.
// app/composables/useApiFetch.ts
export const useApiFetch = createUseFetch((currentOptions) => {
const config = useRuntimeConfig()
const { token } = useAuth()
return {
...currentOptions,
baseURL: currentOptions.baseURL ?? config.public.apiBase,
headers: {
...currentOptions.headers,
Authorization: `Bearer ${token.value}`,
},
onResponseError({ response }) {
if (response.status === 401) navigateTo('/login')
},
}
})
// app/composables/usePublicFetch.ts — không cần auth
export const usePublicFetch = createUseFetch({
server: false, // chỉ fetch trên client
baseURL: '/api/public',
})
Sử dụng trong component cũng tự nhiên như useFetch gốc:
<script setup lang="ts">
// Tự động có auth headers, base URL, error handling
const { data: posts } = await useApiFetch<Post[]>('/posts')
// Public API, chỉ gọi client-side
const { data: stats } = await usePublicFetch<Stats>('/stats')
</script>
Automatic data sharing
Khi nhiều component cùng gọi useFetch hoặc useAsyncData với cùng key, Nuxt 4 tự động chia sẻ dữ liệu thay vì gọi API trùng lặp. Khi component unmount, dữ liệu cũng được tự động cleanup — không cần quản lý thủ công.
4. Hybrid Rendering — ISR, SWR, Edge và Route Rules
Một trong những lợi thế lớn nhất của Nuxt 4 so với các framework khác là khả năng kết hợp nhiều chiến lược rendering trong cùng một ứng dụng thông qua Route Rules. Mỗi route có thể được cấu hình riêng biệt về cách render.
graph TB
REQ["Request từ User"] --> RR{"Route Rules Engine"}
RR -->|"/blog/*"| ISR["ISR
Cache 1h, CDN edge"]
RR -->|"/dashboard/*"| SSR["SSR
Server render mỗi request"]
RR -->|"/about"| SSG["SSG
Pre-rendered tại build"]
RR -->|"/api/*"| SWR["SWR
Stale-While-Revalidate"]
ISR --> CDN["CDN Edge Cache"]
SSR --> SERVER["Nitro Server"]
SSG --> STATIC["Static Files"]
SWR --> CACHE["In-Memory LRU Cache"]
CDN --> USER["Response ~50ms TTFB"]
SERVER --> USER
STATIC --> USER
CACHE --> USER
style REQ fill:#e94560,stroke:#fff,color:#fff
style RR fill:#2c3e50,stroke:#fff,color:#fff
style ISR fill:#4CAF50,stroke:#fff,color:#fff
style SSR fill:#2196F3,stroke:#fff,color:#fff
style SSG fill:#ff9800,stroke:#fff,color:#fff
style SWR fill:#9C27B0,stroke:#fff,color:#fff
style USER fill:#e94560,stroke:#fff,color:#fff
Hình 1: Hybrid Rendering — mỗi route được render theo chiến lược phù hợp nhất
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
// Blog posts: ISR với TTL 1 giờ
'/blog/**': { isr: 3600 },
// Trang chủ: SWR - phục vụ bản cũ, revalidate background
'/': { swr: 600 },
// Dashboard: luôn SSR, cần dữ liệu real-time
'/dashboard/**': { ssr: true },
// Landing pages: pre-render tại build time
'/about': { prerender: true },
'/pricing': { prerender: true },
// API: CORS + cache
'/api/**': {
cors: true,
headers: { 'Cache-Control': 'max-age=60' },
},
},
})
| Chiến lược | TTFB | Phù hợp cho | Trade-off |
|---|---|---|---|
| SSG (Static) | ~10ms | Landing page, docs, about | Phải rebuild khi nội dung đổi |
| ISR (Incremental) | ~50ms | Blog, catalog, marketing | Dữ liệu có thể stale trong TTL |
| SWR (Stale-While-Revalidate) | ~50ms | API responses, feeds | Request đầu tiên có thể chậm |
| SSR (Server) | ~200ms | Dashboard, user-specific content | Mỗi request đều render mới |
| Edge SSR | ~30ms | Content toàn cầu, cần fresh | Hạn chế Node.js APIs |
5. Nitro — Universal Server Engine
Phía sau Nuxt 4 là Nitro — server engine cho phép deploy cùng một codebase lên bất kỳ đâu: Node.js server, Cloudflare Workers, Vercel Edge Functions, AWS Lambda, Deno Deploy, hoặc Bun. Nitro tự động tối ưu build output cho từng target platform.
// server/api/products/[id].get.ts
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id')
// Sử dụng Nitro built-in KV storage
const cached = await useStorage('cache').getItem(`product:${id}`)
if (cached) return cached
const product = await db.query('SELECT * FROM products WHERE id = ?', [id])
// Cache 5 phút
await useStorage('cache').setItem(`product:${id}`, product, { ttl: 300 })
return product
})
// server/api/upload.post.ts — File upload với multipart
export default defineEventHandler(async (event) => {
const files = await readMultipartFormData(event)
if (!files?.length) throw createError({ statusCode: 400, message: 'No file' })
const file = files[0]
// Xử lý file: lưu R2, S3, hoặc local
await useStorage('assets').setItemRaw(`uploads/${file.filename}`, file.data)
return { url: `/uploads/${file.filename}` }
})
Deploy targets phổ biến
Nitro hỗ trợ hơn 15 deployment targets: Node.js (default), Cloudflare Workers/Pages, Vercel Edge/Serverless, Netlify Edge, AWS Lambda, Azure Functions, Deno Deploy, Bun, Docker. Chỉ cần thay đổi nitro.preset trong config — không cần sửa code ứng dụng.
6. Nuxt 4.4 — Các tính năng nổi bật mới nhất
6.1. Typed Layout Props
Pages giờ có thể truyền props trực tiếp đến layout thông qua definePageMeta — với đầy đủ type safety:
<!-- app/layouts/panel.vue -->
<script setup lang="ts">
defineProps<{
sidebar?: boolean
title?: string
}>()
</script>
<template>
<div class="panel-layout">
<aside v-if="sidebar">...</aside>
<main>
<h1 v-if="title">{{ title }}</h1>
<slot />
</main>
</div>
</template>
<!-- app/pages/dashboard.vue -->
<script setup lang="ts">
definePageMeta({
layout: {
name: 'panel',
props: { sidebar: true, title: 'Dashboard' }, // ✅ có autocomplete
},
})
</script>
6.2. Payload Extraction Mode
Cho các ứng dụng sử dụng ISR/SWR, Nuxt 4.4 cung cấp chế độ payloadExtraction: 'client' — inline toàn bộ payload vào HTML ban đầu, đồng thời tạo _payload.json cho client-side navigation. Kết hợp với runtime LRU cache, serverless functions không cần re-render khi phục vụ payload:
export default defineNuxtConfig({
experimental: {
payloadExtraction: 'client',
},
})
6.3. Accessibility Announcer
Composable useAnnouncer mới giúp thông báo dynamic content cho screen readers — quan trọng cho accessibility compliance:
const { polite, assertive } = useAnnouncer()
async function addToCart(item: Product) {
await $fetch('/api/cart', { method: 'POST', body: { itemId: item.id } })
polite(`Đã thêm ${item.name} vào giỏ hàng`) // Screen reader đọc sau khi rảnh
}
function showCriticalError(msg: string) {
assertive(msg) // Screen reader đọc ngay lập tức
}
6.4. Build Profiling
Lệnh nuxt build --profile xuất Chrome Trace, JSON report, và CPU profile — giúp phân tích chi tiết thời gian build của từng module, plugin, transform:
nuxt build --profile
# Output:
# ✓ .nuxt/perf-trace.json → mở trong Chrome DevTools
# ✓ .nuxt/perf-report.json → tracking dài hạn
# ✓ nuxt-build.cpuprofile → flame graph
7. Tối ưu Performance — Từ Build đến Runtime
7.1. Bundle Optimization
// nuxt.config.ts — lazy load heavy components
export default defineNuxtConfig({
components: [
{ path: '~/components', pathPrefix: false },
{ path: '~/components/heavy', prefix: 'Heavy', global: false },
],
})
<!-- Lazy load component chỉ khi cần -->
<template>
<LazyHeavyChart v-if="showChart" :data="chartData" />
<LazyHeavyEditor v-if="isEditing" :content="content" />
</template>
7.2. Image Optimization với Nuxt Image
<template>
<NuxtImg
src="/hero.jpg"
format="avif,webp"
width="1200"
height="600"
sizes="sm:100vw md:80vw lg:1200px"
loading="lazy"
placeholder
/>
</template>
7.3. View Transitions API
Nuxt 4.4 mở rộng hỗ trợ View Transitions với type definitions — cho phép animation khác nhau tùy theo kiểu navigation:
export default defineNuxtConfig({
experimental: {
viewTransition: true,
},
})
<script setup lang="ts">
definePageMeta({
viewTransition: {
type: 'slide-left', // forward navigation
},
})
</script>
8. Nuxt 4 vs Next.js 15 — So sánh thực tế
| Tiêu chí | Nuxt 4 | Next.js 15 |
|---|---|---|
| Framework gốc | Vue 3.6 | React 19 |
| Server engine | Nitro (universal, 15+ targets) | Built-in (Vercel-optimized) |
| Rendering modes | SSR, SSG, ISR, SWR, Edge — per route | SSR, SSG, ISR — per route |
| Auto-imports | Composables, components, utils | Không (import thủ công) |
| File-based routing | Có (Vue Router v5) | Có (App Router) |
| State management | useState + Pinia (tích hợp sẵn) | React Context + Zustand/Jotai |
| Edge deployment | Cloudflare, Vercel, Netlify, Deno... | Vercel Edge (native), khác qua adapter |
| Learning curve | Thấp — Vue Options/Composition API | Cao — RSC, Server Actions, Suspense |
| Bundle size (starter) | ~45KB gzipped | ~85KB gzipped |
9. Migration từ Nuxt 3 lên Nuxt 4
npx nuxt upgrade --dedupe để cập nhật Nuxt và deduplicate lockfile. Kiểm tra tương thích module.npx codemod@latest nuxt/4/migration-recipe để tự động chuyển đổi phần lớn breaking changes.app/ để tận dụng IDE performance và type separation.nuxi typecheck — type project mới có thể phát hiện lỗi type ẩn trước đây.Lưu ý cho module authors
Nuxt 2 compatibility đã bị loại bỏ hoàn toàn khỏi @nuxt/kit trong Nuxt 4. Nếu bạn maintain module Nuxt, cần cập nhật để chỉ hỗ trợ Nuxt 3+/4+.
10. Best Practices cho Production
// nuxt.config.ts — cấu hình production-ready
export default defineNuxtConfig({
// Hybrid rendering
routeRules: {
'/': { swr: 600 },
'/blog/**': { isr: 3600 },
'/app/**': { ssr: true },
'/admin/**': { ssr: false }, // SPA mode cho admin
},
// Performance
experimental: {
payloadExtraction: 'client',
viewTransition: true,
},
// Nitro — deploy target
nitro: {
preset: 'cloudflare-pages', // hoặc 'node-server', 'vercel-edge'
compressPublicAssets: true,
minify: true,
},
// Vite optimizations
vite: {
build: {
cssCodeSplit: true,
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router', 'pinia'],
},
},
},
},
},
})
Checklist trước khi go live
1. Đã cấu hình routeRules phù hợp cho từng nhóm route.
2. Đã bật payloadExtraction: 'client' nếu dùng ISR/SWR.
3. Đã chạy nuxt build --profile để kiểm tra không có module nào build quá lâu.
4. Đã test trên target deployment (Cloudflare, Vercel...) chứ không chỉ local.
5. Đã bật compression (gzip/brotli) tại reverse proxy hoặc CDN.
6. Images sử dụng <NuxtImg> với format avif/webp.
11. Kết luận
Nuxt 4 không chỉ là phiên bản kế tiếp của Nuxt 3 — nó đánh dấu sự trưởng thành của Vue.js ecosystem trong việc cạnh tranh trực tiếp với React/Next.js ở phân khúc fullstack framework. Với cấu trúc dự án sạch hơn, TypeScript tối ưu, hybrid rendering linh hoạt, custom useFetch factories, và Nitro hỗ trợ deploy lên mọi nền tảng, Nuxt 4 là lựa chọn production-ready cho mọi quy mô dự án — từ blog cá nhân đến enterprise SaaS.
Phiên bản 4.4 tiếp tục nâng tầm với typed layout props, accessibility announcer, build profiling và payload optimization — những tính năng cho thấy đội ngũ Nuxt không chỉ chạy theo tính năng mà còn đầu tư sâu vào developer experience và performance thực tế.
Nguồn tham khảo:
Announcing Nuxt 4.0 — Nuxt Blog
Nuxt 4.4 Release Notes — Nuxt Blog
Rendering Modes — Nuxt 4 Docs
Performance Best Practices — Nuxt 4 Docs
Vue, Nuxt & Vite Status in 2026 — Five Jars
Rspack — Bundler viết bằng Rust thay thế Webpack, build nhanh gấp 20 lần
Deno 2 — JavaScript Runtime Thế Hệ Mới: Bảo Mật, TypeScript Native và Tương Thích NPM
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.