Nitro是什么

Nitro 是Nuxt 团队最新推出的一个全新的部署工具,是 Nuxt.js 3 的后端运行和部署工具
Nitro 的目标是提供在 (SSR) 应用程序中,最快速的冷启动和最小的冷启动延迟。

Nitro是一个强大的后端开发框架,但它并不是仅限于与Nuxt.js一起使用。

Nitro 具有以下特点

  • 快速冷启动速度:云函数在每次请求时都可能需要冷启动。Nitro 针对这一点进行了优化,可以在几毫秒内启动。
  • 全面支持 JS/TS:你可以直接在 API 路由中编写 TypeScript 或 JavaScript。
  • 支持 Nuxt 3 和 2:尽管 Nitro 是为 Nuxt 3 设计的,但它也支持 Nuxt 2。只需要安装@nuxt/nitro 就可以使用。
  • 服务器渲染 (SSR):nitro 能够更快、更有效地进行服务器端渲染,优化了渲染性能。
  • Edge-ready:Nitro 是为边缘计算设计的,完全兼容云平台和边缘推理服务,如 Cloudflare Workers,同时也支持 传统的 Node.js 服务器。
  • 支持静态站点生成:Nitro不仅支持SSR,也支持预渲染静态站点。
  • 实时函数和 API Route:Nitro 自带实时函数的功能,无需额外设置即可使用。在任何地方编写 Serverless 函数,并与你的前端代码共享相同的 Typescript 或 JavaScript 代码

创建Nitro项目

  • 使用入门模板创建一个新项目
npx giget@latest nitro nitro-app
  • 安装依赖项
cd nitro-app
npm i
  • 运行项目
npm run dev
  • 打包项目
npm run build

打包的删除目录是:.output,打包的输出目录.output可以部署在几乎没有依赖项提供的程序上。

  • 预览打包后的内容
npm run preview

nitro项目打包之后可以运行npm run preview命令进行预览

边缘发布通道

nitro提供了一个边缘发布通道,可以在每次提交到main分支时自动发布
需要随package.json做如下配置:

{
  "devDependencies": {
      "nitropack": "npm:nitropack-edge@latest"
  }
}

Nitro的配置

  • 可以使用单个配置文件自定义您的 Nitro 服务器:nitro.config.ts
  • 如果您使用的是 Nuxt,请在您的 Nuxt 配置中使用 nitro 选项。

使用nitro.config.ts配置

import { defineNitroConfig } from 'nitropack/config'

export default defineNitroConfig({
  // Nitro options
})

使用nuxt.config.ts配置

export default defineNuxtConfig({
  nitro: {
    // Nitro options
  }
})

可配置项

普通配置

  • preset
    使用preset选项的NITRO_PRESET 环境变量来自定义production预设。

  • logLevel
    日志的详细级别,小于等于该级别的日志都会进行输出。生产环境下默认是3,开发环境下默认为1。
    日志级别:
    0:致命和错误
    1:警告
    2:正常日志
    3:信息日志,success, fail, ready, start,…
    4:调试日志
    5:跟踪日志

  • runtimeConfig
    服务运行时配置,默认值{ nitro: { ... }, ...yourOptions }

特性配置

  • experimental
    启用实验性功能。默认值:{}
  • storage
    存储配置,默认值:{}
  • timing
    是否启用时序信息(包括:1. nitro启用时间日志;2. HTTP响应上的Server-Timing标头)
    默认值是false
  • render
    主渲染路径(文件应默认到处事件处理程序)
  • serveStatic
    在生产环境中提供公共资产,默认值:取决于您的部署预设
  • noPublicDir
    如果启用,则禁用.output/public目录创建。禁用预渲染。
  • publicAssets
    用于开发和捆绑生产环境下的的公共资产目录
publicAssets: [
    {
      baseURL: "images",
      dir: "public/images",
      maxAge: 60 * 60 * 24 * 7, // 7 days
    },
  ],

如果检测到 public/ 目录,它会默认将public文件夹中的内容添加进来。

  • compressPublicAssets

如果启用,Nitro 将生成受支持类型的公共资产预渲染路由的预压缩
使用此选项,您可以在不使用 CDN 的情况下支持零开销资产压缩。
默认值:{ gzip: false, brotli: false }

  • serverAssets
    如果启用,资产可以在服务器逻辑中访问并在生产中捆绑

  • devServer
    开发服务器选项,可以使用watch监听指定路径文件的修改,一旦修改重新加载开发服务器。
    默认值:{ watch: [] }

  • watchOptions
    监听开发模式的选项

  • imports
    自动但如选项

  • plugins
    注册nitro的插件,他们将在第一次初始化的时候按顺序执行。
    (Nitro 会在 plugins/ 目录中自动注册插件)

  • virtual
    从动态虚拟导入名称到其内容的映射或返回它的(异步)函数。
    默认值:{}

路由配置

  • baseURL
    服务器的主要基础 URL。
    默认值:/(如果提供了 NITRO_APP_BASE_URL 环境变量,默认值就是NITRO_APP_BASE_URL

  • handlers
    服务器处理程序和路由。
    如果 routes/、api/ 或 middleware/ 目录存在,它们将被自动添加到 handlers 数组中。

  • devHandlers
    开发环境下的服务器处理程序和路由。

  • devProxy
    开发服务器的代理配置

{
  devProxy: {
    '/proxy/test': 'http://localhost:3001',
    '/proxy/example': { target: 'https://example.com', changeOrigin: true }
  }
}
  • errorHandler
    自定义运行时错误处理程序的路径。 替换 nitro 的内置错误页面。
    nitro.config
import { defineNitroConfig } from "nitropack/config";

export default defineNitroConfig({
  errorHandler: "~/error",
});

error.ts

import type { NitroErrorHandler } from 'nitropack'

export default <NitroErrorHandler> function (error, event) {
  event.res.end('[custom error handler] ' + error.stack)
}
  • routeRules
    路由配置规则。
    当设置了 cache 选项时,匹配模式的处理程序将自动用 defineCachedEventHandler 包装。
    nitro.config
routeRules: {
  '/blog/**': { swr: true },
  '/blog/**': { swr: 600 },
  '/blog/**': { static: true },
  '/blog/**': { cache: { /* cache options*/ } },
  '/assets/**': { headers: { 'cache-control': 's-maxage=0' } },
  '/api/v1/**': { cors: true, headers: { 'access-control-allow-methods': 'GET' } },
  '/old-page': { redirect: '/new-page' },
  '/proxy/example': { proxy: 'https://example.com' },
  '/proxy/**': { proxy: '/api/**' },
}

swr: true|numbercache: { swr: true, maxAge: number }的简写。

  • prerender
    默认值:{ crawlLinks: false, ignore: [], routes: [] }
    预渲染选项。
    任何在routes中指定的路由都将在构建期间获取并作为静态资产复制到 .output/public 目录。
    任何在 ignore 中列出的前缀开头的路由都将被忽略。
    如果 crawlLinks 选项设置为 true,nitro 默认以 / 开始(或 routes 数组中的所有路由),对于 HTML 页面提取 <a href=""> 标签并预渲染它们 .

目录配置

  • rootDir
    项目根目录
  • srcDir
    项目源码目录。默认和rootDir相同
  • scanDirs
    扫描和自动注册文件的目录列表
  • buildDir
    nitro用于生成构建相关文件的链式目录.
    默认值:.nitro
  • output
    生产包的输出目录。
    默认值:{ dir: '.output', serverDir: '.output/server', publicDir: '.output/public' }

高级配置

  • dev
    为true时表示用于开发,为false时表示用于生产
    默认值是true

  • typeScript
    默认值:{ generateTsConfig: true }

  • nodeModulesDirs
    解析模块时要搜索的附加 node_modules

  • hooks
    用于定义nitro的钩子

  • commands
    预览和部署命令的提示

  • devErrorHandler
    用于定义开发模式下的自定义错误处理函数

Rollup配置

  • rollupConfig
    rollup的额外配置

  • entry
    rollup打包的入口文件

  • alias
    配置别名,方便我们在项目中使用简短的名车给或枯井别名来引用文件或模块。

  • minify
    最小化压缩(默认值是false)

  • inlineDynamicImports
    用于控制 Rollup 是否将动态导入(import())的模块内联到生成的 bundle 中。
    默认值为 false。
    使用此选项时, Rollup 将尝试将所有动态导入的模块合并到单个包中。

  • sourceMap
    启用源映射生成,即生成打包后文件和源码的映射文件,方便报错信息的快速定位。
    默认值:true

  • node
    指定构建是否基于 Node.js。
    如果设置为“false”,nitro 会尝试使用 unjs/unenv 模拟 Node.js 依赖项并调整其行为。

  • analyze
    如果启用,将在构建后使用 rollup-plugin-visualizer 分析服务器包。

  • moduleSideEffects
    指定具有副作用的模块导入
    默认值: ['unenv/runtime/polyfill/', 'node-fetch-native/polyfill']

  • commonJS
    指定 CommonJS 的附加配置。

nitro的自动导入

Nitro 使用 unjs/unimport 与 tree-shaking 一起支持使用时自动导入实用程序。

可以用的自动导入

  • cachedFunction

  • cachedEventHandler

  • defineCachedFunction(fn, options) / cachedFunction(fn, options)

  • defineCachedEventHandler(handler, options) / cachedEventHandler(handler, options)

  • defineRenderHandler(handler)

  • defineNitroErrorHandler

  • useRuntimeConfig(event?)

  • useAppConfig(event?)

  • useStorage(base?)

  • useNitroApp()

  • defineNitroPlugin(plugin)

  • nitroPlugin(plugin)

  • getRouteRules(event)

  • useEvent

      在运行 prepare 或 dev 命令时,这些类型是为全局自动导入自动生成的。
    

手动导入

对于某些边缘情况,不可能依赖自动导入,此时我们需要手动进行导入。从#imports文件中导入他们。
plugins/test.ts

import { useStorage } from '#imports'

nitro的路由

notro路由指的是api/routes/文件夹下的内容。
如果您使用的是 Nuxt,请将 api/ 和 routes/ 移到 server/ 目录中。

普通路由

api/hello.ts

export default eventHandler(() => {
  return { hello: 'world' }
})

配置完成之后就可以使用 await $fetch('/api/hello') 普遍调用此 API。

动态路由

服务器路由可以在文件名中使用中括号内的动态参数:
例如 /api/hello/[name].ts 并通过 event.context.params 访问。

/server/api/hello/[name].ts

export default defineEventHandler((event) => `Hello, ${event.context.params.name}!`)

使用 await $fetch(‘/api/hello/nuxt’) 调用此 API 会获得 Hello, nuxt!。

指定请求方法的api文件

句柄文件名可以加上 .get、.post、.put、.delete 等后缀,以匹配请求的http方法。

  • api/test.get.ts: 就是接受get请求
  • api/test.post.ts:就是接受post请求

处理没有匹配路径的请求

  • api/foo/[…].ts 文件将匹配 api/foo/ 路径下不匹配任何已经定义好的路径的路径
  • api/[…].ts 文件将匹配 api/ 路径下不匹配任何已经定义好的路径的路径

路由配置

需要在配置文件中进行配置,利用routeRules配置项进行配置。

  • 设置了 cache 选项时,匹配模式的处理程序将自动用 defineCachedEventHandler 包装。
import { defineNitroConfig } from 'nitropack/config'

export default defineNitroConfig({
  routeRules: {
    '/blog/**': { swr: true },
    '/blog/**': { swr: 600 },
    '/blog/**': { static: true },
    '/blog/**': { cache: { /* cache options*/ } },
    '/assets/**': { headers: { 'cache-control': 's-maxage=0' } },
    '/api/v1/**': { cors: true, headers: { 'access-control-allow-methods': 'GET' } },
    '/old-page': { redirect: '/new-page' },
    '/proxy/example': { proxy: 'https://example.com' },
    '/proxy/**': { proxy: '/api/**' },
  }
})

nuxt.config.js中也是使用顶层配置项routeRules进行配置

nitro的存储层Storage

nitro的store是依赖Unstorage实现的,详细用法可以参见Unstorage

其中nitro的seStorage() 就是对应Unstorage的createStorage 实例。

简单用法

await useStorage().setItem('test:foo', { hello: 'world' })
await useStorage().getItem('test:foo')

// 您还可以在 useStorage(base) 中指定基数
await useStorage('test').setItem('foo', { hello: 'world' })
await useStorage('test').getItem('foo')

配置使用数据库

  • 配置数据库
    在nitro.config.ts文件中编写如下代码
import { defineNitroConfig } from 'nitropack/config'

export default defineNitroConfig({
  storage: {
    'redis': {
      driver: 'redis',
      /* redis 连接的配置文件 */
    },
    'db': {
      driver: 'fs',
      base: './data/db'
    }
  }
})

在nuxt.config.js中的配置就是在storage外面添加一层nitro:{}

  • 使用数据库
await useStorage('redis').setItem('foo', { hello: 'world' })
await useStorage('redis').getItem('foo')
// 或者
await useStorage().setItem('redis:foo', { hello: 'world' })
await useStorage().getItem('redis:foo')

添加缓存挂载

在开发中,Nitro 使用 FS 驱动程序 添加“缓存”挂载点.

await useStorage('cache').setItem('foo', { hello: 'world' })
await useStorage('cache').getItem('foo')

配置开发环境下的storage

使用devStorage进行配置。
nitro.config.js

export default defineNitroConfig({
  // 生产
  storage: {
    db: {
      driver: 'redis',
      /* redis connector options */
    }
  },
  // 开发
  devStorage: {
    db: {
      driver: 'fs',
      base: './data/db'
    }
  }
})

上述配置可以使在生产中使用数据库,并在开发中使用文件系统。便于开发,防止污染数据库。

nitro的缓存

Nitro提供了一个建立在存储层之上的强大的缓存系统。他将数据存储在“缓存”挂载点中。

配置缓存

如果想要使用缓存,需要在配置文件中进行配置,使用 storage 选项设置 cache 挂载点:
nitro.config.js

import { defineNitroConfig } from "nitropack/config";

export default defineNitroConfig({
  storage: {
    cache: {
      driver: 'redis',
    }
  }
})

要在开发中覆盖 cache 挂载点,请使用 devStorage 选项添加 cache 挂载点。

使用缓存

路由路径使用缓存

eg: routes/cached.ts

export default cachedEventHandler(async () => {
  return `Response generated at ${new Date().toISOString()}`;
}, {
  swr: true, maxAge: 10
});

响应将被缓存 10 秒,如果当缓存在后台更新时,有请求,此时一个过时的值将被发送到客户端。
缓存的值被存储在:.nitro/cache/handlers/_/*.json

函数格式使用缓存

utils/github.ts

export const cachedGHStars = cachedFunction(async (repo: string) => {
  const data: any = await $fetch(`https://api.github.com/repos/${repo}`)
  return data.stargazers_count
}, {
  maxAge: 60 * 60,
  name: 'ghStars',
  getKey: (repo: string) => repo
})

响应将被缓存 1小时,如果当缓存在后台更新时,有请求,此时一个过时的值将被发送到客户端。
缓存的值被存储在:.nitro/cache/functions/ghStars//.json 中:

{"expires":1677851092249,"value":43991,"mtime":1677847492540,"integrity":"ZUHcsxCWEH"}

routeRules配置缓存

  • 添加cache配置项即可
    如:博文路由缓存一小时
    nitro.config.js
import { defineNitroConfig } from "nitropack/config";

export default defineNitroConfig({
  routeRules: {
    "/blog/**": {
      swr: 60 * 60,
      // or
      cache: {
        maxAge: 60 * 60
      }
    },
  },
});
  • 自定义存储挂载点,配置cache配置项下的base选项即可
    nitro.config.js配置项
import { defineNitroConfig } from "nitropack/config";

export default defineNitroConfig({
  storage: {
    redis: {
      driver: "redis",
      url: "redis://localhost:6379",
    },
  },
  routeRules: {
    "/blog/**": {
      swr: 60 * 60,
      cache: {
        base: "redis",
      },
    },
  },
});

nitro的资产

静态资源目录public

public目录存储的都是静态资源,打包的时候不会被处理。
使用 Nitro 构建时,它会将 public/ 目录复制到 .output/public/ 并创建一个包含元数据的清单:
json文件

{
  "/image.png": {
    "type": "image/png",
    "etag": "\"4a0c-6utWq0Kbk5OqDmksYCa9XV8irnM\"",
    "mtime": "2023-03-04T21:39:45.086Z",
    "size": 18956
  },
  "/robots.txt": {
    "type": "text/plain; charset=utf-8",
    "etag": "\"8-hMqyDrA8fJ0R904zgEPs3L55Jls\"",
    "mtime": "2023-03-04T21:39:45.086Z",
    "size": 8
  },
  "/video.mp4": {
    "type": "video/mp4",
    "etag": "\"9b943-4UwfQXKUjPCesGPr6J5j7GzNYGU\"",
    "mtime": "2023-03-04T21:39:45.085Z",
    "size": 637251
  }
}

这使 Nitro 根据该清单,无需扫描目录即可了解公共资产,从而通过缓存标头提供高性能。

服务端资源Assets

assets目录中的资源都将添加到服务器包中,会被打包工具打包。

自定义资源目录

可以在自定义目录中添加资源但是需要在nitro中进行配置。
nitro.config.ts

import { defineNitroConfig } from 'nitropack/config'

export default defineNitroConfig({
  serverAssets: [{
    baseName: 'my_directory',
    dir: './server/my_directory'
  }]
})

配置之后资源地址就会被编译成 assets/my_directory/.

查询资源

它们可以通过使用 useStorage('assets:资源名') 来获取资源
eg:

export default defineEventHandler(async () => {
  const data = await useStorage().getItem(`assets/server/data.json`)
  return data
})

nitro插件plugins

插件的导入

会自动导入plugins/文件夹下的插件,但是如果不是plugins文件夹下的需要在配置文件中配置:
nitro.config.js

import { defineNitroConfig } from 'nitropack/config'

export default defineNitroConfig({
  plugins: ['my-plugins/hello.ts']
})

简单插件

plugins/test.ts

export default defineNitroPlugin((nitroApp) => {
  console.log('Nitro plugin', nitroApp)
})

nitro的类型检查

要在您的项目中添加类型提示,请创建一个 tsconfig.json 文件.
tsconfig.json :

{
  "extends": "./.nitro/types/tsconfig.json"
}

运行 npx nitropack prepare 来生成全局自动导入的类型。

如果是nuxt项目引入路径如下:
tsconfig.json :

{
  "extends": "./.nuxt/tsconfig.json"
}

nitro 和 nuxt3的server文件夹

nitro毕竟是Nuxt3的后端实现工具,所以Nuxt的server文件夹下的代码和nitro的规则是一样的。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐