🧩 Fixing ā€œCannot destructure property 'Request' of undefinedā€ in Vite + React Builds

Recently, while working on a React + Vite project, I ran into a strange runtime error after building my app:

Cannot destructure property 'Request' of undefined as it is undefined

This issue didn’t appear in development mode — only in the production build.
After some debugging, the fix turned out to be related to how the Istanbul plugin was loaded in the Vite configuration.

Let’s go through what happened :backhand_index_pointing_down:


:gear: The Original Setup

Here’s the initial vite.config.js:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import istanbul from 'vite-plugin-istanbul';
require("dotenv").config();

export default defineConfig({
  plugins: [
    react({ include: "**/*.jsx" }),
    istanbul({
      forceBuildInstrument: true,
      include: 'src/*',
      exclude: ['node_modules', 'test/'],
      extension: ['.js', '.ts', '.dist', '.jsx'],
      requireEnv: true,
    }),
  ],
  define: {
    global: "window",
  },
  resolve: {
    alias: {
      "./runtimeConfig": "./runtimeConfig.browser",
    },
  },
  server: { port: 3000 }
})

Everything worked locally, but after running the production build, the app crashed with the error:

Cannot destructure property ā€˜Request’ of undefined


:brain: The Root Cause

The error happened because the Istanbul plugin, which is meant for test coverage, was included even in the production build.

This plugin is designed to work in a Node.js environment — it expects Node-only variables like global and process.
When it runs inside the browser build, those variables don’t exist, and the plugin’s code ends up breaking parts of the global environment.

That’s why, when the browser tried to use Request (a built-in web API), it couldn’t find it anymore — resulting in the error.

In short:

  • Istanbul ran in production (by mistake).
  • It tried to use Node.js features not available in browsers.
  • This broke the global environment and made Request undefined.

:white_check_mark: The Fix: Conditional Plugin Loading + Safe Global Definition

Here’s the updated (working) version of vite.config.js:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
require("dotenv").config();

export default defineConfig(async () => {
  const { default: istanbul } = await import('vite-plugin-istanbul');
  
  return {
    plugins: [
      react({ include: "**/*.jsx" }),
      ...(process.env.NODE_ENV !== 'production' ? [istanbul({
        forceBuildInstrument: true,
        include: 'src/*',
        exclude: ['node_modules', 'test/'],
        extension: ['.js', '.ts', '.dist', '.jsx'],
        requireEnv: true,
      })] : []),
    ],
    optimizeDeps: {
      esbuildOptions: {
        define: {
          global: 'globalThis', // āœ… ensures browser-safe global variable
        },
        target: 'esnext'
      },
    },
    resolve: {
      alias: {
        "./runtimeConfig": "./runtimeConfig.browser",
      },
    },
    build: {
      outDir: 'dist',
      target: 'esnext',
      minify: 'esbuild',
      inlineDynamicImports: true,
    },
    server: { port: 3000, open: true }
  };
});

Here’s what changed and why it works:

  1. Dynamic Import for Istanbul Plugin
const { default: istanbul } = await import('vite-plugin-istanbul');

This defers loading the plugin until the environment is initialized.
2. Conditional Plugin Inclusion

...(process.env.NODE_ENV !== 'production' ? [istanbul(...)] : [])

This ensures Istanbul only runs in development and testing, never in production.
3. Safe Global Definition

define: { global: 'globalThis' }

This maps Node’s global to the browser’s globalThis, preventing environment mismatches.


:rocket: The Outcome

Once the build configuration was updated:

  • The production build ran smoothly.
  • No more Request errors.
  • Code coverage reports still worked during testing.

:light_bulb: Takeaway

When using Vite plugins that depend on Node.js (like Istanbul for coverage):

  • Only load them in non-production environments.
  • Avoid static imports that run too early.
  • Always map global → globalThis for browser compatibility.
3 Likes