30

I'm creating a project using Vite with vanilla-ts, at one point I had to use the readdir method from the fs-extra package, but it created an error saying process is not defined, some suggested I place this code in my vite-config.ts file:

import { defineConfig } from 'vite'

export default defineConfig({
  define: {
    'process.env': {}
  }
})

That fixed the initial error but created a new one that read global is not defined, more research and by adding 'global': {} on the define object, like before fixed the error but created another one saying Cannot read properties of undefined (reading 'substr')

Code used:

import { readdirSync } from 'fs-extra';

const folders = readdirSync('./', { withFileTypes: true })
  .filter(dir => dir.isDirectory);

Vite version: ^2.9.5

FS-Extra version: ^9.0.13

8BitSoda
  • 368
  • 1
  • 4
  • 9

12 Answers12

45

The problem is because vite doesn't define a global field in window as webpack does. And some libraries relies on it since webpack is much more older than vite.

Just insert at the very start, before any library import:

// init.js
window.global ||= window;

A good way to have the above code before any import is to write in new file, let's call it init.js, and import it as first.

// in index.js or main.js file

import "./init"
// import your app and libraries after... 
import App from './App'
import ...
Yairopro
  • 9,084
  • 6
  • 44
  • 51
  • 4
    This GitHub comment may be useful, I've been able to solve this issue (Svelte + Vite app) https://github.com/bevacqua/dragula/issues/602#issuecomment-1109840139 – endorama Aug 20 '22 at 18:35
  • 2
    Genius answer. Other ways —using `define`— are just a workaround and don't work in some cases, especially when dealing with dependencies. This should be the verified answer. – l-portet Feb 12 '23 at 20:54
  • @endorama your solution worked on my setup, Nuxt3 + Vite when using WaxJS – Rod Maniego Feb 16 '23 at 19:36
  • 1
    genuis, a good way .. thanks – Miloud Mokkedem Apr 08 '23 at 00:49
  • can confirm, this worked better. – amiellion Apr 12 '23 at 14:41
  • fantastic, spot on! – adoubleyoueye Apr 21 '23 at 17:28
  • Nope, this doesn't work in development mode for me. The vite.config.ts approach works, but this breaks vitest with "ReferenceError: window is not defined" – Lqueryvg May 24 '23 at 08:06
  • this worked in development and prod builds for me. The vite config extension answer fixed the development build but during minification other libraries started complaining – PM1 Jun 03 '23 at 00:34
  • After hours of searching and testing multiple solution - that did the job! – Volmarg Reiso Jun 11 '23 at 04:47
  • This is the only way that made vite build, build-storybook, run dev, and run storybook all work for me. Thanks. Though now I'm worried about testing after reading @Lqueryvg comment. Haven't gotten that far yet – isimmons Jun 12 '23 at 06:25
  • @Lqueryvg try to replace window with globalThis – Yairopro Jun 13 '23 at 20:26
  • 1
    FYI, I solved my problem like this: `define: process.env.NODE_ENV === 'development' ? { global: 'window' } : {}` (in vite.config.ts) – Lqueryvg Jun 14 '23 at 08:31
24

another solutions:

  export default defineConfig({
    define: {
      global: {},
    },
  })

But be careful: For example, process.env.FOO and APP_VERSION are good fits. But process or global should not be put into this option. Variables can be shimmed or polyfilled instead.

source: https://vitejs.dev/config/shared-options.html#define

  • 13
    What worked for me was to define `global: 'window'`, this way, libraries depending on global.something worked (eg lodash used `global.isFinite()` which was throwing errors) – Patrick Hübl-Neschkudla Sep 13 '22 at 08:27
  • 1
    You suggested what is marked in the question as not working... – Joel Bourbonnais Dec 09 '22 at 20:24
  • 5
    [The Vite docs warn against using define for global](https://vitejs.dev/config/shared-options.html#define), as it can replaces the string `global` *everywhere* in the code, not just when it's used as a variable name. So @Yairopro's answer is the way to go. – Ethan Feb 21 '23 at 03:21
  • this works in development mode for me, but then vitest breaks with "ReferenceError: window is not defined" – Lqueryvg May 24 '23 at 08:07
4

Omg, thank you, Patrick Hübl-Neschkudla !

What worked for me was to define global: 'window', this way, libraries depending on global.something worked (eg lodash used global.isFinite() which was throwing errors) – Patrick Hübl-Neschkudla Sep 13, 2022 at 8:27

I was struggling with this issue for 2 hours and finally found the solution from you.

For me, the issue was, AWS Authenticator needed to use Buffer package that required 'global' to be defined on vite config, while I also had Phaser package that was declaring global.somethingsomething in its main phaser.js code.

With the 'global' defined in vite config, running 'npm run build' failed when compiling phaser, saying there is unexpected token at the part it declares 'global: blah blah'.

When I don't define 'global' in vite config, then 'npm run build' would NOT fail, but the AWS Authenticator will fail to work and throw console.error, saying 'global' was not defined in Buffer.

Setting

define: {global: 'window'}

in vite.config solved this issue.

Albert
  • 49
  • 3
  • 3
    [The Vite docs warn against using define for global](https://vitejs.dev/config/shared-options.html#define), as it can replaces the string `global` *everywhere* in the code, not just when it's used as a variable name. So @Yairopro's answer is the way to go. – Ethan Feb 21 '23 at 03:22
  • 1
    Setting `define: {global: 'window'}` causes build failures in dependencies for me. `global.window |= window;` works though – rcbevans Apr 07 '23 at 18:10
4

Referencing https://gist.github.com/FbN/0e651105937c8000f10fefdf9ec9af3d, I realized that:

  1. the issue seemed esbuild-specific
  2. I could fix it with:
export default defineConfig({
    optimizeDeps: {
      esbuildOptions: {
        define: {
          global: 'globalThis'
        }
      }
    }
  })
Shawn
  • 41
  • 2
3

As mentioned here, I defined the global in my vite.config.ts file, it worked for development, but build had error.

1- Fix the development error:

Simply, I added that global conditionally because having it for production causes builds getting failure.

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";

export default defineConfig(({ mode }) => {
  const config = {
    plugins: [react()],
    define: {} as any,
  };

  if (mode === "development") {
    config.define.global = {};
  }

  return config;
});

2- Fix the production error:

In my case was a React app, I added the snippet below at the top of the main.tsx file:

window.global ||= window;
Amir2mi
  • 896
  • 9
  • 13
  • This is the best answer, I've tested others and none of them work correctly for both environments. – Emil Jun 06 '23 at 13:42
1

The solution that worked for me, is by adding the below code to main.js or index.js.

declare global {
  interface Window {
    global: any;
  }
}

if (typeof window !== "undefined") {
  window.global = window;
}
0

This solved the issue for me..

Inside my vite.config.js, I added this

// ...every other thing, 
define: {
    global: {},
    "process.env": {}
  }

the final file was

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  define: {
    global: {},
    "process.env": {}
  }
});
0

setting an empty global inside your vite config can break other libraries such as react-pdf, so the best and easiest way is to add it to your index.html file as follows:

<script>
    if (global === undefined) {
      var global = window;
    }
  </script>
hamdi islam
  • 1,327
  • 14
  • 26
0

Sometimes we have 2 errors related to varialble global

1: global is not define
2. _global is not define

When we encountered these 2 errors in vite.js, we can resolve by: `

export default defineConfig({
  build: {
    sourcemap: true,
  },
  define: {
    _global: {},
  },
  plugins: [react(), EnvironmentPlugin(['VITE_APP_TEXT'])],
  publicDir: 'public',
  resolve: {
    alias: [{ find: '@', replacement: resolve(__dirname, 'src') }],
  },
  server: {
    host: true,
    port: 3000,
  },
})

and updateindex.html` by:

if (typeof window !== "undefined") {
    window.global = window;
}
0

Found this solution in Github. AWS SDK uses 'global' for some things. This is why it happens. Just use it on your index.html on your React project.

<!-- your index.html -->
<script>
/**
 * this is a hack for dragula
 * error: global is not defined
 */
var global = global || window
</script>
Sebastian Paduano
  • 301
  • 1
  • 5
  • 17
0
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig(({ mode }): UserConfig => {
 const isProduction = mode === 'production';
 const config: UserConfig = {
   plugins: [react()],
   build: {
     outDir: 'build',
     sourcemap: 'inline',
   },
   resolve: {
     alias: {
       '@': path.resolve(__dirname, 'src'),
     },
   },
 };
 if (!isProduction) {
   config.define = {
     'process.env': {},
     global: {},
   };
 }
 return config;
});
Ashe
  • 1
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 15 '23 at 18:07
-8

You are most likely using Vite for a frontend project. fs-extra (file access) / global (nodejs global) are not something that exist in the browser (frontend).

Fix

Use a backend project and export an API that you can then use from the Vite / frontend to make file system changes on the server.

basarat
  • 261,912
  • 58
  • 460
  • 511
  • How would I implement this, do I use a library or... maybe with existing tools, if so, please provide pseudocode or at least an example, @basarat. – 8BitSoda May 05 '22 at 12:22