T
TanStack6mo ago
sensitive-blue

Server and client environment variables are being loaded from different .env files.

Hello, I'm working on tanstack/start app in monorepo. I also configured /src/ directory to better organize the files. The issue is that server environment variables (from process.env) are being loaded from web/src/.env, while the client variables (from import.meta.env) are being loaded from web/.env. I found that I can set vite.envDir in app.config.ts. I can technically use this to solve my issue, but the .env file would have to live in /web/src. This is not ideal. Instead I'd like the .env file to live in /web. But I couldn't find any way to set path for server envs. Is there way to set which file the server envs are loaded from? Or possibly, is there any other solution to my issue?
2 Replies
sensitive-blue
sensitive-blueOP6mo ago
The whole file structure looks like this:
.
├── apps
│ └── web
│ ├── app.config.ts
│ ├── components.json
│ ├── package.json
│ ├── src
│ │ ├── api
│ │ ├── app
│ │ ├── components
│ │ ├── styles
│ │ ├── ui
│ │ ├── utils
| │ └── .env // Server env is loaded from this file.
│ ├── tsconfig.json
| └── .env // Client env is loaded from this file.
├── bun.lock
├── package.json
├── packages
│ └── db
└── turbo.json
.
├── apps
│ └── web
│ ├── app.config.ts
│ ├── components.json
│ ├── package.json
│ ├── src
│ │ ├── api
│ │ ├── app
│ │ ├── components
│ │ ├── styles
│ │ ├── ui
│ │ ├── utils
| │ └── .env // Server env is loaded from this file.
│ ├── tsconfig.json
| └── .env // Client env is loaded from this file.
├── bun.lock
├── package.json
├── packages
│ └── db
└── turbo.json
My app config:
// apps/web/app.config.ts
import { defineConfig } from "@tanstack/react-start/config";
import tsConfigPaths from "vite-tsconfig-paths";
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import tailwindcss from "@tailwindcss/vite";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

export default defineConfig({
tsr: {
appDirectory: resolve(__dirname, "./src/app"),
},
server: {
rootDir: resolve(__dirname, "./src"),
preset: "vercel",
},
vite: {
cacheDir: resolve(__dirname, "../../node_modules/.vite/packages/router"),
envPrefix: "PUBLIC_",
// envDir: __dirname, // This is not needed, because default value is the same.
plugins: [tsConfigPaths({ projects: ["./tsconfig.json"] }), tailwindcss()],
},
});
// apps/web/app.config.ts
import { defineConfig } from "@tanstack/react-start/config";
import tsConfigPaths from "vite-tsconfig-paths";
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import tailwindcss from "@tailwindcss/vite";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

export default defineConfig({
tsr: {
appDirectory: resolve(__dirname, "./src/app"),
},
server: {
rootDir: resolve(__dirname, "./src"),
preset: "vercel",
},
vite: {
cacheDir: resolve(__dirname, "../../node_modules/.vite/packages/router"),
envPrefix: "PUBLIC_",
// envDir: __dirname, // This is not needed, because default value is the same.
plugins: [tsConfigPaths({ projects: ["./tsconfig.json"] }), tailwindcss()],
},
});
My tsconfig:
// apps/web/tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"moduleResolution": "Bundler",
"module": "ESNext",
"target": "ES2022",
"skipLibCheck": true,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"~/*": ["./src/*"]
}
}
}
// apps/web/tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"moduleResolution": "Bundler",
"module": "ESNext",
"target": "ES2022",
"skipLibCheck": true,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"~/*": ["./src/*"]
}
}
}
absent-sapphire
absent-sapphire5mo ago
Did you find a solution? In my case import.meta.env is picked from .env.local but process.env is picked from .env

Did you find this page helpful?