引言

Nuxt 4标志着Vue全栈开发框架的重大进化。作为基于Vue 3的通用框架,Nuxt 4在性能、开发体验和可扩展性方面都带来了显著改进。本文将深入探讨Nuxt 4的核心新特性、架构变化以及如何从Nuxt 3平滑迁移。

一、Nuxt 4核心变化概览

1.1 主要更新内容

类别更新内容影响等级
项目结构新的目录结构约定高
服务端引擎Nitro 2.0性能提升高
TypeScript类型系统全面增强中
开发体验开发服务器热更新优化中
配置系统简化的配置选项低
性能优化构建产物体积减小高

1.2 版本对比

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Nuxt 3 配置
// nuxt.config.ts
export default defineNuxtConfig({
  typescript: {
    strict: true,
    typeCheck: true
  },
  app: {
    head: {
      title: 'My App',
      meta: [
        { name: 'viewport', content: 'width=device-width' }
      ]
    }
  }
})

// Nuxt 4 配置(更简洁)
// nuxt.config.ts
export default defineNuxtConfig({
  compatibilityDate: '2024-12-01',
  future: {
    compatibilityVersion: 4
  },
  app: {
    title: 'My App',
    viewport: 'width=device-width'
  }
})

二、新的项目结构

2.1 目录结构变化

Nuxt 3结构

nuxt3-project/
├── .nuxt/
├── assets/
├── components/
├── composables/
├── layouts/
├── middleware/
├── pages/
├── plugins/
├── public/
├── server/
│   ├── api/
│   ├── middleware/
│   └── routes/
├── server.ts
├── app.vue
└── nuxt.config.ts

Nuxt 4结构

nuxt4-project/
├── .nuxt/
├── app/
│   ├── components/      # 组件目录
│   ├── composables/     # 组合式函数
│   ├── layouts/         # 布局
│   ├── middleware/      # 中间件
│   ├── pages/           # 页面
│   ├── plugins/         # 插件
│   └── vue-app.ts      # 应用入口(可选)
├── assets/
├── public/
├── server/              # 服务端代码
│   ├── api/
│   ├── middleware/
│   └── routes/
├── nuxt.config.ts
└── package.json

2.2 使用新结构

1
2
3
4
5
6
7
8
9
// nuxt.config.ts 启用新结构
export default defineNuxtConfig({
  _experimental: {
    workspace: true  // 启用新的app目录结构
  }
})

// 组件现在位于 app/components/
// 页面现在位于 app/pages/

2.3 路由配置变化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!-- app/pages/index.vue -->
<template>
  <div>
    <h1>Welcome to Nuxt 4</h1>
  </div>
</template>

<!-- app/pages/blog/[slug].vue -->
<template>
  <div>
    <h1>{{ route.params.slug }}</h1>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
</script>

三、Nitro 2.0服务端引擎

3.1 性能提升

冷启动优化

1
2
3
4
5
6
7
8
9
// server/api/hello.ts
export default defineEventHandler((event) => {
  return { message: 'Hello from Nuxt 4!' }
})

// Nuxt 4中Nitro 2.0的改进:
// - 更快的冷启动时间(减少30-50%)
// - 优化的边缘运行时支持
// - 更好的并发处理

3.2 新增服务端功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// server/api/users.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event)

  // 自动类型推断
  const user = {
    name: body.name,
    email: body.email
  }

  return user
})

// server/api/users/[id].delete.ts
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, 'id')

  // 使用改进的数据库工具
  await useDatabase().delete(id)

  return { success: true }
})

3.3 存储层增强

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// server/api/cache.ts
export default defineEventHandler(async (event) => {
  const storage = useStorage()

  // 新的缓存API
  await storage.setItem('key', { data: 'value' }, {
    ttl: 3600  // 自动过期
  })

  const value = await storage.getItem('key')

  return { cached: value }
})

四、TypeScript增强

4.1 更好的类型推断

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 自动类型推断的composables
// composables/useUser.ts
export const useUser = () => {
  const user = useState('user', () => ({
    name: '',
    email: '',
    role: 'user' as 'user' | 'admin' | 'guest'
  }))

  const isAdmin = computed(() => user.value.role === 'admin')

  return {
    user: readonly(user),
    isAdmin
  }
}

// 使用时自动推断类型
// <script setup lang="ts">
const { user, isAdmin } = useUser()
// user类型自动推断为 ReadonlyRef<...>
// isAdmin类型自动推断为 ComputedRef<boolean>
// </script>

4.2 类型安全路由

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 类型安全的路由跳转
navigateTo({
  name: 'blog-slug',
  params: {
    slug: 'my-post'  // 类型检查
  }
})

// 类型安全的参数获取
const route = useRoute<'blog-slug'>()
route.params.slug  // 类型为 string

4.3 组件类型增强

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!-- components/UserCard.vue -->
<script setup lang="ts">
interface Props {
  user: {
    name: string
    email: string
  }
  size?: 'sm' | 'md' | 'lg'
}

const props = withDefaults(defineProps<Props>(), {
  size: 'md'
})

defineEmits<{
  click: [user: Props['user']]
}>()
</script>

五、开发体验改进

5.1 热模块替换优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// nuxt.config.ts
export default defineNuxtConfig({
  vite: {
    // 改进的HMR配置
    server: {
      hmr: {
        protocol: 'ws',
        host: 'localhost',
        port: 24678
      }
    }
  }
})

5.2 开发工具集成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// nuxt.config.ts
export default defineNuxtConfig({
  devtools: {
    enabled: true,

    // 新的devtools功能
    timeline: {
      enabled: true  // 性能时间线
    },
    componentInspector: true  // 组件检查器
  }
})

5.3 调试增强

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 使用新的调试工具
// app/vue-app.ts
import { setupDevtools } from '@nuxt/devtools'

if (process.env.NODE_ENV === 'development') {
  setupDevtools({
    // 自定义调试面板
    panels: [
      {
        name: 'My Panel',
        component: () => import('./components/DevPanel.vue')
      }
    ]
  })
}

六、性能优化

6.1 构建优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// nuxt.config.ts
export default defineNuxtConfig({
  // 自动优化
  experimental: {
    inlineSSRStyles: false,  // 内联SSR样式
    renderSubResources: true  // 子资源预渲染
  },

  vite: {
    build: {
      rollupOptions: {
        output: {
          manualChunks: {
            'vue-vendor': ['vue', 'vue-router', 'pinia'],
            'ui': ['@nuxtjs/ui']
          }
        }
      }
    }
  }
})

6.2 图片优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
  <!-- 自动优化 -->
  <NuxtImg
    src="/image.jpg"
    width="600"
    height="400"
    format="webp"
    loading="lazy"
    placeholder
  />

  <!-- 新增:响应式图片 -->
  <NuxtPicture
    src="/hero.jpg"
    :sizes="{
      mobile: 400,
      tablet: 800,
      desktop: 1200
    }"
  />
</template>

6.3 数据获取优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// useLazyAsyncData 非阻塞加载
const { data, pending } = useLazyAsyncData('users', () =>
  $fetch('/api/users')
)

// useFetch 带智能缓存
const { data, refresh } = await useFetch('/api/posts', {
  // 新的缓存选项
  getCachedData: (key) => useNuxtData(key).data,
  transform: (input) => input.reverse(),
  watch: [searchTerm]  // 自动重新获取
})

七、从Nuxt 3迁移

7.1 迁移步骤

第一步:更新依赖

1
2
3
4
5
# 卸载旧版本
npm uninstall nuxt

# 安装Nuxt 4
npm install nuxt@4

第二步:更新配置

1
2
3
4
5
6
7
// nuxt.config.ts
export default defineNuxtConfig({
  compatibilityDate: '2024-12-01',
  future: {
    compatibilityVersion: 4
  }
})

第三步:运行迁移检查

1
2
npx nuxi upgrade
npx nuxi typecheck

7.2 破坏性变化

变化Nuxt 3Nuxt 4
head属性app.headapp配置项
publicPath未支持app.baseURL
plugins顺序按文件名按配置
fetch弃用useFetch仅$fetch
asyncData弃用useAsyncData仅useAsyncData

7.3 迁移示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// Nuxt 3
export default defineNuxtConfig({
  app: {
    head: {
      title: 'My App',
      htmlAttrs: { lang: 'en' }
    }
  }
})

// Nuxt 4
export default defineNuxtConfig({
  app: {
    title: 'My App',
    lang: 'en'
  }
})

八、最佳实践

8.1 项目组织

1
2
3
4
5
6
7
8
9
// 使用新的app目录
app/
├── components/       # 通用组件
│   ├── common/      # 基础组件
│   └── features/    # 功能组件
├── composables/     # 可复用逻辑
├── layouts/         # 布局
├── pages/           # 页面
└── utils/           # 工具函数

8.2 状态管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// composables/useAuth.ts
export const useAuth = () => {
  const user = useState<User | null>('auth-user', () => null)
  const token = useCookie('auth-token')

  const login = async (credentials: Credentials) => {
    const data = await $fetch('/api/login', {
      method: 'POST',
      body: credentials
    })

    user.value = data.user
    token.value = data.token
  }

  const logout = () => {
    user.value = null
    token.value = null
  }

  return {
    user: readonly(user),
    token,
    login,
    logout,
    isAuthenticated: computed(() => !!user.value)
  }
}

8.3 SEO优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- app/pages/blog/[slug].vue -->
<script setup lang="ts">
const route = useRoute()
const { data: post } = await useFetch(`/api/blog/${route.params.slug}`)

useSeoMeta({
  title: post.value?.title,
  description: post.value?.excerpt,
  ogTitle: post.value?.title,
  ogImage: post.value?.cover,
  twitterCard: 'summary_large_image'
})

useHead({
  link: [
    {
      rel: 'canonical',
      href: `https://example.com/blog/${route.params.slug}`
    }
  ]
})
</script>

总结

Nuxt 4带来了全面的改进:

  1. 新的项目结构 - 更清晰的代码组织
  2. Nitro 2.0 - 更快的服务端性能
  3. TypeScript增强 - 更好的开发体验
  4. 性能优化 - 更小的构建体积
  5. 平滑迁移 - 兼容性支持

从Nuxt 3升级到Nuxt 4是值得的投资,带来的性能提升和开发体验改进将显著提高项目质量。

相关工具推荐