Vercel Middleware for Every Vite Project

May 04, 2022
cover image

Vercel Middleware is a great way to add A/B Testing, Bot Detection, Basic Auth and other server-side features to your static website, it's built on top of Edge Function so it almost feels like visting a static site, giving you the benefits of static with the power of dynamic.

Vite is the new standard way to create a single-page static website (and even server-rendered applications, see SvelteKit and Nuxt), but as far as I know there's no easy way to use Vercel Middleware in a Vite project, the official way to use it is either:

  • Next.js, which is not Vite
  • SvelteKit, recently allows you deploy the entire app as a Vercel Edge Function

And that's it, if I'm not missing something here.

But I just want a simple way to use Vercel Middleware in my Vite SPA, I mean any Vite SPA, regardless of what frontend framework I use. That's why I made vite-vercel, a light-weight Vite plugin that brings Vercel Middleware to your static site, the usage is simple and straightforward:

First install vite-vercel in your project:

npm i -D vite-vercel

And use it in vite.config.ts:

import { defineConfig } from "vite"
import vercel from "vite-vercel"

export default defineConfig({
  plugins: [
    vercel({
      middleware: "./middleware.ts",
    }),
  ],
})

Then create a middleware.ts:

import { MiddlewareRequest, MiddlewareResponse } from "vite-vercel/server"

export default (request: MiddlewareRequest) => {
  const url = new URL(request.url)

  if (url.pathname === "/from-middleware") {
    return new Response("from middleware")
  }

  // Rewrite to another URL
  if (url.pathname === "/todo") {
    return MiddlewareResponse.rewrite(
      "https://jsonplaceholder.typicode.com/todos/1",
    )
  }

  // Continue serving `index.html`
  return MiddlewareResponse.next()
}

The API is loosely modeled after Next.js' _middleware.ts (no request.nextUrl here) so you will feel right at home if you already had experienced with Vercel and Next.js. In case you're new, the API looks like (req: Request) => Response where Request and Response are just web fetch API.

The middleware runs before the Vite-generated index.html file, so you have to call MiddlewareResponse.next() if you want to pass through the request to it.

The Code

I didn't open source the code, but you can feel free to use the the npm package, if you want to take a look at the code or use the issue tracker right now, you can sponsor me on GitHub to get access to it. I will open source it in a couple months 😉.