迁移指南

Nitro v3 引入了有意的不向后兼容更改。本指南将帮助你从 Nitro v2 迁移。

Note

这是一份关于从 Nitro 2 迁移到 3 的动态文档。在使用测试版期间,请定期查看。

大多数迁移遵循相同的顺序:

添加显式导入,并更新 类型 和 子路径 导入。
更新配置:启用服务器目录扫描,并查看已移除的功能。
根据 H3 v2 API 更改更新处理器。

#nitropack 已重命名为 nitro

NPM 包 nitropack(v2)已重命名为 nitro(v3)。

迁移: 在 package.json 中将 nitropack 依赖更新为 nitro:

{
  "dependencies": {
--    "nitropack": "latest"
++    "nitro": "latest"
  }
}

有关 nightly 构建的更多信息,请参阅 nightly channel 指南。

迁移: 搜索你的代码库,并将所有 nitropack 实例重命名为 nitro:

-- import { defineNitroConfig } from "nitropack/config"
++ import { defineConfig } from "nitro"

#最低支持的 Node.js 版本:20

Nitro 现在要求最低 Node.js 版本为 20,因为 Node.js 18 已于 2025 年 4 月结束生命周期。

请升级到最新的 LTS 版本(>= 20)。

迁移:

  • 使用 node --version 检查本地 Node.js 版本,并在必要时进行更新。
  • 如果你使用 CI/CD 系统进行部署,请确保你的流水线运行的是 Node.js 20 或更高版本。
  • 如果你的托管服务商管理 Node.js 运行时,请确保其设置为版本 20、22 或更高版本。

#构建器按需安装

Nitro 默认使用 rolldown(或 rollup、vite)打包服务器,但它们都不是 Nitro 的依赖。构建器会从你的项目中解析,并在构建时按需安装。将其添加到项目依赖中即可固定版本:

npm i -D rolldown

未安装 rolldown 时,nitro dev 会在没有构建器的情况下运行服务器源代码(builder: false)。

#自动导入已移除

Nitro v2 会自动让 defineEventHandler、useStorage、useRuntimeConfig、defineCachedFunction 和 defineNitroPlugin 等工具在服务器代码中无需导入即可使用(由 unimport 提供支持),同时还会公开 server/utils/ 的导出内容和虚拟的 #imports 模块。

Nitro v3 中已移除自动导入。imports 配置选项、#imports 模块和生成的 nitro-imports.d.ts 声明均不再可用。使用这些全局变量将导致构建或运行时错误。

迁移: 在所有位置添加显式导入。常用工具及其来源:

import { defineHandler, definePlugin, defineErrorHandler, HTTPError } from "nitro";
import { useKV } from "nitro/kv";
import { useRuntimeConfig } from "nitro/runtime-config";
import { defineCachedFunction, defineCachedHandler } from "nitro/cache";
import { useDatabase } from "nitro/database";
import { defineTask, runTask } from "nitro/task";
import { useNitroApp, useNitroHooks } from "nitro/app";
import { getQuery, getCookie } from "nitro/h3";

你自己的 utils/ 目录中的工具也需要显式的(相对)导入:

server/routes/index.ts
import { defineHandler } from "nitro";
import { makeGreeting } from "../utils/hello.ts";

export default defineHandler(() => makeGreeting("Nitro"));

#类型导入

Nitro 类型现在仅从 nitro/types 导出。

迁移: 从 nitro/types 导入类型,而不是从 nitro 导入:

-- import { NitroRuntimeConfig } from "nitropack"
++ import { NitroRuntimeConfig } from "nitro/types"

#更改后的 Nitro 子路径导入

Nitro v2 引入了多个子路径导出,其中一些已被移除或更新:

  • nitropack/rollup、nitropack/core(使用 nitro/builder)
  • nitropack/runtime/*(使用 nitro/*)
  • nitropack/kit(已移除)
  • nitropack/presets(已移除)
  • nitropack/meta(改用 nitro/meta,它只导出 version、runtimeDir 和 runtimeDependencies)

此前引入了实验性的 nitropack/kit,但现在已将其移除。未来可能会推出独立的 Nitro Kit 包,并明确其目标。

迁移:

  • 使用来自 nitro/types 的 NitroModule,而不是 kit 中的 defineNitroModule。
  • 优先使用内置的 Nitro 预设(外部预设仅用于评估)。

#服务器目录扫描需选择性启用

在 Nitro v2 中,srcDir 默认为项目根目录,并且始终会扫描 routes/、api/、middleware/、plugins/ 和 tasks/ 等目录。

在 Nitro v3 中:

  • srcDir 选项已弃用,推荐使用 serverDir(继续使用 srcDir 仍然有效,但会记录警告)。
  • serverDir 默认为 false,这意味着在显式启用之前不会进行目录扫描。否则,扫描到的路由、中间件、插件和任务不会被注册。

迁移: 在 Nitro 配置中设置 serverDir:

nitro.config.ts
import { defineConfig } from "nitro";

export default defineConfig({
  serverDir: "./server", // or "." to keep the v2 root layout
});

将 serverDir 设置为 true 等同于设置为 "server"。路径将相对于项目根目录解析。

#扫描文件中的保留后缀

Nitro v3 将扫描文件名末尾的小写后缀保留给自身约定使用。在 v2 中,routes/hello.world.ts 会注册为 /hello.world;在 v3 中,构建会因未知后缀而失败(开发模式下会跳过该文件并记录错误)。routes/sitemap.xml.ts 等已知文件扩展名仍然有效。

middleware/、plugins/、tasks/ 和 modules/ 文件名中的 .dev、.prod 和 .prerender 也属于保留后缀,使用这些后缀同样会导致构建失败。

测试文件(*.test.ts、*.spec.ts)和类型声明文件(*.d.ts)不再注册。

迁移: 重命名该文件,或将后缀添加到 scanSuffixes,以便将其保留为文件名的一部分。

#unenv 选项已弃用

unenv 配置选项(以及钩子中的 nitro.options.unenv)已弃用,请改用 alias、inject、polyfills 和 builtinModules 选项(unenv 的 polyfill 和 external 分别对应 polyfills 和 builtinModules)。传给 unenv 的预设仍然有效,但会记录一条警告。

export default defineConfig({
-  unenv: {
-    alias: { "my-module": "my-module/web" },
-    external: ["cloudflare:workers"],
-  },
+  alias: { "my-module": "my-module/web" },
+  builtinModules: ["cloudflare:workers"],
});

通过钩子推送预设的模块应直接更新这些选项(例如 nitro.options.builtinModules.push(...))。在这些选项中设置的值会覆盖部署预设添加的默认值(例如 Cloudflare 和 Deno 会将受支持的 Node.js 内置模块映射到原生模块)。

unenv 不再是 Nitro 的依赖。当 node: false 构建导入目标运行时不支持的 Node.js 内置模块时,Nitro 会从你的项目中解析 unenv 并自动安装(不会提示确认)。如果你直接导入 unenv,请将其添加到项目依赖中。

#unstorage、db0 和 ocache 按需安装

unstorage、db0 和 ocache 不再是 Nitro 的依赖。使用时,Nitro 会从你的项目中解析并按需安装它们:

  • unstorage:导入 nitro/kv(或 nitro/storage)、配置 kv 挂载,或将 cache.driver 设为 "kv" 时。
  • db0:启用 experimental.database 或导入 nitro/database 时。
  • ocache:导入 nitro/cache(defineCachedHandler、defineCachedFunction)或使用 cache / swr路由规则时。

这些依赖会在不提示确认的情况下安装到项目依赖中。如果你直接导入 unstorage、db0 或 ocache,请自行将它们添加为项目依赖。

#已移除 App Config 支持

Nitro v2 支持捆绑的 app config,可以在 app.config.ts 中定义配置,并通过 useAppConfig() 在运行时访问这些配置。

此功能已被移除。

迁移:

在服务器目录中使用常规的 .ts 文件,并直接导入它。

#路由规则

路由规则的匹配和处理已移至 h3-rules。redirect、proxy、cors、headers、cache 和 swr 的规则形状现在由 h3-rules 定义,而 isr、prerender 和 static 仍是 Nitro 特有的规则。

NitroRouteConfig 和 NitroRouteRules 类型已弃用,推荐使用从 nitro/types 重新导出的 RouteRuleConfig 和 NormalizedRouteRules:

- import { NitroRouteConfig, NitroRouteRules } from "nitropack/types"
+ import { RouteRuleConfig, NormalizedRouteRules } from "nitro/types"

getRouteRules(event) 已由 event.context.routeRules 替代。若要解析其他路径的规则,请使用 nitro/app 中的 getRouteRules(method, pathname).routeRules。

- import { getRouteRules } from "nitropack/runtime"
- const rules = getRouteRules(event)
+ import { getRouteRules } from "nitro/app"
+ const rules = event.context.routeRules
+ const { routeRules: blogRules } = getRouteRules("GET", "/blog/post")

#运行时工具

运行时工具已移至单独的 nitro/* 子路径导出。有关用法,请参阅文档。

-- import { useStorage } from "nitropack/runtime/storage"
++ import { useKV } from "nitro/kv"
工具Nitro v3 导入
useKV(原为 useStorage)nitro/kv
defineCachedFunction、defineCachedHandlernitro/cache
useDatabasenitro/database
useRuntimeConfignitro/runtime-config
defineTask、runTasknitro/task
useNitroApp、useNitroHooks、getRouteRulesnitro/app

Note

useStorage 已重命名为 useKV,nitro/storage 已重命名为 nitro/kv。storage 配置选项已重命名为 kv,而 devStorage 已由 $development 中的 kv 替代(如果你在预渲染期间依赖 devStorage,也请将其添加到 $prerender 中)。旧名称仍可作为已弃用的别名使用,并将在未来版本中移除。

#缓存存储

缓存函数和处理器默认不再使用存储层。条目存储在内存 LRU 存储中,可通过新的 cache 选项配置(driver: "memory" | "fs" | "kv")。

如果配置了 cache 存储挂载点(例如 storage: { cache: { driver: "redis" } }),缓存条目会继续存储在其中。如果缓存函数、处理器或路由规则使用自定义 base 指向另一个挂载点,或在运行时挂载缓存存储(例如在插件中调用 useKV().mount(...)),请设置 cache: { driver: "kv" }。

#内部服务器请求

要向你自己的服务器发起内部请求(v2 的 useNitroApp().localFetch 模式),请使用从 nitro 导出的 serverFetch 工具。此外,还有一个 fetch 导出,它会将绝对路径(以 / 开头)路由到服务器,并将其他所有内容路由到全局 fetch。

import { serverFetch } from "nitro";

const res = await serverFetch("/api/hello"); // returns a web Response

#插件

defineNitroPlugin 工具已重命名为 definePlugin,现在从 nitro 中导入。

-- export default defineNitroPlugin((nitroApp) => {
++ import { definePlugin } from "nitro"
++
++ export default definePlugin((nitroApp) => {

#可选钩子

如果你之前在 Nitro 插件之外使用 useNitroApp().hooks,它可能是未定义的。使用新的 useNitroHooks() 可以确保获得一个实例。

import { useNitroHooks } from "nitro/app";

useNitroHooks().hook("request", (event) => {
  /* ... */
});

#构建钩子重命名

rollup:before 和 rollup:reload 构建钩子会在所有构建器(Rollup、Rolldown 和 Vite)中运行,因此现已分别重命名为 build:config 和 build:reload。build:config 钩子接收 { builder, rollup } 或 { builder, rolldown },而不是单独的打包器配置。使用 Vite 构建器时,builder 为 "vite",配置对应于 Vite 所用的打包器。

-- nitro.hooks.hook("rollup:before", (nitro, config) => {
--   config.plugins.push(myPlugin());
++ nitro.hooks.hook("build:config", (nitro, { builder, rollup, rolldown }) => {
++   const config = rollup ?? rolldown;
++   config.plugins.push(builder === "rollup" ? myRollupPlugin() : myPlugin());
   });

旧名称仍可作为已弃用的别名使用(会记录警告):rollup:before 钩子由 build:config 以单独的配置参数调用,rollup:reload 钩子则由 build:reload 调用。使用 nitro.hooks.callHook() 调用旧名称不再会运行任何钩子。

#错误处理器

defineNitroErrorHandler 工具已重命名为 defineErrorHandler,现在从 nitro 导入。

-- export default defineNitroErrorHandler((error, event) => {
++ import { defineErrorHandler } from "nitro"
++
++ export default defineErrorHandler((error, event) => {

#H3 v2

Nitro v3 升级到 H3 v2,其中包含 API 更改。所有 H3 工具从 nitro/h3 导入。

#Web 标准

H3 v2 基于 Web 标准原语(URL、Headers、Request 和 Response)重写。

仅在 Node.js 运行时中可访问 event.node.{req,res}。event.web 已重命名为 event.req(Web Request 的实例)。

#响应处理

你应该始终显式地 return 响应体或 throw 一个错误:

-- import { send, sendRedirect, sendStream } from "nitro/h3"
-- send(event, value)
-- sendStream(event, stream)
-- sendRedirect(event, location, code)
++ import { redirect } from "nitro/h3"
++ return value
++ return stream
++ return redirect(location, code)

其他更改:

  • sendError(event, error) → throw error(或 throw new HTTPError(...))
  • sendNoContent(event) → return noContent()
  • sendProxy(event, target) → return proxy(event, target)

#请求体

大多数 body 工具可以被原生的 event.req 方法替代:

-- import { readBody, readRawBody, readFormData } from "nitro/h3"
++ // 使用原生 Request 方法
++ const json = await event.req.json()
++ const text = await event.req.text()
++ const formData = await event.req.formData()
++ const stream = event.req.body

#请求头

H3 现在使用标准 Web Headers。请求头的值始终是纯 string(没有 null、undefined 或 string[])。

-- import { getHeader, setHeader, getResponseStatus } from "nitro/h3"
-- getHeader(event, "x-foo")
-- setHeader(event, "x-foo", "bar")
++ event.req.headers.get("x-foo")
++ event.res.headers.set("x-foo", "bar")
++ event.res.status // 替代 getResponseStatus(event)

#处理器工具

-- import { eventHandler, defineEventHandler } from "nitro/h3"
++ import { defineHandler } from "nitro"
  • lazyEventHandler → defineLazyEventHandler
  • useBase → withBase

#错误工具

-- import { createError, isError } from "nitro/h3"
++ import { HTTPError } from "nitro"
++ throw new HTTPError({ status: 404, message: "未找到" })
++ HTTPError.isError(error)

#Node.js 工具

-- import { defineNodeListener, fromNodeMiddleware, toNodeListener } from "nitro/h3"
++ import { defineNodeHandler, fromNodeHandler, toNodeHandler } from "nitro/h3"

#预设更新

Nitro 预设已针对最新兼容性进行更新。

一些(旧版)预设已被移除或重命名。

旧预设新预设
node(Node.js 中间件)node_middleware(导出已更改为 middleware)
cloudflare、cloudflare_worker、cloudflare_module_legacycloudflare_module
deno-server-legacy使用 Deno v2 的 deno_server
netlify-buildernetlify 或 netlify_edge
vercel-edge启用 Fluid compute 的 vercel
azure、azure_functionsazure_swa
firebasefirebase_app_hosting
iisiis_handler
deno(Deno Deploy)、deno_deploydeno_server
edgio已停止维护
cli因缺乏使用而移除
service_worker因不稳定而移除

Warning

node 和 deno 预设名称在 v3 中仍然存在,但它们现在指向不同的目标:

  • 在 v2 中,node 预设会生成可复用的 Node.js 中间件。在 v3 中,node 是 node_server 的别名,会构建一个完整的独立 Node.js 服务器。如果保留 preset: "node",现在将获得一个独立服务器。使用 node_middleware 以保留 v2 的中间件输出。
  • 在 v2 中,deno 和 deno_deploy 预设面向 Deno Deploy Classic(打包为 server/index.ts 并通过 deployctl 部署)。Deno Deploy Classic 已于 2026 年 7 月 20 日关闭。在 v3 中,deno 和 deno_deploy 是 deno_server 的别名,会构建 .output/server/index.mjs。新版 Deno Deploy 使用此输出(参阅 Deno Deploy 指南)。

#AWS Amplify 默认运行时

由于 Node.js 20 已于 2026 年 4 月结束生命周期,aws_amplify 预设现在默认使用 nodejs22.x 计算运行时(此前为 nodejs20.x)。

迁移:

  • 在 Node.js 22 上测试应用,或在 Nitro 配置中通过 awsAmplify: { runtime: "nodejs24.x" } 显式固定运行时。

#Cloudflare Dev 和 Vercel 可观测性不再受兼容日期限制

此前受 compatibilityDate 控制的两项预设功能现在始终启用,因此从 v2 沿用较早兼容日期的配置也会保留这些功能:

  • cloudflare_module、cloudflare_durable 和 cloudflare_pages 预设在开发环境中始终使用 cloudflare-dev 预设(通过 Miniflare 模拟并提供绑定)。此前,compatibilityDate 早于 2025-07-13 时会静默回退到通用的 nitro-dev 预设。
  • vercel 预设始终会生成可观测性路由。此前,这些路由要求 compatibilityDate 为 2025-07-15 或更晚。

#Azure Functions v4 编程模型

azure_swa 预设现在使用 Azure Functions 的 Node.js v4 编程模型部署服务器,不再使用 function.json。项目依赖中需要 @azure/functions v4:

npm i @azure/functions@^4

迁移:

  • 将 @azure/functions@^4 添加到依赖中(缺少时 Nitro 会提示安装)。如果已安装 v3,请更新它。
  • 若要继续使用旧版 v3 编程模型,请在 Nitro 配置中设置 azure: { functionsVersion: 3 }。

#Vercel ISR 路由规则

在 Nitro v2 中,vercel 预设会将 swr、static 和 cache: false 路由规则转换为 Vercel ISR 配置。在 Nitro v3 中,只有 isr 路由规则会为 Vercel 配置 ISR;swr / cache 规则则像其他平台一样使用 Nitro 内置缓存层。用于启用此行为的 future.nativeSWR 选项已移除。

迁移:

原先依赖 Vercel ISR 的地方请改用 isr 路由规则,并从配置中移除 future.nativeSWR。

nitro.config.ts
export default defineConfig({
--  future: { nativeSWR: true },
  routeRules: {
--    "/blog/**": { swr: true },
--    "/api/realtime/**": { cache: false },
++    "/blog/**": { isr: true },
++    "/api/realtime/**": { isr: false },
  },
});

#Netlify 输出目录

netlify 和 netlify_edge 预设现在会将输出写入 Netlify Frameworks API 指定的目录:

输出之前之后
服务器函数(netlify).netlify/functions-internal.netlify/v1/functions
边缘函数(netlify_edge).netlify/edge-functions.netlify/v1/edge-functions
部署配置(netlify.config).netlify/deploy/v1/config.json.netlify/v1/config.json

边缘函数配置现在会内联到 server.mjs,而不再写入 .netlify/edge-functions/manifest.json;netlify_edge 预设也会应用 netlify.config。

迁移:

  • 更新引用旧目录的 CI 脚本或缓存路径。
  • 使用 netlify deploy --no-build 部署本地构建时,请先清理 .netlify/functions-internal 和 .netlify/edge-functions 中旧构建遗留的文件。

#Cloudflare Pages 重定向目标

Cloudflare Pages 预设不再为生成的 _redirects 文件中的相对 redirect 目标添加 baseURL 前缀。现在目标会按原样使用,与服务器运行时以及 Vercel、Netlify 预设的行为一致。路由规则键(匹配路径)仍相对于 baseURL。EdgeOne 预设在此前的 v3 预发布版本中也会添加前缀,现在同样采用这一行为。

迁移:

如果使用非根路径的 baseURL,请在相对重定向目标中包含该前缀:

nitro.config.ts
export default defineConfig({
  baseURL: "/app/",
  routeRules: {
--    "/old/**": { redirect: "/new/**" },
++    "/old/**": { redirect: "/app/new/**" },
  },
});

#Cloudflare 绑定访问

在 Nitro v2 中,可以通过 event.context.cloudflare.env 访问 Cloudflare 环境变量和绑定。

在 Nitro v3 中,Cloudflare 运行时上下文改为附加到请求的运行时对象上。

迁移:

-- const { cloudflare } = event.context
-- const binding = cloudflare.env.MY_BINDING
++ const { env } = event.req.runtime.cloudflare
++ const binding = env.MY_BINDING

#Cloudflare Email 和 Queue 钩子

cloudflare:email 和 cloudflare:queue 运行时钩子中已移除已弃用的 event 字段,请改用 message 和 batch。

迁移:

-- nitroApp.hooks.hook("cloudflare:email", ({ event }) => {})
++ nitroApp.hooks.hook("cloudflare:email", ({ message }) => {})
-- nitroApp.hooks.hook("cloudflare:queue", ({ event }) => {})
++ nitroApp.hooks.hook("cloudflare:queue", ({ batch }) => {})

#Cloudflare 导出

较早的 v3 预发布版本曾实验性支持从 exports.cloudflare.ts 文件(或 cloudflare.exports 选项)导出 Durable Objects、Workflows 和其他 Cloudflare 类。现在应改为从 server.ts 文件导出,并且在本地开发中也可使用。参阅 Durable Objects。

server.ts
++ export { MyWorkflow } from "./exports.cloudflare.ts";
++
++ export default {
++   fetch() {},
++ };

#Vite 插件选项

较早的 v3 预发布版本中,services、assetsImport 和 serverReload 只能作为 experimental.vite 选项传给 nitro() Vite 插件。它们现已移至顶层 vite 选项,也可以放在 Vite 配置的 nitro 项下或写入 nitro.config.ts。experimental.vite 仍可使用,但已弃用。已弃用的 ServiceConfig 类型已移除,请改用 ViteServiceConfig。

vite.config.ts
-- nitro({ experimental: { vite: { services: { api: { entry: "./api.ts" } } } } })
++ nitro({ vite: { services: { api: { entry: "./api.ts" } } } })

#已移除的弃用选项

此前 v3 预发布版本中已弃用或不起作用的部分选项和导出已移除:

  • netlify.images:改用 netlify.config.images。
  • vercel.regions:它仅适用于已移除的 vercel-edge 预设。请改用 vercel.functions.regions。
  • prerender.retry 和 prerender.retryDelay:它们在 v3 中不起作用。
  • 从 nitro/storage 导入的 useKV:请改为从 nitro/kv 导入。
  • nitro/builder 中的 getBuildInfo(rootDir):请传入选项对象 getBuildInfo({ rootDir })。