nuxt

框架

nuxt/nuxt

全栈 Vue 框架,构建类型安全、高性能网页应用。

项目简介

Nuxt 是一个基于 Vue.js 的开源框架,提供服务端渲染、静态站点生成、混合渲染等功能。具备自动路由、数据获取、状态管理及零配置 TypeScript 支持。通过 300 多个模块可扩展,适用于生产级全栈应用。

README 预览

\n\n# Nuxt\n\n\n  \n  \n  \n  \n  \n  \n  \n  \n\n\nNuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js.\n\nIt provides a number of features that make it easy to build fast, SEO-friendly, and scalable web applications, including:\n- Server-side rendering, static site generation, hybrid rendering and edge-side rendering\n- Automatic routing with code-splitting and pre-fetching\n- Data fetching and state management\n- Search engine optimization and defining meta tags\n- Auto imports of components, composables and utils\n- TypeScript with zero configuration\n- Go full-stack with our server/ directory\n- Extensible with [300+ modules](https://nuxt.com/modules)\n- Deployment to a variety of [hosting platforms](https://nuxt.com/deploy)\n- ...[and much more](https://nuxt.com) 🚀\n\n### Table of Contents\n\n- 🚀 [Getting Started](#getting-started)\n- 💻 [Vue Development](#vue-development)\n- 📖 [Documentation](#documentation)\n- 🧩 [Modules](#modules)\n- ❤️ [Contribute](#contribute)\n- 🏠 [Local Development](#local-development)\n- 🛟 [Professional Support](#professional-support)\n- 🔗 [Follow Us](#follow-us)\n- ⚖️ [License](#license)\n\n---\n\n## 🚀 Getting Started\n\nUse the following command to create a new starter project. This will create a starter project with all the necessary files and dependencies:\n\n```bash\nnpm create nuxt@latest \n```\n\n> [!TIP]\n> Discover also [nuxt.new](https://nuxt.new): Open a Nuxt starter on CodeSandbox, StackBlitz or locally to get up and running in a few seconds.\n\n## 💻 Vue Development\n\nSimple, intuitive and powerful, Nuxt lets you write Vue components in a way that makes sense. Every repetitive task is automated, so you can focus on writing your full-stack Vue application with confidence.\n\nExample of an `app.vue`:\n\n```vue\n\nuseSeoMeta({\n  title: 'Meet Nuxt',\n  description: 'The Intuitive Vue Fra

常见问题 (5)

故障排除
如何修复 Nuxt 4.6 中 useFetch<T>() 接收运行时字符串 baseURL 时出现的 TS2769 错误?

这是 Nuxt 4.6.0 中的一个 TypeScript 泛型推断回归问题。当你提供显式的响应类型时,例如 useFetch<{ items: number[] }>(),BaseURL 泛型会默认为字面量类型 '',因此来自 useRuntimeConfig() 的运行时 string 会被拒绝。

变通方法 1 —— 使用基础 URL 创建一个 fetch 实例,并通过 $fetch 传入:

const config = useRuntimeConfig()
const api = $fetch.create({ baseURL: config.public.apiBase })

useFetch<{ items: number[] }>('/x', { $fetch: api })
useLazyFetch<{ items: number[] }>('/x', { $fetch: api })

变通方法 2 —— 构建完整的 URL 并省略 baseURL:

const config = useRuntimeConfig()
useFetch<{ items: number[] }>(`${config.public.apiBase}/x`)

同样的变通方法也适用于从 #build/fetch 导入的 $fetch。作为临时措施,你也可以降级到 Nuxt 4.5.2,在该版本中之前的行为是正常的。

来源 Issue #36521
故障排除
如何修复 Nuxt `Serialize` 丢失具有字符串索引签名对象的命名属性的问题?

这是 Nuxt 4.6.0 的 SerializeObject 中的一个类型层面的 bug。它使用了 Omit<T, FilterKeys<T, NonJsonPrimitive>>;当 T 具有索引签名时,keyof T 会变成 string | number,因此在映射类型过程中命名键会被移除。请将 node_modules/nuxt/dist/app/types/serialize.d.ts 中的 SerializeObject 替换为使用键重映射的映射类型:

type SerializeObject<T extends object> = {
  [K in keyof T as T[K] extends NonJsonPrimitive ? never : K]: Serialize<T[K]>
}

这样既能保留 docFormat 和 name 等命名属性,也能保留索引签名。使用 patch-package 持久化此更改:

npx patch-package nuxt

然后将 patch-package 添加到 postinstall:

{ "scripts": { "postinstall": "patch-package" } }

作为不对 Nuxt 打补丁的临时变通方案,可以将响应转换为显式的修正类型:

type SerializeObjectFixed<T extends object> = {
  [K in keyof T as T[K] extends NonJsonPrimitive ? never : K]: Serialize<T[K]>
}

const wire = JSON.parse(JSON.stringify(doc)) as SerializeObjectFixed<Doc>

同样的问题也常出现在 Zod 的 .catchall()、z.looseObject() 和 .passthrough() 类型中。请在相关修复发布后升级 Nuxt,或在此之前使用该补丁。

来源 Issue #36500
故障排除
为什么在 Nuxt 4.6.1 中全局 $fetch 的类型是 nitropack 的 $Fetch 而不是 NuxtGlobalFetch(routeTypedFetch 不起作用)?

在 Nuxt 4.6.1 中,@nuxt/kit 会通过 defu 将你的 typescript.appTsConfig(或 tsConfig)合并到生成的 tsconfig 中,这会将你自定义的 include 条目置于 ./nuxt.d.ts 之前。如果这些被包含的文件中有任何一个导入了 nuxt/app(例如测试辅助文件),nitropack 的 declare global { var $fetch: $Fetch } 会被先加载,因此全局 $fetch 的类型会再次变为 $Fetch<unknown, NitroFetchRequest>——即使已启用 experimental.routeTypedFetch: true。解决方法:将 ./nuxt.d.ts 作为 include 数组的第一个条目:

export default defineNuxtConfig({
  experimental: { routeTypedFetch: true },
  typescript: {
    appTsConfig: {
      include: ['./nuxt.d.ts', '../test/**/*.ts'],
    },
  },
})

重复的 ./nuxt.d.ts 条目会被 Nuxt 去重,全局 $fetch 的类型将再次变为 NuxtGlobalFetch。可先运行 nuxi prepare,然后执行 tsc -p .nuxt/tsconfig.app.json --noEmit 进行验证。

来源 Issue #36621
故障排除
为什么当通过包名扩展 Nuxt layer 时,计划任务和 Cloudflare cron 触发器会出现重复?

在 extends 图中经由两条路径到达的同一个 layer,其配置会按每条路径各合并一次,使其声明的每个数组都翻倍——例如 nitro.cloudflare.wrangler.triggers.crons 会变成 ['0 0 * * *','0 0 * * *'](Cloudflare 部署失败,报错 duplicate cron found ... [code: 10100]),且 nitro.scheduledTasks 的任务列表会并发执行两次。原因在于:@nuxt/kit 中的 seenLayerDirs 去重保护位于 existsSync 检查之后,而像 extends: ['@org/layer-a','@org/layer-b'] 这样的包标识符在去重执行之前就未能通过该检查(在 nuxt 4.5.2 / c12 3.3.4 上观察到)。变通方法:将 layer 写成相对路径而非包名,例如 extends: ['./packages/a','./packages/b']——路径写法能通过存在性检查并被正确去重。上游尚未发布修复。

来源 Issue #36339
故障排除
为什么在 Windows 上的 Nuxt 开发模式下,CSS 会被加载两次且级联层顺序被破坏(Nuxt 4.6.2)?

这是一个仅在 Windows 上出现的回归问题,由 Nuxt 4.6.2 引入(4.6.1 中正常)。在 collectDevCss(@nuxt/vite-builder)中,模块图的 URL 现在会经过 toDevUrl() 处理,它会为任何不以 / 开头的 URL 加上 /@id/ 前缀。在 Windows 上,绝对路径以盘符开头(例如 D:/),因此 SSR 样式表链接会变成 /_nuxt/@id/D:/…/lib.css。而 nuxt:dev-style-ssr 插件只移除 link[href="/_nuxt/<id>"] 和 link[href="/_nuxt/@fs/<id>"],所以 /@id/ 链接在水合之后永远不会被移除。后果是:每个全局样式表(例如 css: ['primeicons/primeicons.css'] 或由模块注入的 CSS)在开发环境中都会加载两次,并且残留的链接始终位于 Vite 注入的 <style> 标签之前,导致 @layer 优先级不再遵循 nuxt.options.css 的顺序(靠后条目的层可能变成最低优先级)。临时解决方案:降级/固定到 Nuxt 4.6.1(pnpm add nuxt@4.6.1 或在 package.json 中添加 override),直到补丁发布。POSIX 系统(Linux/macOS)不受影响,因为其绝对路径以 / 开头。给维护者的正确修复方案:将 /@id/ 形式(joinURL(buildAssetsURL, '@id', moduleId))加入 DevStyleSSRPlugin 所移除的选择器中,或者让 collectDevCss 对绝对路径输出 /@fs/ 形式。

来源 Issue #36737