remix: Uncaught ReferenceError: process is not defined | Using env variables with Vite
Reproduction
I checked the console and the only error I have is this:
Uncaught ReferenceError: process is not defined
at node_modules/util/util.js (@remix-run_node.js?v=2071f225:764:5)
at __require (chunk-WXXH56N5.js?v=2071f225:12:50)
at node_modules/stream-slice/index.js (@remix-run_node.js?v=2071f225:5672:16)
at __require (chunk-WXXH56N5.js?v=2071f225:12:50)
at node_modules/@remix-run/node/dist/upload/fileUploadHandler.js (@remix-run_node.js?v=2071f225:5869:23)
at __require (chunk-WXXH56N5.js?v=2071f225:12:50)
at node_modules/@remix-run/node/dist/index.js (@remix-run_node.js?v=2071f225:6057:29)
at __require (chunk-WXXH56N5.js?v=2071f225:12:50)
at @remix-run_node.js?v=2071f225:6159:16
vite.config.ts:
import { unstable_vitePlugin as remix } from "@remix-run/dev";
import { ConfigEnv, defineConfig, loadEnv } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default ({ mode }: ConfigEnv) => {
// Here we add env vars from .env files to process.env.
// Note the last arg is a blank string so that all env vars
// are loaded, not just those starting with "VITE_"
Object.assign(process.env, loadEnv(mode, process.cwd(), ""));
return defineConfig({
plugins: [
remix({
ignoredRouteFiles: ["**/.*"],
serverModuleFormat: "cjs",
}),
tsconfigPaths(),
],
});
};
How I’m accessing the env variables is as per the documentation: https://remix.run/docs/en/main/guides/envvars
root.tsx:
export async function loader({ request }: LoaderFunctionArgs) {
const isAnonymous = await isAnonymousSession(request);
if (isAnonymous) {
return response.ok(
{
env: getBrowserEnv(),
email: null,
userTier: null,
},
{ authSession: null }
);
}
const authSession = await requireAuthSession(request);
const { userId, email } = authSession;
try {
const userTier = await getUserTier(userId);
return response.ok(
{
env: getBrowserEnv(),
email,
userTier,
},
{ authSession }
);
} catch (cause) {
throw response.error(cause, { authSession });
}
}
export default function App() {
const { env } = useLoaderData<typeof loader>();
return (
<html className="h-full" lang="en">
<head>
<Meta />
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,maximum-scale=1.0"
/>
<Links />
</head>
<body className="h-full">
<Content />
<ScrollRestoration />
<script
dangerouslySetInnerHTML={{
__html: `window.env = ${JSON.stringify(env)}`,
}}
/>
<Scripts />
<LiveReload />
</body>
</html>
);
}
env.ts:
import { Currency } from "@prisma/client";
import { z } from "zod";
import { OneMixError } from "~/utils/error";
import { isBrowser } from "./misc";
declare global {
interface Window {
env: {
SUPABASE_URL: string;
SUPABASE_ANON_PUBLIC: string;
DEFAULT_CURRENCY: Currency;
};
}
}
declare global {
namespace NodeJS {
interface ProcessEnv {
SUPABASE_URL: string;
SUPABASE_SERVICE_ROLE: string;
SERVER_URL: string;
SUPABASE_ANON_PUBLIC: string;
SESSION_SECRET: string;
STRIPE_SECRET_KEY: string;
STRIPE_ENDPOINT_SECRET: string;
DEFAULT_CURRENCY: Currency;
}
}
}
type EnvOptions = {
isSecret?: boolean;
isRequired?: boolean;
};
function getEnv(
name: string,
{ isRequired, isSecret }: EnvOptions = { isSecret: true, isRequired: true }
) {
if (isBrowser && isSecret) return "";
const source = (isBrowser ? window.env : process.env) ?? {};
const value = source[name as keyof typeof source] || "";
if (!value && isRequired) {
throw new OneMixError({
message: `Env "${name}" is not set`,
});
}
return value;
}
/**
* Server env
*/
export const SERVER_URL = getEnv("SERVER_URL");
export const SUPABASE_SERVICE_ROLE = getEnv("SUPABASE_SERVICE_ROLE");
export const SESSION_SECRET = getEnv("SESSION_SECRET");
export const STRIPE_SECRET_KEY = getEnv("STRIPE_SECRET_KEY");
export const STRIPE_ENDPOINT_SECRET = getEnv("STRIPE_ENDPOINT_SECRET");
/**
* Shared envs
*/
export const NODE_ENV = getEnv("NODE_ENV", {
isSecret: false,
isRequired: false,
});
export const SUPABASE_URL = getEnv("SUPABASE_URL", { isSecret: false });
export const SUPABASE_ANON_PUBLIC = getEnv("SUPABASE_ANON_PUBLIC", {
isSecret: false,
});
export const DEFAULT_CURRENCY = z
.nativeEnum(Currency)
.parse(getEnv("DEFAULT_CURRENCY", { isSecret: false }));
export function getBrowserEnv() {
return {
SUPABASE_URL,
SUPABASE_ANON_PUBLIC,
DEFAULT_CURRENCY,
};
}
System Info
System:
OS: Windows 11 10.0.22631
CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Memory: 1.00 GB / 7.86 GB
Binaries:
Node: 20.9.0 - D:\Node\node.EXE
npm: 10.2.4 - ~\AppData\Roaming\npm\npm.CMD
pnpm: 8.11.0 - ~\AppData\Local\pnpm\pnpm.EXE
Browsers:
Edge: Chromium (120.0.2210.121)
Internet Explorer: 11.0.22621.1
npmPackages:
@remix-run/dev: ^2.4.0 => 2.4.1
@remix-run/node: ^2.4.0 => 2.4.1
@remix-run/react: ^2.4.0 => 2.4.1
@remix-run/serve: ^2.4.0 => 2.4.1
vite: ^5.0.0 => 5.0.10
Used Package Manager
npm
Expected Behavior
There should be a process is not defined error.
Actual Behavior
There is a process is not defined error in the browser console. As a side effect of this, the onClick function for any of my buttons is not working.
About this issue
- Original URL
- State: closed
- Created 6 months ago
- Comments: 19 (6 by maintainers)
Literally having the same exact issue as well. Issue is happening for me with this line:
import { json, redirect } from "@remix-run/nodeFor anyone coming across this problem, I had a similar issue where I had a common
utils.tsfile with some server + client utils. I separated them to autils.tsandutils.server.tssuch that the latter was the only one that was importing:This seemed to have fixed the issue. Alternatively, I could have used the
vite-env-onlypackage to have one file and ensure the individual functions are nominated as client or server only. Two files made more sense for my project.@toddheslin I had the same issue as @fabregas4.
The error occurs if you import either
jsonorredirectand don’t actually use them in your loader/action. I hit this in development when I implemented a redirect, but then backed it out without actually removing the import as well.@Pape98 @toddheslin
I’m a newbie so I might be off-track, but I have struggled with what seems a very similar issue over the last 24 hours. I finally resolved it (I think), at least for me.
I was trying to
import { json } from '@remix-run/node'as well.I was getting that same
processvar error in browser console.I tried moving the import to a utils.server.js and then importing that from my route. This seemed to clear the browser console error, but now became a server console error “Internal server error: Server-only module referenced by client”.
What I eventually discovered is you have to USE the
jsonmethod within your loader or action. If you do this, the error should clear, regardless of whether you import the package directly or via a .server file.I was tripped up because I was actually importing both
jsonandredirect, but only using one or the other in the action. The error only cleared when both were being used, or the one that wasn’t being used, was removed from the import.Hope that makes sense and hope it helps.
Basically my conclusion is that if you import methods without using them, vite/remix assumes they are referenced by the client, whereas if you use them within loader/action, then it understands they are only referenced by the server. Perhaps someone from the team can comment?
The error message comes from JS itself, not Remix. If Remix tries to handle the error, it would prevent users from setting up client-safe polyfills for the same imports so not much we can do without a substantially more complex approach.