Env variables are read by the client and server at the same time
Answered
AM posted this in #help-forum
AMOP
Hello i do have 2 env variables:
and i can see that in my client component
really not sure what is happening and how to handle it
NEXT_PUBLIC_API_BASE_URL=baseUrlApi
NEXTAUTH_SECRET=next_secretand i can see that in my client component
NEXTAUTH_SECRET is logged for some reason, however it comes as null and env validations are throwing error, what could be the reason for that. Is it possible because in my client component i'm using service that internally is using getSession like this:export const updatePasswordApi = async (data: UpdatePasswordRequestType) => {
const session = await getSession();
const response = await fetch(
`${PUBLIC_API_BASE_URL}/${API_ENDPOINTS.UPDATE_PASSWORD}`,
{
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${session?.user.accessToken}`
}
}
);
if (!response.ok) {
throw new Error(API_ERRORS.UPDATE_PASSWORD);
}
return response.json();
};really not sure what is happening and how to handle it
Answered by fuma
that's simple - when you import this from a client component, your whole file will be loaded by client too
22 Replies
NEXTAUTH_SECRET shouldn't be passed to the client side otherwise people can easily steal the next auth secret of your app. This is unsafe.Next.js won't include environment variables without
NEXT_PUBLIC_ as a prefix. That's why NEXT_PUBLIC_API_BASE_URL can be accessed on client side while NEXTAUTH_SECRET can'tAMOP
i'm not passing it actually more likely i do have this:
and in my service:
actually not passing it, i dont understand why is failing is not used anywhere
'use client';
const SignUp = () => {
...code...
const onSubmit = async (values: RegisterDataType) => {
const res = await registerApi(values);
console.log('res', res);
};
...code...
}and in my service:
export const registerApi = async (data: RegisterRequestType) => {
const response = await fetch(
`${PUBLIC_API_BASE_URL}/${API_ENDPOINTS.REGISTER}`,
{
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}
);
if (!response.ok) {
throw new Error(API_ERRORS.REGISTER);
}
return response.json();
};actually not passing it, i dont understand why is failing is not used anywhere
NEXTAUTH_SECRET secret thoin the scenario above does this
PUBLIC_API_BASE_URL needs to be prefixed as public, i do have standalone service that is used in client component?interesting thing is that i can see errors start coming when i import my
registerApi in my SignUp client componentand my
registerApi is located hereindex.ts of auth folderany idea what possible could fail how this chain is happening
importing api from index.ts is start consuming
NEXTAUTH_SECRET for some reasonAMOP
ok further more i think i have isolated even more the problem
i do have this import in my services:
and then in
import { PUBLIC_API_BASE_URL } from '@/app/lib;lib/index.ts:export * from './env';
export * from './utils';and then in
env.ts i do have this:import { nonNull } from './utils';
export const PUBLIC_API_BASE_URL = nonNull<string>(
process.env.NEXT_PUBLIC_API_BASE_URL,
`env of "NEXT_PUBLIC_API_BASE_URL" is not defined. Did you forget a definition in the ".env.local"?`
);
export const NEXTAUTH_SECRET = nonNull<string>(
process.env.NEXTAUTH_SECRET,
`env of "NEXTAUTH_SECRET" is not defined. Did you forget a definition in the ".env.local"?`
);somehow when i import the public api base url to my service next auth is coming too
is it somehow because of the barrel imports hmm
that's simple - when you import this from a client component, your whole file will be loaded by client too
Answer
Then
nonNull throw an error, causing the problem you mentionedcreate another file for it, like
env-server for exampleAMOP
ok but from the file i'm loading just
why is messing with the
import { PUBLIC_API_BASE_URL } from '@/app/libwhy is messing with the
NEXTAUTH_SECRETis true like intelisense gives me to import
NEXTAUTH_SECRET so the whole file is loaded trueBecause it is same as:
It is executed when script is loaded
nonNull(process.env.NEXT_PUBLIC)
nonNull(process.env.SECRET)It is executed when script is loaded
you can throw errors at top-level
AMOP
axx i see
and for the components that are client side i will need to have
where
process.env.NEXT_PUBLIC_API_BASE_URL along with process.env.API_BASE_URLwhere
process.env.NEXT_PUBLIC_API_BASE_URL goes in env-client.ts and other one goes into env-server.ts and based on the component ( in most cases server but right now submitting form ) they will be imported from env-server.tsYou can store shared envs in
env-shared IMOAMOP
but isn't this like the scenario right now where i do have
env.ts and contains both server and client and when client env is imported into client component server ones are triggered as well