Release·  

Nuxt 4.4

Nuxt 4.4 带来了自定义的 useFetch/useAsyncData 工厂、vue-router v5、新的无障碍播报器、类型化的布局 props、构建性能分析、更智能的 payload 处理,以及更多功能。
Daniel Roe

Daniel Roe

@danielroe.dev

🏭 createUseFetchcreateUseAsyncData

现在你可以使用自己的默认选项创建 自定义实例useFetchuseAsyncData 了(#32300)。

composables/api.ts
// 简单默认值
export const useClientFetch = createUseFetch({
  server: false,
})

// 带完整合并控制的动态默认值
export const useApiFetch = createUseFetch((currentOptions) => {
  const runtimeConfig = useRuntimeConfig()

  return {
    ...currentOptions,
    baseURL: currentOptions.baseURL ?? runtimeConfig.public.baseApiUrl,
  }
})

然后像使用 useFetch 一样使用它们 – 它们具有完整类型支持,并支持所有相同的选项:

pages/dashboard.vue
<script setup lang="ts">
// 自动使用 runtimeConfig 中的 baseURL
const { data: users } = await useApiFetch('/users')
</script>

当你传入一个普通对象时,你的使用选项会自动覆盖默认值。当你传入一个函数时,你可以完全控制选项如何合并 – 这意味着你可以按需要组合拦截器、请求头以及其他复杂选项。

在底层,这由一个新的 Nuxt 临时模块驱动,它会扫描你的 composables 目录,并自动为 key 注入注册你的自定义实例 – 因此它们可以像 useAsyncDatauseFetch 一样,和 SSR 无缝配合。

createUseAsyncData 也提供了同样的模式,用于 useAsyncData

Docs > API > Composables > Create Use Async Data 中查看详情

🗺️ Vue Router v5

我们已经升级到 vue-router v5#34181),并移除了对 unplugin-vue-router 的依赖。这是自 Nuxt 3 以来首次重大升级 vue-router,它在底层带来了许多改进。

对大多数应用来说,这应该是一次透明升级。如果你直接使用了 unplugin-vue-router,可以将它从依赖中移除。

下一步将是把类型化路由从实验状态中移出。👀

💪 definePageMeta 中的类型化布局 Props

现在你可以直接从 definePageMeta 向布局传递 props 了(#34262)。这意味着你的布局可以按页面参数化,而不需要使用 provide/inject 或其他变通方案。查看更新后的文档以了解完整细节。

pages/dashboard.vue
definePageMeta({
  layout: {
    name: 'panel',
    props: {
      sidebar: true,
      title: 'Dashboard',
    },
  },
})

更棒的是 – 这些 props 是完全类型化的(#34409)。如果你的布局定义了 props,你在 definePageMeta 中就会获得自动补全和类型检查。

layouts/panel.vue
<script setup lang="ts">
defineProps<{
  sidebar?: boolean
  title?: string
}>()
</script>
Docs > Guide > Directory Structure > Layouts 中查看详情

🗣️ useAnnouncer Composable

新的 useAnnouncer composable 和 <NuxtAnnouncer> 组件让无障碍支持得到了重大提升(#34318)。虽然 useRouteAnnouncer 负责屏幕阅读器的页面导航播报,但许多应用还需要播报页面内动态变化 – 表单提交、加载状态、搜索结果等等。

<template>
  <NuxtAnnouncer />
  <NuxtRouteAnnouncer />
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>
这是我们无障碍路线图的一部分。你不需要在所有地方都使用它 – 对于很多交互来说,把焦点移动到新内容上,或使用原生表单校验就已经足够了。useAnnouncer 在内容动态变化但没有相应焦点变化时最有用。
Docs > API > Composables > Use Announcer 中查看详情

🚀 迁移到 unrouting

我们已将 Nuxt 的文件系统路由生成迁移到 unrouting#34316),它使用 trie 数据结构来构建路由。冷启动时间大致相同(大型应用约 ~8ms 对 ~6ms),但在不新增/删除页面时,开发服务器变更速度最高快 28 倍,即使新增/删除页面时也仍然快约 ~15%。

这也让路由生成更加确定性 – 不再受页面文件顺序影响。

🍫 缓存路由的更智能 Payload 处理

当启用了 payload 提取的缓存路由(ISR/SWR)在运行时渲染时,浏览器会立即作为第二个请求获取 _payload.json – 这会触发同一页面的完整 SSR 重新渲染。在无服务器环境中,这甚至可能在第一次响应流还未结束时就启动第二个 lambda。

本次发布通过两项改动解决了这个问题(#34410):

  1. 新的 payloadExtraction: 'client' 模式会在初始 HTML 响应中内联完整 payload,同时仍然生成 _payload.json 供客户端导航使用
  2. 运行时内存 LRU payload 缓存,使 _payload.json 请求可以在不完整重渲染的情况下被响应
nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    payloadExtraction: 'client',
  },
})
payloadExtraction: 'client' 将在 compatibilityVersion: 5 时成为默认值。运行时缓存对所有用户都已启用。
Docs > Guide > Going Further > Experimental Features#payloadextraction 中查看详情

🍪 useCookierefresh 选项

如果你使用 cookie 进行会话管理,你大概遇到过这样的问题:需要在不改变 cookie 值的情况下延长其过期时间。新的 refresh 选项让这变得很简单(#33814):

const session = useCookie('session-id', {
  maxAge: 60 * 60,
  refresh: true,
})

// 每次都会延长过期时间,即使值相同
session.value = session.value
Docs > API > Composables > Use Cookie 中查看详情

♻️ useState 重置为默认值

useStateclearNuxtState 现在支持将状态重置为初始值,而不是清空为 undefined#33527)。这与 useAsyncData 的重置处理方式一致,也更符合状态管理的直觉。

const count = useState('counter', () => 0)
count.value = 42

// 重置为 0(初始值),而不是 undefined
clearNuxtState('counter')
Docs > API > Utils > Clear Nuxt State 中查看详情

🕵️‍♂️ 更好的导入保护

TanStack Start 中功能的启发,导入保护现在会显示建议以及问题导入来源的完整追踪#34454)。这让调试为什么仅服务端的导入最终进入了客户端 bundle 变得容易得多。

例如,如果你在组件中不小心从一个服务端路由导入:

追踪会显示导入链(该组件是从一个页面导入的)、精确的代码行,以及如何修复的可操作建议。

我们计划继续改进错误信息。🪵

🔮 View Transitions 类型

现在你可以在 Nuxt 的实验性视图过渡支持中定义 view transition types 了(#31982)。这让你可以针对不同的导航模式使用不同的过渡样式(前进 vs. 后退、标签页 vs. 页面,等等)。

Docs > Getting Started > Transitions#view Transitions API Experimental 中查看详情

💡 改进的 optimizeDeps 提示

当 Vite 在运行时发现新的依赖并触发页面刷新时,Nuxt 现在会显示一段清晰、可直接复制粘贴的 nuxt.config.ts 片段,用于预构建这些依赖(#34320)。它还会在启动时警告不可解析的条目。

🏷️ 规范化的页面组件名称(实验性)

一个新的实验性选项会将页面组件名称规范化,使其与路由名称一致(#33513),这有助于在 devtools 和调试中保持一致性。

nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    normalizeComponentNames: true,
  },
})
Docs > Guide > Going Further > Experimental Features#normalizecomponentnames 中查看详情

⚡ 构建性能分析

有没有想过你的构建时间都花到哪里去了?现在你可以获得 Nuxt 构建的详细性能分解了(#34468, nuxt/cli#1243):

nuxt build --profile

这会生成一份报告,展示每个构建阶段、模块和打包器插件的耗时、RSS 变化量以及 heap 变化量:

它还会对单个模块和打包器插件进行分析,方便你快速发现瓶颈。会写出三种输出格式:

  • Chrome Trace (.nuxt/perf-trace.json) – 在 chrome://tracing 或 Perfetto 中打开,可查看可视化时间线
  • JSON 报告 (.nuxt/perf-report.json) – 便于机器读取的数据,用于长期跟踪
  • CPU profile (nuxt-build.cpuprofile) – 可在 Chrome DevTools 或 VS Code 中打开以查看火焰图

如果想要更详细的信息,可以使用 --profile=verbose 在控制台输出更细粒度的时间分解。

Docs > API > Commands > Build 中查看详情

我们会使用这个功能让 Nuxt 变得更快 – 如果你也关心性能,这可能是一个很好的贡献机会!

🔥 性能改进

  • 模块 ID 解析速度提升 14,000 倍 – 使用单个 indexOf + slice 替换了 new URL() + 正则链 (#34451)
  • 在开发环境中禁用了 NuxtLink 可见性预取 – 阻止 Vite 在开发过程中不必要地发现并重新加载依赖项 (#34325)

⬆︎ 升级

我们建议通过以下命令进行升级:

npx nuxt upgrade --dedupe

这将去重你的 lockfile,并帮助确保你拉取到 Nuxt 所依赖的其他依赖项的更新,特别是在 unjs 生态系统中。

如果你是从旧版本升级,请查看我们的 升级指南

👉 完整发布说明

阅读 Nuxt v4.4.0 的完整发布说明。

感谢本次发布的所有贡献者!💚