Skip to main content

Vercel Edge Middleware

Why this is important

When customers look to achieve fast performance, elastic scale, enhanced security, and infrastructure efficiency of their web properties, they turn to Jamstack. The static websites provide this promise. Where static sites typically fail to deliver is when you need to alter the web experience of each individual visitor. The marketing users want to keep personalization and A/B testing capabilities, so they can continuously optimize the web experience and increase the conversions.

While there are client-side tools that work on the DOM-level, this approach predates the modern virtual DOM-based front-end libraries and frameworks, like React and Vue. This causes constant conflict for DOM (HTML), which results in flicker, content swaps, poor UX for your visitors in general, as well as a negative impact on Core Web Vitals.

This is when the digital architects turn back to the server-side rendering. Depending on the specific parameters of the solution, this may set you back in terms of infrastructure overhead and even performance. Going back from the Jamstack paradigm to more traditional server-side rendering can come with some trade-offs.

This is where the edge-side processing of static sites comes to the rescue. Powered by the edge compute capability of a Content Delivery Network, this functionality allows to continue generating static pages at build-time (Jamstack) but also provides the ability to modify page contents before it reaches the users' browser.

This allows keeping the best of both worlds: stellar performance, scale, and security characteristics that Jamstack is great for, and run personalization and A/B testing.

Enter Vercel Edge Middleware

Vercel supports the concept of Edge Middleware, which can act as the edge transformation layer for your static site. To learn more about Vercel Edge Middleware, visit this official documentation.

Next.js v12.2 is not supported yet.

At this moment, the current approach works with Next.js 12.1 and not compatible with Next.js 12.2. Stay tuned, we are updating our implementation to support the updated approach in 12.2.

Uniform and Vercel Edge Middleware

Uniform Context comes with the edge-side SDK and plugs natively into Vercel Edge Middleware allowing business users to manage both personalization and A/B testing without developer involvement. The personalization and A/B testing runs in front of the statically generated pages, outside of the browser, which conquers the flicker, content swaps and Cumulative Layout Shift issues. This capability is what we will be referring to as Edge-side personalization.

To learn more about Edge-side vs. Server-side personalization, check out this doc.

Blazing fast page load without flicker

This is a real webpagetest.org test showing 0.6 second page load without any UX issues:

Quick demo

Open this pre-deployed demo site to experience Uniform personalization running on Vercel Edge Middleware, check it out:

Experience these scenarios

  1. Open the For Developers page and go back home. Notice the hero changed to show a different message.
  2. Do a full page reload. Notice the page is stable, and no flicker!
  3. Now, try disabling JavaScript in your browser dev tools. Refresh the page. Notice the personalization still occurs? This is edge-side execution in action.
  4. Re-enable JavaScript to continue with the demo.
  5. Click Forget me to reset the Uniform signal scores. Visit For marketers and return to the home page, notice a different variant. This is personalization based on behavior collected at the edge.
  6. Go to Registration and complete fake registration. Go back to home. Notice a different hero is shown. This is a cookie-based signal in action. Click Forget me to reset the Uniform signal scores.
  7. Now visit the Campaign page. Notice ?utm_campaign=unfrmconf is added to the URL and a different hero is shown? This is a query string-based signal in action.

Use cases

The following use cases are possible with Uniform Context + Vercel Edge Middleware:

  1. GEO-based personalization based on the Geo data available within the Edge Middleware.
  2. Personalize on any data present on the HTTP request:
    • utm_campaign or any query string-based personalization
    • Cookie-based personalization
  3. Uniform A/B testing
  4. Personalization based on session context (user preferences, profile, shopping history, etc.).
  5. CDP-based personalization (or any API-based data context provider for that matter).

    This will require fetching this data from the Edge Functions and supplying the values into Uniform Context quirks.

Pre-requisites

  1. An account with Vercel.
  2. Access to Github.
  3. Node.js installed locally.

Deploying the app to Vercel

This sample app is using a "fake CMS", so it's easy to get started.

It's a sample app

This is a sample app geared towards this specific tutorial. It setup with the essentials only, therefore not recommended to be used as a foundation to build a production site.

  1. Clone this repo:

    git clone https://github.com/uniformdev/examples.git
  2. cd examples/context-edge-vercel

  3. npm install

    Private npm packages needed

    This guide requires access to private Uniform npm packages, requiring an npm token issued by one of the Uniform representatives. Set the token as NPM_TOKEN environment variable (recommended), or replace the token reference in .npmrc file in application root.

  4. Install Vercel CLI if you haven't already with npm i -g vercel

  5. Run this command to deploy your site to your Vercel account: vercel --build-env NPM_TOKEN=<INSERT_NPM_TOKEN_HERE> --prod

    This command adds the NPM_TOKEN environment variable while deploying your site. The value is the npm token that one of our Uniform representatives provided you with.

  6. The CLI will ask you a few questions. Your answers may vary. When asked which directory - hit "enter":

    ? Set up and deploy “~/code/examples/examples/context-edge-vercel”? [Y/n] y
    ? Link to different existing project? [Y/n] n
    ? What’s your project’s name? whatever
    ? In which directory is your code located? ./
  7. After the successful deployment, you may open up the site URL and go through the same scenarios as before to test drive personalization.

    • Try disabling the JS in your browser dev tools to see personalization taking place on the Vercel edge side.
Success!

Congratulations, you have your edge-side personalizable site up and running on Vercel Edge Middleware!

Next steps:

If you'd like to understand the internals more, proceed to the deep dive section below.

Optional deep dive

If you would like to reconstruct this whole setup from scratch, this section walks through all the moving pieces. You can use this section to review the sample app we cloned earlier. After going through this doc, you should be able to integrate this capability into your own web application.

Step 1: Get a Next.js app running

You would need a vanilla Next.js app instrumented to Uniform Context SDK basics. If you don't have one running yet, we recommend completing this tutorial here.

Step 2: Enable the edge-side mode

Follow the steps in this doc.

Don't forget

Make sure you set outputType="edge" on your <UniformContext />:

<UniformContext outputType="edge" ...>
...
</UniformContext>

Step 3: Add Uniform edge context SDK

  1. Install the edge specific packages from Uniform as dependencies in your Next.js app:

    npm install @uniformdev/context-edge @uniformdev/context-edge-vercel buffer
    Private npm package

    This package is private and requires an npm token issued by one of the Uniform representatives.

  2. Create your middleware function under /pages as _middleware.ts. The purpose of this middelware is to register Uniform Context middleware and ensure it is processing all pages:

    import { NextResponse, NextRequest } from "next/server";
    import { createEdgeContext } from "@uniformdev/context-edge";
    import { createUniformEdgeMiddleware } from "@uniformdev/context-edge-vercel";
    import manifest from "../lib/uniform/context-manifest.json";
    import { ManifestV2 } from "@uniformdev/context/*";

    const IGNORED_PATHS = /^\/.*\.(ico|png|jpg|jpeg|svg)$/g;

    export default async function middleware(request: NextRequest) {
    if (process.env.NODE_ENV === "development") {
    console.log("Middleware disabled in development");
    return;
    }

    if (!process.env.VERCEL_URL) {
    console.error("VERCEL_URL environment is not defined");
    return new Response("Configuration Error", {
    status: 500,
    });
    }

    if (
    request.method.toUpperCase() !== "GET" ||
    request.nextUrl.pathname.match(IGNORED_PATHS)
    ) {
    return NextResponse.next();
    }

    const context = createEdgeContext({
    manifest: manifest as ManifestV2,
    request,
    });

    const middleware = createUniformEdgeMiddleware();

    const response = await middleware({
    context,
    origin: new URL(`https://${process.env.VERCEL_URL}`),
    request,
    });

    return new Response(response.body, {
    ...response,
    headers: {
    ...response.headers,
    "Cache-Control": "no-store, must-revalidate",
    Expires: "0",
    },
    });
    }

That's it! You made it to the end of this walkthrough.