Search code examples
next.jsvercelvercel-middleware

How to disable Vercel Middleware in specific environment without invoking the middleware?


Vercel provides IP / user access control features, but they do not work for my use case. Therefore, I am currently using middleware on my NextJS site hosted on Vercel solely to block unauthorized access to my preview sites based on user IP.

I don't need/want the middleware to run on my production site. To prevent this, I am performing an environment check within the middleware itself, and if production is detected, the middleware exits early. However, performing that check results in a middleware invocation, which I don't want.

As a refresher, here is what the Vercel docs say about middleware:

Middleware will be invoked for every route in your project. If you only want it to be run on specific paths, you can define those either with a custom matcher config or with conditional statements.

While the config option is the preferred method, as it does not get invoked on every request, you can also use conditional statements to only run the Middleware when it matches specific paths.

Neither of these approaches allow for environment-specific disabling without invoking the middleware.

Is there a good way in which I can "disable" middleware on my production site? Or is there another approach I can use as a workaround? Perhaps by modifying package.json or build pipeline steps?


Solution

  • We can leverage a prebuild step in package.json that uses environment variables to create/delete/modify middleware.json:

    package.json

    "scripts": {
      "prebuild": "node build-files.js"
    }
    

    build-files.js

    const fs = require('fs');
    
    if (process.env.GENERATE_MIDDLEWARE === 'true') {
      const content = 'async function middleware(req) {console.log("Middleware is running")}';
      fs.writeFileSync('./src/middleware.js', content, 'utf8');
      console.log('middleware.js file created');
    } else {
      if (fs.existsSync('./src/middleware.js')) {
        fs.unlinkSync('./src/middleware.js');
        console.log('middleware.js file removed ');
      }
    }