Nitro Documentation

repository·main·Indexed 27 days ago

https://github.com/nitrojs/nitro

A production-ready, platform-agnostic server engine designed to extend Vite applications. Nitro provides a zero-config experience for adding server routes and deploying universal JavaScript servers across various environments. Key features include filesystem-based routing, a flexible renderer for SPAs and SSR, and integration with Rolldown for build customization.

Tokens
83.4K
Snippets
310
Records
416
Agent score
95%

What's inside Nitro

  1. Overview of Nitro

    main
    Nitro is a production-ready server engine that extends Vite applications. It is designed to be platform-agnostic, allowing you to add server routes and deploy your application across multiple environments with a zero-config experience.
  2. Overview of Nitro features

    main

    Nitro is a production-ready server engine that extends Vite applications. Key capabilities include:

    • File-system Routing: Automatically register routes in a routes/ folder or use a custom entry point (H3, Hono, Elysia, Express).
    • Multi-runtime Deployment: Deploy to Node.js, Cloudflare Workers, Deno, Bun, AWS Lambda, Vercel, Netlify, etc., with zero config.
    • Universal Storage: A key-value storage abstraction (powered by unstorage) that works with filesystem, Redis, Cloudflare KV, and more.
    • Built-in Caching: Cache route handlers and functions using various storage backends and stale-while-revalidate patterns.
    • Server Entry: Support for Web standard servers including H3, Hono, Elysia, Express, or the raw fetch API.
    • Universal Renderer: Works with any frontend framework as a server layer.
    • Server Plugins: Extend runtime behavior by hooking into lifecycle events via the plugins/ directory.
    • Built-in Database: A lightweight SQL layer (powered by db0) with support for SQLite, PostgreSQL, MySQL, and Cloudflare D1.
    • Assets: Serve public assets to clients or bundle server assets for programmatic access.
  3. Create a Server Entry for React SSR

    main

    The server entry point is responsible for rendering your React application to a streaming HTML response. For edge-compatible streaming, use renderToReadableStream from react-dom/server.edge.

    To manage assets (CSS and JS) correctly, import your client and server entries using the ?assets=client and ?assets=ssr query parameters. You can then use the .merge() method on the client assets to combine them with server assets, providing a unified manifest of stylesheets, module preloads, and the main entry script.

    import "./styles.css";
    import { renderToReadableStream } from "react-dom/server.edge";
    import { App } from "./app.tsx";
    
    import clientAssets from "./entry-client?assets=client";
    import serverAssets from "./entry-server?assets=ssr";
    
    export default {
      async fetch(_req: Request) {
        const assets = clientAssets.merge(serverAssets);
        return new Response(
          await renderToReadableStream(
            <html lang="en">
              <head>
                <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                {assets.css.map((attr: any) => (
                  <link key={attr.href} rel="stylesheet" {...attr} />
                ))}
                {assets.js.map((attr: any) => (
                  <link key={attr.href} type="modulepreload" {...attr} />
                ))}
                <script type="module" src={assets.entry} />
              </head>
              <body id="app">
                <App />
              </body>
            </html>
          ),
          { headers: { "Content-Type": "text/html;charset=utf-8" } }
        );
      },
    };
  4. Deploy to Cloudflare Pages

    main

    To deploy a Nitro application to Cloudflare Pages, use the cloudflare_pages preset.

    Note: Cloudflare Workers (cloudflare_module) is currently the recommended preset. Use Pages only if specific features are required.

    Configuration

    import { defineConfig } from "nitro";
    
    export default defineConfig({
        preset: "cloudflare_pages"
    })

    Nitro automatically generates a _routes.json file for routing. You can override this using the cloudflare.pages.routes config option.

    Local Preview

    npm run build
    wrangler pages dev

    Manual Deploy

    wrangler login
    wrangler pages deploy
  5. Configure GitHub Actions workflow for GitHub Pages deployment

    main

    Use the following GitHub Actions workflow configuration to build your Nitro app and deploy it to GitHub Pages. This workflow includes a build job that generates the output and a deploy job that uses the actions/deploy-pages action.

    Key requirements:

    1. Set NITRO_PRESET: github_pages in the build step.
    2. Upload the ./.output/public directory using actions/upload-pages-artifact@v1.
    3. The deploy job must have permissions for pages: write and id-token: write.
    4. The deploy job must depend on the build job via needs: build.
    name: Deploy to GitHub Pages
    
    on:
      workflow_dispatch:
      push:
        branches:
          - main
    
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v5
          - run: corepack enable
          - uses: actions/setup-node@v6
            with:
              node-version: "18"
    
          - run: npx nypm install
          - run: npm run build
            env:
              NITRO_PRESET: github_pages
    
          - name: Upload artifact
            uses: actions/upload-pages-artifact@v1
            with:
              path: ./.output/public
    
      deploy:
        needs: build
        permissions:
          pages: write
          id-token: write
        environment:
          name: github-pages
          url: ${{ steps.deployment.outputs.page_url }}
        runs-on: ubuntu-latest
        steps:
          - name: Deploy to GitHub Pages
            id: deployment
            uses: actions/deploy-pages@v1
  6. Define dynamic routes with parameters

    main

    You can define dynamic routes using the [<param>] syntax. Parameters are accessible via event.context.params or the getRouterParam utility.

    • Single param: Use [name].ts (e.g., routes/hello/[name].ts matches /hello/nitro).
    • Multiple params: Use nested folders like [name]/[age].ts (e.g., routes/hello/[name]/[age].ts). You cannot define multiple params in a single filename.
    • Catch-all params: Use [...name].ts to capture all remaining URL segments (e.g., routes/hello/[...name].ts matches /hello/nitro/is/hot).
    import { defineHandler } from "nitro";
    
    export default defineHandler((event) => {
      const { name } = event.context.params;
    
      return `Hello ${name}!`;
    });
  7. Deploy Nitro apps to Cleavr

    main

    To deploy a Nitro application to Cleavr, you must set the Nitro preset to cleavr. This allows Nitro to build the application in a format compatible with Cleavr's environment.

    Configuration

    Update your configuration file (e.g., nitro.config.ts or your framework's config) to include the cleavr preset:

    export default {
      nitro: {
        preset: 'cleavr'
      }
    }

    Cleavr Panel Setup

    After pushing your changes to your code repository, follow these steps in the Cleavr dashboard:

    1. Provision a new server.
    2. Add a website, selecting Nuxt 3 as the app type.
    3. Navigate to web app > settings > Code Repo and point it to your project's code repository.

    Note: Integration with this provider is possible with zero configuration.

  8. Integrate Express with Nitro using a custom server entry

    main

    To use Express as your backend framework with Nitro, you must provide a custom server entry file named server.node.ts in your project root. Nitro will auto-detect this file and use it as the entry point. This approach gives you full control over Express routing and middleware, but note that the .node.ts suffix indicates this entry is Node.js specific and is not compatible with other runtimes like Cloudflare Workers or Deno.

    Setup Requirements

    1. Dependencies: Ensure express and @types/express are installed.
    2. Vite Configuration: Include the nitro() plugin in your vite.config.ts.
    3. Server Entry: Create server.node.ts and export your Express application instance as the default export.
    import Express from "express";
    
    const app = Express();
    
    app.use("/", (_req, res) => {
      res.send("Hello from Express with Nitro!");
    });
    
    export default app;
  9. Deploy Nitro apps to EdgeOne Pages via Control Panel

    main

    To deploy your Nitro application to EdgeOne Pages using the web control panel, follow these steps:

    1. Go to the EdgeOne pages control panel and click Create project.
    2. Select Import Git repository as the deployment method (supports GitHub, GitLab, Gitee, and CNB).
    3. Select the appropriate repository and branch for your application.
    4. Crucial Step: Add the environment variable NITRO_PRESET with the value edgeone-pages during the setup process.
    5. Click Deploy.
  10. Implement Global Middleware

    main

    Global middleware is defined in the middleware/ directory. These handlers run after route rules. You can use event.context to pass data through the lifecycle.

    Warning: Returning from a middleware will close the request; avoid doing this unless you intend to terminate the request early.

    import { defineHandler } from "nitro";
    
    export default defineHandler((event) => {
      event.context.info = { name: "Nitro" };
    });
  11. Enable OpenAPI support in Nitro

    main

    To use Nitro's automatic OpenAPI specification generation and interactive documentation UIs, enable the experimental openAPI feature in your nitro.config.ts.

    Once enabled, the following endpoints are available during development:

    • /_openapi.json: The OpenAPI 3.1.0 JSON specification.
    • /_scalar: The Scalar API reference UI.
    • /_swagger: The Swagger UI.
    IMPORTANT

    OpenAPI support is currently experimental.

    import { defineConfig } from "nitro";
    
    export default defineConfig({
      experimental: {
        openAPI: true,
      },
    });