react-native-mmkv icon indicating copy to clipboard operation
react-native-mmkv copied to clipboard

Global is Not Defined

Open jjcfatras opened this issue 10 months ago • 4 comments

I keep running into this issue on startup. I'm using react-native-web with nextjs (page router) via the @expo/next-adapter https://www.npmjs.com/package/@expo/next-adapter. Attached is a screenshot of the error and of my next.config.js file.

Image

Image

jjcfatras avatar Feb 06 '25 16:02 jjcfatras

Guten Tag, Hans here! 🍻

It looks like you're running into a "Global is Not Defined" issue with your setup. To help mrousavy investigate this, we really need more information. Could you please provide logs from your runtime? If you're using Xcode or Android Studio, you can find them in the logs window or use adb logcat for Android. This will help us understand what's going wrong.

And remember, if you want to support the project and get faster responses, consider sponsoring mrousavy at GitHub Sponsors. Thank you!

Note: If you think I made a mistake, please ping @mrousavy to take a look.

maintenance-hans[bot] avatar Feb 06 '25 16:02 maintenance-hans[bot]

Does this help?

Image

jjcfatras avatar Feb 06 '25 16:02 jjcfatras

I am running into this as well after upgrading MMKV to 3.x from 2.x.

index.js:648 Uncaught ReferenceError: global is not defined
    at isTest (PlatformChecker.js:9:3)
    at new MMKV (MMKV.js:29:83)
    at eval (StorageContext.ts:8:17)
    at (:3000/packages/app/storage/StorageContext.ts (http://localhost:3000/_next/static/chunks/pages/_app.js:20643:1)
    at options.factory (webpack.js:703:31)
    at __webpack_require__ (webpack.js:37:33)
    at fn (webpack.js:360:21)
    at eval (index.ts:2:73)
    at (:3000/packages/app/storage/index.ts (http://localhost:3000/_next/static/chunks/pages/_app.js:20654:1)
    at options.factory (webpack.js:703:31)
    at __webpack_require__ (webpack.js:37:33)
    at fn (webpack.js:360:21)
    at eval (useFeatureFlag.web.ts:6:66)
    at (:3000/packages/app/feature-flags/useFeatureFlag.web.ts (http://localhost:3000/_next/static/chunks/pages/_app.js:19950:1)
    at options.factory (webpack.js:703:31)
    at __webpack_require__ (webpack.js:37:33)
    at fn (webpack.js:360:21)
    at eval (_app.tsx:29:91)
    at (:3000/pages-dir-browser)/src/pages/_app.tsx (http://localhost:3000/_next/static/chunks/pages/_app.js:21423:1)
    at options.factory (webpack.js:703:31)
    at __webpack_require__ (webpack.js:37:33)
    at fn (webpack.js:360:21)
    at eval (next-client-pages-loader.js?absolutePagePath=private-next-pages%2F_app&page=%2F_app!:5:16)
    at eval (route-loader.js:238:51)

wongk avatar Apr 17 '25 19:04 wongk

I am running into this as well after upgrading MMKV to 3.x from 2.x.

index.js:648 Uncaught ReferenceError: global is not defined
    at isTest (PlatformChecker.js:9:3)
    at new MMKV (MMKV.js:29:83)
    at eval (StorageContext.ts:8:17)
    at (:3000/packages/app/storage/StorageContext.ts (http://localhost:3000/_next/static/chunks/pages/_app.js:20643:1)
    at options.factory (webpack.js:703:31)
    at __webpack_require__ (webpack.js:37:33)
    at fn (webpack.js:360:21)
    at eval (index.ts:2:73)
    at (:3000/packages/app/storage/index.ts (http://localhost:3000/_next/static/chunks/pages/_app.js:20654:1)
    at options.factory (webpack.js:703:31)
    at __webpack_require__ (webpack.js:37:33)
    at fn (webpack.js:360:21)
    at eval (useFeatureFlag.web.ts:6:66)
    at (:3000/packages/app/feature-flags/useFeatureFlag.web.ts (http://localhost:3000/_next/static/chunks/pages/_app.js:19950:1)
    at options.factory (webpack.js:703:31)
    at __webpack_require__ (webpack.js:37:33)
    at fn (webpack.js:360:21)
    at eval (_app.tsx:29:91)
    at (:3000/pages-dir-browser)/src/pages/_app.tsx (http://localhost:3000/_next/static/chunks/pages/_app.js:21423:1)
    at options.factory (webpack.js:703:31)
    at __webpack_require__ (webpack.js:37:33)
    at fn (webpack.js:360:21)
    at eval (next-client-pages-loader.js?absolutePagePath=private-next-pages%2F_app&page=%2F_app!:5:16)
    at eval (route-loader.js:238:51)

I'm running into this as well on Solito after upgrading to mmkv v3 and enabling new arch, the error is only on Next.js.

MustafaAlsihati avatar May 14 '25 10:05 MustafaAlsihati

The problem here is that global doesn't exist on web unless it's polyfilled. Some bundlers do this, some dont. A safer way is to use globalThis (which is available regardless of platform).

There are a couple web-platform files that need patching - PlatformChecker and createTextEncoder. You can enhance this a bit to have a server check. I used Tanstack's helper (for reference).

Here's my patch file (for patch-package) - patch, delete .next cache folder, run dev:

diff --git a/node_modules/react-native-mmkv/lib/module/PlatformChecker.js b/node_modules/react-native-mmkv/lib/module/PlatformChecker.js
index d2efd0c..11237fa 100644
--- a/node_modules/react-native-mmkv/lib/module/PlatformChecker.js
+++ b/node_modules/react-native-mmkv/lib/module/PlatformChecker.js
@@ -1,10 +1,14 @@
-"use strict";
+'use strict';
+
+const isServer = typeof window === 'undefined' || 'Deno' in globalThis;
 
 export function isTest() {
-  if (global.process == null) {
-    // In a WebBrowser/Electron the `process` variable does not exist
+  if (isServer) {
+    return (
+      process.env.JEST_WORKER_ID != null || process.env.VITEST_WORKER_ID != null
+    );
+  } else {
     return false;
   }
-  return process.env.JEST_WORKER_ID != null || process.env.VITEST_WORKER_ID != null;
 }
 //# sourceMappingURL=PlatformChecker.js.map
diff --git a/node_modules/react-native-mmkv/lib/module/createTextEncoder.js b/node_modules/react-native-mmkv/lib/module/createTextEncoder.js
index 6d6ae5a..1777a9c 100644
--- a/node_modules/react-native-mmkv/lib/module/createTextEncoder.js
+++ b/node_modules/react-native-mmkv/lib/module/createTextEncoder.js
@@ -1,19 +1,25 @@
-"use strict";
+'use strict';
+
+const isServer = typeof window === 'undefined' || 'Deno' in globalThis;
+
+const noopTextEncoder = {
+  encode: () => {
+    throw new Error('TextEncoder is not supported in this environment!');
+  },
+  encodeInto: () => {
+    throw new Error('TextEncoder is not supported in this environment!');
+  },
+  encoding: 'utf-8',
+};
 
 /* global TextEncoder */
 export function createTextEncoder() {
-  if (global.TextEncoder != null) {
-    return new global.TextEncoder();
+  if (isServer) {
+    return noopTextEncoder;
+  } else if (globalThis.TextEncoder != null) {
+    return new globalThis.TextEncoder();
   } else {
-    return {
-      encode: () => {
-        throw new Error('TextEncoder is not supported in this environment!');
-      },
-      encodeInto: () => {
-        throw new Error('TextEncoder is not supported in this environment!');
-      },
-      encoding: 'utf-8'
-    };
+    return noopTextEncoder;
   }
 }
 //# sourceMappingURL=createTextEncoder.js.map

yulolimum avatar Aug 10 '25 03:08 yulolimum

How can global be null?

I cannot reproduce this.

mrousavy avatar Aug 20 '25 14:08 mrousavy

we worked around this issue by adding the following to our webpack configuration block in next.config.js:

        // This prevents a crash from react-native-mmkv.
        // https://github.com/mrousavy/react-native-mmkv/issues/794
        if (!options.isServer) {
          webpackConfig.plugins.push(
            new webpack.DefinePlugin({
              global: "window",
            }),
          )
        }

wongk avatar Aug 20 '25 14:08 wongk

@mrousavy

From MDN:

In a web browser, any code which the script doesn't specifically start up as a background task has a Window as its global object. This is the vast majority of JavaScript code on the Web.

Scripts running under Node.js have an object called global as their global object.

The globalThis global property allows one to access the global object regardless of the current environment.

Image


Some bundlers will polyfill this - Next (for the browser env) does not by default.

Will a reproducer help? I can open a new issue with a repo.

Thanks!

yulolimum avatar Aug 20 '25 14:08 yulolimum

Will a reproducer help? I can open a new issue with a repo.

Can you just create a PR to fix this issue in MMKV? I don't use web. Maybe we should do something like

const _global = global ?? globalThis ?? window

or whatever the best practice for web is. idk.

mrousavy avatar Aug 20 '25 14:08 mrousavy

Sure thing!

yulolimum avatar Aug 20 '25 14:08 yulolimum