迁移指南

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 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/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"。路径将相对于项目根目录解析。

#已移除 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 和 RouteRules:

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

#运行时工具

运行时工具已移至单独的 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 中)。旧名称仍可作为已弃用的别名使用,并将在未来版本中移除。

#内部服务器请求

要向你自己的服务器发起内部请求(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) => {
  /* ... */
});

#错误处理器

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(event, location, code)

其他更改:

  • sendError(event, error) → throw error(或 throw new HTTPError(...))
  • sendNoContent(event) → return noContent(event)
  • 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_deploy
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。在 v3 中,deno 是 deno_server 的别名,会构建一个自托管的 Deno 服务器。使用 deno_deploy 以继续部署到 Deno Deploy。

#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