vinext

repository·main·Indexed 27 days ago

https://github.com/cloudflare/vinext

A framework that reimplements the Next.js API surface on Vite, allowing Next.js applications (targeting version 16.x) to run on Vite-based toolchains. It supports both App Router and Pages Router, including SSR, ISR, and Server Actions. Optimized for Cloudflare Workers with native support for bindings, KV caching, and image optimization via @vinext/cloudflare, it also supports other platforms like Node.js, Vercel, and Netlify via the Nitro Vite plugin.

Tokens
19.6K
Snippets
30
Records
121
Agent score
93%

What's inside vinext

  1. Understand the vinext AsyncLocalStorage (ALS) architecture

    main
    vinext uses AsyncLocalStorage (ALS) to isolate request state and prevent data bleeding (e.g., headers, cookies, <Head> children, and cache tags) between concurrent requests. The architecture uses a two-tier scope model to distinguish between state that lasts for the entire request and state that is scoped to individual function calls.
  2. Understand vinext core concepts and compatibility

    main

    vinext is a Vite plugin that reimplements the Next.js public API (routing, SSR, next/* module imports, and the CLI) to allow running Next.js applications on Vite instead of the Next.js compiler.

    Key Characteristics:

    • Target Version: Targets Next.js 16.x. It does not support deprecated APIs from older versions.
    • Router Support: Supports both the Pages Router and the App Router (including file-system routing, SSR, client hydration, and deployment to Cloudflare Workers).
    • Dependency Model: Does not require next to be installed. vinext provides fallback declarations for next and next/* APIs. If next is installed, vinext uses its authoritative types and adds its own extensions.
    • Comparison to OpenNext: Unlike OpenNext, which adapts the output of next build, vinext reimplements the APIs from scratch on Vite. This results in faster builds and smaller bundles but may have less coverage of the long tail of Next.js features.
    • Deployment:
      • Cloudflare Workers: Natively supported.
      • Other Platforms: Supported via the Nitro Vite plugin (e.g., Vercel, Netlify, AWS Amplify, Deno Deploy, Azure).
  3. Use @vinext/types for type declarations

    main

    The @vinext/types package provides type declarations for vinext's Next.js-compatible public API.

    Important: Applications should normally load these types through the vinext/types entry point rather than importing the @vinext/types package directly.

  4. Deploy to Cloudflare Workers

    main

    vinext provides a one-command workflow for deploying to Cloudflare Workers using @vinext/cloudflare deploy. This integration includes native support for cloudflare:workers bindings, KV caching, and image optimization.

    Prerequisites

    1. Authentication Choose one method:

    • wrangler login: Recommended for local development. Opens a browser to authenticate.
    • CLOUDFLARE_API_TOKEN: Use this for CI/CD. Create a token at dash.cloudflare.com/profile/api-tokens using the Edit Cloudflare Workers template.

    2. Account ID Provide your Cloudflare account ID in wrangler.jsonc or via the CLOUDFLARE_ACCOUNT_ID environment variable.

    {
      "account_id": "<your-account-id>",
      ...
    }

    Setup

    Run vinext init --platform=cloudflare first to install dependencies and configure vite.config.* and wrangler.jsonc automatically.

    npx @vinext/cloudflare deploy
    # or using vp exec
    vp exec vinext-cloudflare deploy
  5. Run performance benchmarks locally

    main

    You can run the performance pipeline locally using benchmarks/perf/run-scenarios.mjs. Use the VINEXT_PERF_SAMPLES environment variable to specify the output path for the results.

    1. Prepare Scenarios

    Run this to execute any configured performanceSetup commands:

    node benchmarks/perf/run-scenarios.mjs --setup-only

    2. Run Direct Samples

    To run a single direct sample for every implementation without the CI profiler:

    VINEXT_PERF_SAMPLES="$PWD/benchmarks/results/perf-samples.jsonl" \
      node benchmarks/perf/run-scenarios.mjs --direct --rounds=1

    3. Run CI Measurement Path

    To simulate the CI measurement path (requires the pinned CodSpeed runner and wall-time harness):

    VINEXT_PERF_SAMPLES="$PWD/benchmarks/results/perf-samples.jsonl" \
      node benchmarks/perf/run-scenarios.mjs
    # Example: Running direct samples
    VINEXT_PERF_SAMPLES="$PWD/benchmarks/results/perf-samples.jsonl" \
      node benchmarks/perf/run-scenarios.mjs --direct --rounds=1
  6. Configure @vinext/cloudflare adapters in Vite

    main

    To use Cloudflare-specific cache and image backends with vinext, declare the adapters within the vinext() plugin configuration in your vite.config.ts.

    • Use kvDataAdapter() to back the data cache (fetch, "use cache", unstable_cache) and enable ISR using a Workers KV namespace. This requires a KV binding named VINEXT_KV_CACHE.
    • Use imagesOptimizer() to back next/image transformations using a Cloudflare Images binding named IMAGES.
    import { kvDataAdapter } from "@vinext/cloudflare/cache/kv-data-adapter";
    import { imagesOptimizer } from "@vinext/cloudflare/images/images-optimizer";
    
    export default defineConfig({
      plugins: [
        vinext({
          cache: {
            data: kvDataAdapter(), // KV-backed data cache (binding: VINEXT_KV_CACHE)
          },
          images: { optimizer: imagesOptimizer() }, // Cloudflare Images binding: IMAGES
        }),
        cloudflare(),
      ],
    });
  7. Create a new vinext project

    main

    To start a new project from scratch, use the create-vinext-app command. This creates a TypeScript App Router project with Tailwind CSS that is Cloudflare Workers-ready by default. If you prefer a Node.js target, pass the --platform=node flag.

    pnpm create vinext-app@latest my-app
  8. Deploy Cloudflare Workers projects

    main

    You can deploy Cloudflare Workers projects using the @vinext/cloudflare CLI. Depending on your environment, use one of the following commands:

    • Standard: npx @vinext/cloudflare deploy
    • With Vite+: vpx @vinext/cloudflare deploy
    • Using locally installed bin: vp exec vinext-cloudflare deploy
    npx @vinext/cloudflare deploy
  9. Deploy to other platforms via Nitro

    main

    To deploy to platforms other than Cloudflare (e.g., Vercel, Netlify, AWS, Node.js), use Nitro as a Vite plugin.

    Setup:

    1. Install nitro: npm install nitro.
    2. Add nitro() to your vite.config.ts plugins array.
    3. For local builds, set the NITRO_PRESET environment variable to specify the target platform.

    Supported Platforms via Nitro Presets:

    • vercel
    • netlify
    • aws_amplify
    • deno_deploy
    • node (for standalone Node.js servers)
    import { defineConfig } from "vite";
    import vinext from "vinext";
    import { nitro } from "nitro/vite";
    
    export default defineConfig({
      plugins: [vinext(), nitro()],
    });
    # Example: Local build for Vercel
    NITRO_PRESET=vercel npx vite build
    
    # Example: Local build for Node.js
    NITRO_PRESET=node npx vite build
    node .output/server/index.mjs
  10. Add a performance scenario

    main

    To add a new performance benchmark, you must modify scenarios.mjs. The process involves three steps:

    1. Setup: Add any required one-time setup commands to the performanceSetup array in scenarios.mjs.
    2. Scenario Definition: Add a new scenario object to the performanceScenarios array.
    3. Implementation: Add implementations to the scenario that execute an adapter command. Each implementation must report a single numeric value using reportPerformanceSample(value).

    Scenario Object Schema:

    • id: Unique identifier for the scenario.
    • suite: The category of the benchmark.
    • label: Human-readable name.
    • description: Detailed description.
    • unit: The measurement unit (e.g., ms).
    • lowerIsBetter: Boolean indicating if a lower value is preferable.
    • implementations: An array of implementation objects:
      • id: Unique identifier for the implementation (the full ID is <implementation id>-<scenario id>).
      • label: Human-readable name.
      • profile: Boolean. Set to true to enable subprocess tree sampling (e.g., for vinext traces).
      • command: The command array to execute.
      • compareBase: Boolean. If true, the implementation is measured at both the PR base and head.

    No changes to workflows, databases, APIs, normalizers, or dashboards are required.

    {
      id: "production-build",
      suite: "Build",
      label: "Production build time",
      description: "Clean production build.",
      unit: "ms",
      lowerIsBetter: true,
      implementations: [
        {
          id: "vinext",
          label: "vinext",
          profile: true,
          command: ["node", "benchmarks/perf/build-time.mjs", "vinext"],
        },
      ],
    }