Nuxt4 是基于 Vue 3 构建的现代化全栈 Web 框架,它为开发者提供了构建高性能、可扩展的 Web 应用程序的 SSR 完整解决方案。
核心定位: Nuxt4 是一个元框架 (Meta Framework),致力于让 Vue 开发变得更简单、高效、现代化,它在 Vue 3 的基础上提供了完整的应用架构、开发工具链和最佳实践。
# 零配置启动
pnpm create nuxt my-project
cd my-project && pnpm install
pnpm dev -o
// 自动导入,无需手动配置
export default defineNuxtConfig({
// 开箱即用的配置
});
// 自动代码分割
const LazyComponent = defineAsyncComponent(
() => import('~/components/HeavyComponent.vue')
);
// 智能预加载
const { data } = await useLazyFetch('/api/data');
// 自动压缩优化
export default defineNuxtConfig({
nitro: {
compressPublicAssets: true
}
});
// 端到端类型推断
const { data } = await useFetch('/api/user'); // 自动推断返回类型
// 路由类型安全
await navigateTo('/user/profile'); // 路由参数类型检查
// 配置类型提示
export default defineNuxtConfig({
runtimeConfig: {
apiSecret: '', // 自动类型推断
public: {
baseURL: ''
}
}
});
传统方式: 大量的配置,手动引入
import { createPinia } from 'pinia';
import { createApp } from 'vue';
// 需要大量配置
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: []
});
const pinia = createPinia();
const app = createApp(App);
app.use(router);
app.use(pinia);
app.mount('#app');
Nuxt4 方式: 自动导入,约定大于配置
<!-- pages/index.vue -->
<template>
<div>
<h1>欢迎来到 Nuxt4</h1>
<NuxtLink to="/about">
关于我们
</NuxtLink>
</div>
</template>
<script setup>
// 一切都是自动配置的
const { data } = await useFetch('/api/data');
</script>
项目结构:
├── pages/ # 前端页面
├── components/ # Vue 组件
├── server/ # 服务器端代码
│ ├── api/ # API 路由
│ └── middleware/ # 服务器中间件
├── composables/ # 组合式函数
├── plugins/ # 插件
└── nuxt.config.ts # 配置文件
export default defineNuxtConfig({
// 自动性能优化
experimental: {
payloadExtraction: false,
inlineSSRStyles: false
},
// 智能渲染策略
routeRules: {
'/': { prerender: true },
'/admin/**': { ssr: false },
'/api/**': { cors: true }
}
});
让我们回顾 Nuxt.js 的重要发展节点:
时间 | 版本 | 主要特性 |
---|
2016年10月 | Nuxt.js 1.0 发布 | - 基于 Vue 2.x 和 Webpack 2 - 提供基础的 SSR 功能 - 引入约定大于配置的理念 - 支持自动路由生成 |
2018年1月 | Nuxt.js 2.0 重大更新 | - 升级到 Vue 2.5+ 和 Webpack 4 - 引入 Nuxt.js 模块系统 - 支持 TypeScript - 性能显著提升 - 增强的开发体验 |
2021年8月 | Nuxt 3 Beta 发布 | - 基于 Vue 3 和 Vite - 全新的 Nitro 服务器引擎 - 支持 Composition API - 更好的 TypeScript 支持 |
2022年11月 | Nuxt 3 正式发布 | - 生产就绪的稳定版本 - 全面的生态系统支持 - 企业级特性完善 - 社区模块丰富 |
2024年6月 | Nuxt 3.12 发布 | - 为 Nuxt 4 做准备 - 引入 compatibilityVersion: 4 测试功能 - 性能优化和开发体验改进 - 内置无障碍功能增强 |
2025年4月 | Nuxt 3.17 发布 | - 数据获取层重大改进 - 新的内置组件 - 更好的类型安全 - 性能持续优化 |
2025年6月 | Nuxt 4 Alpha 发布 | - 🚀 全新的目录结构 (app/ 目录) - 🔄 改进的数据获取机制 - 🏷️ 一致的组件命名 - 📄 增强的头部管理 - ⚡ 准备采用 Vite Environment API |
Nuxt 4 Alpha 于 2025 年 6 月 2 日正式发布,稳定版本预计在 2025 年 6 月底发布。
重要提醒: Nuxt 4 目前处于 Alpha 阶段,API 可能会有变化。建议在非生产环境中进行测试。
您可以通过两种方式体验 Nuxt4 的新特性:
在现有的 Nuxt 3 项目中,您可以启用 Nuxt 4 的兼容性模式:
// nuxt.config.ts
export default defineNuxtConfig({
future: {
compatibilityVersion: 4
}
});
# 创建新的 Nuxt 4 项目
pnpm create nuxt@4 my-nuxt4-project
# 或者在现有项目中安装 Alpha 版本
pnpm add nuxt@4
根据官方路线图,版本支持计划如下:
版本 | 支持状态 | 支持时间 |
---|
Nuxt 3 | 持续维护 | 至 2025 年底 |
Nuxt 4 | Alpha 阶段 | 2025 年 6 月 - 2026 年中期 (预计) |
Nuxt 5 | 计划中 | 配合 Nitro v3 发布 |
维护承诺: Nuxt 团队承诺在 Nuxt 4 发布后的 6 个月内继续维护 Nuxt 3,确保平滑的升级过渡。
提供现代化的前端开发基础,是 Nuxt4 的响应式和组件化基石。
Composition API
- 更好的逻辑复用
- 更清晰的代码组织
- 更强的类型推断
- 更灵活的状态管理
响应式系统 3.0
- 基于 Proxy 的响应式
- 更好的性能表现
- 更精确的依赖收集
- 更少的内存开销
<!-- Vue 3 核心特性示例 -->
<template>
<div>
<h1>{{ title }}</h1>
<p>访问次数: {{ count }}</p>
<button @click="increment">
增加
</button>
</div>
</template>
<script setup>
// Composition API - 无需导入
const count = ref(0);
const title = computed(() => `计数器: ${count.value}`);
// 响应式系统自动处理依赖
function increment() {
count.value++;
}
// 生命周期钩子
onMounted(() => {
console.log('组件已挂载');
});
</script>
提供极速的开发体验和高效的生产构建,是 Nuxt4 性能优势的重要支撑。
极速热重载
- 毫秒级的文件更新
- 保持应用状态
- 精确的模块更新
- 优化的开发体验
现代化构建
- ESM 原生支持
- 按需编译
- 智能代码分割
- 优化的生产构建
// Vite 配置示例
export default defineNuxtConfig({
vite: {
// 开发服务器配置
server: {
hmr: {
port: 24678, // 热重载端口
host: 'localhost'
}
},
// 构建优化
build: {
// 代码分割策略
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router'],
'ui-vendor': ['@headlessui/vue', '@heroicons/vue']
}
}
},
// 压缩配置
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
},
// 插件配置
plugins: [
// 自动导入优化
AutoImport({
imports: ['vue', 'vue-router', '@vueuse/core']
})
]
}
});
统一的服务器运行时,支持多种部署环境和渲染策略,是 Nuxt4 全栈能力的核心。
Universal 渲染
- SSR/SSG/SPA 统一支持
- 智能渲染策略
- 自动优化性能
- 边缘计算支持
// Nitro 配置示例
export default defineNuxtConfig({
nitro: {
// 预渲染配置
prerender: {
routes: ['/sitemap.xml', '/robots.txt', '/'],
ignore: ['/admin/**', '/api/**']
},
// 压缩配置
compressPublicAssets: true,
// 服务器中间件
serverHandlers: [
{
route: '/api/health',
handler: '~/server/api/health.get.ts'
}
],
// 部署预设
preset: 'node-server', // 或 'vercel', 'netlify', 'cloudflare'
// 实验性功能
experimental: {
wasm: true // WebAssembly 支持
}
},
// 路由规则
routeRules: {
// 静态页面
'/': { prerender: true },
'/about': { prerender: true },
// ISR 页面
'/blog/**': { isr: 60 },
'/products/**': { isr: 3600 },
// SPA 页面
'/admin/**': { ssr: false },
'/dashboard/**': { ssr: false },
// API 路由
'/api/**': {
cors: true,
headers: { 'cache-control': 's-maxage=60' }
}
}
});
提供现代化的 JavaScript 工具集,实现自动化和类型安全,是 Nuxt4 开发体验的关键。
自动导入系统
- 组件自动发现
- Composables 自动导入
- 工具函数自动导入
- 第三方库自动导入
类型安全保障
- 端到端类型推断
- 自动类型生成
- 运行时类型检查
- IDE 智能提示
// UnJS 工具链配置示例
export default defineNuxtConfig({
// 自动导入配置
imports: {
dirs: [
// 自动导入目录
'composables',
'composables/*/index.{ts,js,mjs,mts}',
'composables/**',
'utils/**'
]
},
// 组件自动导入
components: [
{
path: '~/components',
// 启用前缀
prefix: 'App'
},
{
path: '~/components/ui',
// 全局组件
global: true
}
],
// 类型生成
typescript: {
typeCheck: true, // 构建时类型检查
strict: true, // 严格模式
// 自定义类型
tsConfig: {
compilerOptions: {
strict: true,
noImplicitAny: true
}
}
},
// 自动导入第三方库
auto: {
imports: [
// Vue 生态
'vue',
'vue-router',
'@vueuse/core',
'pinia',
// 工具库
'lodash-es',
'dayjs',
// 自定义导入
{
'my-lib': ['myFunction', 'myOtherFunction']
}
]
}
});
基于文件结构自动生成路由,简化路由配置,提高开发效率。
pages/
├── index.vue # → /
├── about.vue # → /about
├── blog/
│ ├── index.vue # → /blog
│ ├── [slug].vue # → /blog/:slug
│ └── [...slug].vue # → /blog/:slug*
└── user/
├── index.vue # → /user
├── [id].vue # → /user/:id
└── settings.vue # → /user/settings
高级路由特性:
<!-- pages/user/[id].vue -->
<template>
<div>
<h1>用户详情</h1>
<p>用户ID: {{ $route.params.id }}</p>
</div>
</template>
<script setup>
// 自动获取路由参数
const route = useRoute();
const userId = route.params.id;
// 数据获取
const { data: user } = await useFetch(`/api/users/${userId}`);
</script>
pages/
├── user/
│ ├── index.vue # /user
│ ├── [id].vue # /user/:id
│ └── [id]/
│ ├── profile.vue # /user/:id/profile
│ └── settings.vue # /user/:id/settings
└── user.vue # 父级布局
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const user = useAuthUser();
if (!user.value) {
return navigateTo('/login');
}
});
提供完整的后端开发能力,实现真正的全栈开发体验。
// server/api/users.get.ts - RESTful API
export default defineEventHandler(async (event) => {
const query = getQuery(event);
const users = await getUsersFromDB(query);
return {
users,
total: users.length,
pagination: {
page: query.page || 1,
limit: query.limit || 10
}
};
});
// server/api/users.post.ts - 创建用户
export default defineEventHandler(async (event) => {
const body = await readBody(event);
// 验证数据
const validation = await validateUser(body);
if (!validation.success) {
throw createError({
statusCode: 400,
statusMessage: validation.error
});
}
// 创建用户
const user = await createUser(body);
return { user };
});
// server/middleware/auth.ts - 认证中间件
export default defineEventHandler(async (event) => {
// 跳过公共 API
if (event.node.req.url?.startsWith('/api/public/')) {
return;
}
// 验证用户身份
const token = getCookie(event, 'auth-token');
if (!token) {
throw createError({
statusCode: 401,
statusMessage: 'Unauthorized'
});
}
// 验证 token
try {
const user = await verifyToken(token);
event.context.user = user;
} catch (error) {
throw createError({
statusCode: 401,
statusMessage: 'Invalid token'
});
}
});
// server/api/database.ts - 数据库操作
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
const method = getMethod(event);
switch (method) {
case 'GET':
return await prisma.user.findMany();
case 'POST': {
const body = await readBody(event);
return await prisma.user.create({
data: body
});
}
default:
throw createError({
statusCode: 405,
statusMessage: 'Method not allowed'
});
}
});
组成部分 | 主要作用 | 核心特性 | 开发价值 |
---|
Vue 3 核心层 | 前端响应式基础 | • Composition API • 响应式系统 3.0 • 组件系统升级 | 现代化开发体验 |
Vite 构建引擎 | 极速构建工具 | • 毫秒级热重载 • ESM 原生支持 • 智能代码分割 | 开发效率提升 |
Nitro 服务器引擎 | 统一服务器运行时 | • 多种渲染模式 • API 路由系统 • 边缘计算支持 | 全栈开发能力 |
UnJS 工具链 | 自动化工具集 | • 自动导入系统 • 类型安全保障 • 约定优于配置 | 开发体验优化 |
文件系统路由 | 自动路由生成 | • 动态路由 • 嵌套路由 • 路由中间件 | 路由配置简化 |
服务器端功能 | 后端开发支持 | • API 路由 • 服务器中间件 • 数据库集成 | 全栈一体化 |
// nuxt.config.ts
export default defineNuxtConfig({
ssr: true, // 默认启用 SSR
routeRules: {
// 特定页面的渲染策略
'/admin/**': { ssr: false }, // SPA 模式
'/blog/**': { isr: 60 }, // ISR 模式
}
});
- 🚀 更快的首屏加载
- 🔍 更好的 SEO 效果
- 🎯 更佳的用户体验
- 📱 移动端友好
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
prerender: {
routes: ['/sitemap.xml', '/robots.txt']
}
}
});
- ⚡ 极速加载速度
- 💰 更低的服务器成本
- 🔒 更高的安全性
- 🌐 CDN 友好
// nuxt.config.ts
export default defineNuxtConfig({
ssr: false, // 全局 SPA 模式
// 或者按路由配置
routeRules: {
'/app/**': { ssr: false }
}
});
- 🎮 更流畅的交互体验
- 📊 适合复杂的应用逻辑
- 🔄 减少服务器负载
- 💾 更好的缓存策略
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/blog/**': { isr: 60 }, // 60秒缓存
'/products/**': { isr: 3600 }, // 1小时缓存
}
});
- 🔄 自动内容更新
- ⚡ 静态文件速度
- 🎯 按需重新生成
- 📈 可扩展性强
<!-- 无需手动导入 -->
<template>
<div>
<!-- 组件自动导入 -->
<UiButton @click="handleLogin">
登录
</UiButton>
<BaseModal v-model="showModal">
<LoginForm @success="onLoginSuccess" />
</BaseModal>
</div>
</template>
<script setup>
// Composables 自动导入
const user = useAuthUser();
const { login } = useAuth();
const router = useRouter();
const { $toast } = useNuxtApp();
// 工具函数自动导入
const formatDate = date => useDateFormat(date, 'YYYY-MM-DD');
const debounced = useDebounce(searchQuery, 300);
// 第三方库自动导入
const { copy } = useClipboard();
const { pause, resume } = useIntervalFn(() => {
// 定时任务
}, 1000);
const showModal = ref(false);
async function handleLogin() {
try {
await login(credentials);
$toast.success('登录成功');
router.push('/dashboard');
} catch (error) {
$toast.error('登录失败');
}
}
</script>
<!-- pages/posts/[id].vue -->
<template>
<article>
<h1>{{ post.title }}</h1>
<div v-html="post.content" />
<CommentSection :comments="comments" />
</article>
</template>
<script setup>
const route = useRoute();
const postId = route.params.id;
// 并行数据获取
const [
{ data: post },
{ data: comments }
] = await Promise.all([
useFetch(`/api/posts/${postId}`),
useFetch(`/api/posts/${postId}/comments`)
]);
// 动态 SEO
useSeoMeta({
title: post.value.title,
description: post.value.excerpt
});
</script>
<!-- components/UserProfile.vue -->
<template>
<div>
<div v-if="pending">
<LoadingSkeleton />
</div>
<div v-else-if="error">
<ErrorMessage :error="error" />
</div>
<div v-else>
<h2>{{ user.name }}</h2>
<p>{{ user.bio }}</p>
</div>
</div>
</template>
<script setup>
const props = defineProps<{
userId: string;
}>();
// 客户端数据获取
const { data: user, pending, error, refresh } = await useLazyFetch(
`/api/users/${props.userId}`,
{
server: false, // 仅在客户端执行
key: `user-${props.userId}` // 缓存键
}
);
</script>
<!-- pages/dashboard.vue -->
<template>
<div>
<!-- 服务端数据 - 首屏关键信息 -->
<DashboardHeader :user="user" :stats="stats" />
<!-- 客户端数据 - 非关键信息 -->
<LazyDashboardCharts />
<LazyRecentActivities />
</div>
</template>
<script setup>
// 定义页面元数据
definePageMeta({
middleware: 'auth'
});
// 服务端获取关键数据
const { data: user } = await useFetch('/api/user');
const { data: stats } = await useFetch('/api/dashboard/stats');
// 客户端获取非关键数据
const { data: activities } = await useLazyFetch('/api/activities', {
server: false
});
</script>
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
// 静态页面缓存
'/': {
prerender: true,
headers: { 'cache-control': 's-maxage=31536000' }
},
// 动态页面缓存
'/blog/**': {
isr: 60,
headers: { 'cache-control': 's-maxage=60' }
},
// API 缓存
'/api/public/**': {
cors: true,
headers: { 'cache-control': 's-maxage=300' }
},
// 禁用缓存
'/api/private/**': {
headers: { 'cache-control': 'no-cache' }
}
}
});
极速开发
- 基于 Vite 的毫秒级热重载
- 零配置 TypeScript 支持
- 自动导入减少样板代码
- 内置开发者工具
智能提示
- 端到端类型推断
- 路由类型安全
- 自动补全和错误检查
- 智能重构支持
模块化架构
- 可插拔的模块系统
- 灵活的插件机制
- 组件自动发现
- 约定优于配置
性能指标 | 传统 Vue SPA | Nuxt4 SSR | 提升幅度 |
---|
首屏加载时间 | 2-5秒 | 0.5-1秒 | 🚀 70-80% |
SEO 友好度 | 低 | 高 | 📈 显著提升 |
构建速度 | 基准 | 3-5x 更快 | ⚡ 300-500% |
开发热重载 | 1-3秒 | 200ms | 🔥 85-90% |
包体积 | 基准 | 减少 20-30% | 📦 25% |
Nuxt4-project/
├── assets/ # 静态资源
├── components/ # Vue 组件
├── composables/ # 组合式函数
├── layouts/ # 布局组件
├── middleware/ # 路由中间件
├── pages/ # 路由页面
├── plugins/ # 插件
├── public/ # 公共文件
├── server/ # 服务器端代码
│ ├── api/ # API 路由
│ └── middleware/ # 服务器中间件
├── stores/ # 状态管理
└── nuxt.config.ts # 配置文件
// 灵活的渲染配置
export default defineNuxtConfig({
routeRules: {
// 首页预渲染
'/': { prerender: true },
// 博客增量静态再生
'/blog/**': { isr: 60 },
// 管理后台SPA模式
'/admin/**': { ssr: false },
// API路由
'/api/**': { cors: true }
}
});
// 丰富的模块生态
export default defineNuxtConfig({
modules: [
'@nuxt/ui', // UI 组件库
'@nuxt/image', // 图片优化
'@nuxt/content', // 内容管理
'@pinia/nuxt', // 状态管理
'@nuxtjs/i18n', // 国际化
'@nuxtjs/seo' // SEO 优化
]
});
Nuxt4 与 Vue 3 的关系可以用"血脉相连"来形容。Nuxt4 不是简单地使用 Vue 3,而是深度集成和扩展了 Vue 3 的能力。
核心关系: Nuxt4 = Vue 3 + 全栈开发能力 + 最佳实践 + 开发者体验优化
<!-- 标准 Vue 3 组件 -->
<template>
<div>
<h1>{{ title }}</h1>
<button @click="increment">
{{ count }}
</button>
</div>
</template>
<script setup>
import { computed, onMounted, ref } from 'vue';
const count = ref(0);
const title = computed(() => `计数: ${count.value}`);
function increment() {
count.value++;
}
onMounted(() => {
console.log('组件已挂载');
});
</script>
<!-- Nuxt4 组件 - 无需导入 -->
<template>
<div>
<h1>{{ title }}</h1>
<button @click="increment">
{{ count }}
</button>
<UserProfile :user="user" />
</div>
</template>
<script setup>
// 无需导入 Vue 3 API,自动可用
const count = ref(0);
const title = computed(() => `计数: ${count.value}`);
// Nuxt4 特有的数据获取
const { data: user } = await useFetch('/api/user');
// 自动导入的组合式函数
const { locale } = useI18n();
const router = useRouter();
function increment() {
count.value++;
}
onMounted(() => {
console.log('组件已挂载');
});
</script>
<template>
<div>
<!-- 响应式数据绑定 -->
<input v-model="searchQuery" placeholder="搜索...">
<!-- 计算属性 -->
<p>搜索结果: {{ filteredResults.length }} 条</p>
<!-- 响应式列表渲染 -->
<ul>
<li v-for="item in filteredResults" :key="item.id">
{{ item.name }}
</li>
</ul>
</div>
</template>
<script setup>
// 响应式数据
const searchQuery = ref('');
const items = ref([]);
// 计算属性 - 自动依赖收集
const filteredResults = computed(() => {
if (!searchQuery.value)
return items.value;
return items.value.filter(item =>
item.name.toLowerCase().includes(searchQuery.value.toLowerCase())
);
});
// 侦听器 - 响应式更新
watch(searchQuery, (newQuery) => {
console.log('搜索词更新:', newQuery);
});
// 数据获取
const { data } = await useFetch('/api/items');
items.value = data.value;
</script>
<!-- components/UserCard.vue -->
<template>
<div class="user-card">
<img :src="user.avatar" :alt="user.name">
<h3>{{ user.name }}</h3>
<p>{{ user.bio }}</p>
<!-- 插槽支持 -->
<slot name="actions" :user="user" />
</div>
</template>
<script setup>
// 类型安全的 Props
interface User {
id: number;
name: string;
avatar: string;
bio: string;
}
const props = defineProps<{
user: User;
}>();
// 事件定义
const emit = defineEmits<{
follow: [userId: number];
unfollow: [userId: number];
}>();
</script>
<!-- pages/users.vue -->
<template>
<div>
<!-- 自动导入的组件 -->
<UserCard
v-for="user in users"
:key="user.id"
:user="user"
@follow="handleFollow"
>
<template #actions="{ user }">
<button @click="followUser(user.id)">
关注
</button>
</template>
</UserCard>
</div>
</template>
<script setup>
const { data: users } = await useFetch('/api/users');
function handleFollow(userId: number) {
// 关注逻辑
console.log('关注用户:', userId);
}
</script>
<!-- pages/product/[id].vue -->
<template>
<div>
<h1>{{ product.name }}</h1>
<p>{{ product.description }}</p>
<img :src="product.image" :alt="product.name">
<!-- 客户端交互 -->
<button :disabled="loading" @click="addToCart">
{{ loading ? '添加中...' : '加入购物车' }}
</button>
</div>
</template>
<script setup>
const route = useRoute();
const productId = route.params.id;
// 服务端数据获取 - SEO友好
const { data: product } = await useFetch(`/api/products/${productId}`);
// 客户端状态
const loading = ref(false);
// 客户端交互
async function addToCart() {
loading.value = true;
try {
await $fetch('/api/cart/add', {
method: 'POST',
body: { productId: product.value.id }
});
// 显示成功消息
await useToast().success('已添加到购物车');
} finally {
loading.value = false;
}
}
// 动态SEO
useSeoMeta({
title: product.value.name,
description: product.value.description,
ogImage: product.value.image
});
</script>
// server/api/products/[id].get.ts
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id');
// 数据库查询
const product = await getProductById(id);
if (!product) {
throw createError({
statusCode: 404,
statusMessage: 'Product not found'
});
}
return product;
});
// server/middleware/auth.ts
export default defineEventHandler(async (event) => {
// 跳过公共路由
if (event.node.req.url?.startsWith('/api/public/')) {
return;
}
// 验证 JWT token
const token = getCookie(event, 'auth-token');
if (!token) {
throw createError({
statusCode: 401,
statusMessage: 'Unauthorized'
});
}
try {
const user = await verifyToken(token);
event.context.user = user;
} catch (error) {
throw createError({
statusCode: 401,
statusMessage: 'Invalid token'
});
}
});
pages/
├── index.vue # → /
├── about.vue # → /about
├── blog/
│ ├── index.vue # → /blog
│ ├── [slug].vue # → /blog/:slug
│ └── category/
│ └── [name].vue # → /blog/category/:name
└── user/
├── index.vue # → /user
├── [id].vue # → /user/:id
└── [id]/
└── settings.vue # → /user/:id/settings
// nuxt.config.ts
export default defineNuxtConfig({
// 自动导入配置
imports: {
dirs: [
'composables',
'composables/*/index.{ts,js,mjs,mts}',
'composables/**'
]
},
// 组件自动导入
components: [
{
path: '~/components',
pathPrefix: false,
// 全局组件
global: true
}
]
});
// 自动生成的类型
declare module '#app' {
interface NuxtApp {
$toast: {
success: (message: string) => void;
error: (message: string) => void;
};
}
}
// 路由类型
declare module 'vue-router' {
interface RouteMeta {
requiresAuth?: boolean;
title?: string;
}
}
import vue from '@vitejs/plugin-vue';
import { createPinia } from 'pinia';
// 需要手动配置构建工具
// vite.config.js
import { defineConfig } from 'vite';
// main.js
import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
// 手动配置路由
const routes = [
{ path: '/', component: () => import('./pages/Home.vue') },
{ path: '/about', component: () => import('./pages/About.vue') }
];
const router = createRouter({
history: createWebHistory(),
routes
});
const pinia = createPinia();
const app = createApp(App);
app.use(router);
app.use(pinia);
app.mount('#app');
export default defineConfig({
plugins: [vue()],
// 大量配置...
});
// nuxt.config.ts
export default defineNuxtConfig({
// 零配置,开箱即用
devtools: { enabled: true }
});
// 页面自动路由
// pages/index.vue → /
// pages/about.vue → /about
// 自动导入
// components/ 目录下的组件自动导入
// composables/ 目录下的函数自动导入
// stores/ 目录下的状态管理自动导入
功能特性 | Vue 3 原生 | Nuxt4 |
---|
路由系统 | 手动配置 Vue Router | 文件系统自动路由 |
状态管理 | 手动配置 Pinia/Vuex | 自动导入 + 类型安全 |
构建工具 | 手动配置 Vite/Webpack | 零配置 Vite |
TypeScript | 需要配置 | 开箱即用 |
SSR/SSG | 需要额外配置 | 内置多种渲染模式 |
开发服务器 | 需要配置 | 自动配置 |
热重载 | 基础支持 | 极速热重载 |
SEO优化 | 手动处理 | 自动化SEO |
选择 Nuxt4 的场景
- 需要 SSR/SSG 的项目
- 要求快速开发迭代
- 团队经验相对较少
- 需要 SEO 优化
- 全栈开发需求
- 企业级应用开发
选择 Vue 3 原生的场景
- 纯客户端应用
- 需要极致的定制化
- 现有项目迁移
- 团队有丰富经验
- 特殊的构建需求
- 库/组件开发
Nuxt4 引入了全新的 app/
目录结构,提供更好的组织和 IDE 性能:
Nuxt4 项目结构:
├── app/ # 新增:应用代码目录
│ ├── components/ # Vue 组件
│ ├── composables/ # 组合式函数
│ ├── layouts/ # 布局文件
│ ├── middleware/ # 路由中间件
│ ├── pages/ # 页面文件
│ ├── plugins/ # 插件
│ └── utils/ # 工具函数
├── server/ # 服务器端代码
├── public/ # 静态资源
└── nuxt.config.ts # 配置文件
迁移提示: 现有的项目结构仍然有效,但推荐逐步迁移到新的 app/
目录以获得更好的开发体验。
Nuxt4 对数据获取层进行了重大改进:
所有使用相同 key 的 useAsyncData
或 useFetch
调用现在共享底层的 refs:
<!-- ComponentA.vue -->
<script setup>
const { data: users, pending } = useAsyncData('users', fetchUsers);
</script>
<!-- ComponentB.vue -->
<script setup>
// 这将引用与 ComponentA 相同的数据状态
const { data: users, status } = useAsyncData('users', fetchUsers);
// 当任一组件刷新数据时,两者都会一致更新
</script>
现在支持使用计算属性、ref 或 getter 函数作为 key:
const userId = ref('123');
const { data: user } = useAsyncData(
computed(() => `user-${userId.value}`),
() => fetchUser(userId.value)
);
// 改变 userId 将自动触发新的数据获取
// 如果没有其他组件使用旧数据,会自动清理
userId.value = '456';
SSR 安全的时间显示组件,解决日期处理的水合不匹配问题:
<template>
<div>
<!-- 基础用法 -->
<NuxtTime :datetime="Date.now()" />
<!-- 自定义格式 -->
<NuxtTime
:datetime="post.createdAt"
:format="{
year: 'numeric',
month: 'long',
day: 'numeric',
}"
/>
</div>
</template>
提供更好的错误处理和恢复机制:
<NuxtErrorBoundary @error="handleError">
<template #error="{ error, clearError }">
<div class="error-container">
<h2>出错了!</h2>
<p>{{ error.message }}</p>
<button @click="clearError">重试</button>
</div>
</template>
<!-- 可能出错的内容 -->
<MyComponent />
</NuxtErrorBoundary>
- 切换到
tinyglobby
实现更快的文件匹配 - 排除
.data
目录进行类型检查 - 改进的 tree-shaking 机制
- 优化的数据重新获取机制
- 减少内存占用
- 更智能的缓存策略
// 自动优化的数据获取
const { data } = useAsyncData(
'users',
() => $fetch(`/api/users?page=${route.query.page}`),
{ watch: [() => route.query.page] }
);
// 当 route.query.page 改变时,只会发生一次获取操作
// 所有使用此 key 的组件会同时更新
- 服务器组件缺少根元素时的警告
- 使用保留
runtimeConfig.app
命名空间时的警告 - 重写核心自动导入预设时的警告
// 新的模块兼容性检查
export default defineNuxtConfig({
experimental: {
enforceModuleCompatibility: true // Nuxt v4 中默认启用
}
});
// 自动注册组件导出
export default defineNuxtModule({
setup(options, nuxt) {
// 自动注册文件中的所有命名导出组件
addComponentExports({
filePath: '~/components/MyComponents.ts'
});
}
});
通过本章学习,全面了解了:
- Nuxt4 当前状态 - Alpha 版本已发布,稳定版预计 2025 年底
- 测试方法 - 兼容性标志和 Alpha 版本安装
- 核心特性 - 多种渲染模式、自动导入、智能缓存等
- 重大更新 - 新目录结构、改进数据获取、增强组件
- 技术优势 - 开发体验、性能表现、架构设计的全面提升
- 与 Vue3 关系 - 深度集成、扩展增强、最佳实践
- 理解 Nuxt4 的核心价值和适用场景
- 掌握如何测试和体验 Nuxt4 新特性
- 了解 Nuxt4 相比 Vue 3 原生开发的优势
- 具备技术选型的决策能力
- 熟悉 Nuxt4 的开发模式和最佳实践
- 了解新的
app/
目录结构 - 掌握改进的数据获取机制
- 熟悉增强的内置组件
- 理解性能优化改进
- 准备逐步迁移策略
展望未来: Nuxt 4 带来了激动人心的改进,建议在开发环境中测试新特性,为未来的正式迁移做好准备。