Skip to content

Commit 1923f4b

Browse files
Handle custom envDir in Vite config (remix-run#12969)
1 parent 033bc34 commit 1923f4b

File tree

4 files changed

+110
-58
lines changed

4 files changed

+110
-58
lines changed

.changeset/afraid-buses-pay.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-router/dev": patch
3+
---
4+
5+
Handle custom `envDir` in Vite config

integration/helpers/vite.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,14 @@ export const reactRouterConfig = ({
5858
`;
5959
};
6060

61+
type ViteConfigArgs = {
62+
port: number;
63+
fsAllow?: string[];
64+
envDir?: string;
65+
};
66+
6167
export const viteConfig = {
62-
server: async (args: { port: number; fsAllow?: string[] }) => {
68+
server: async (args: ViteConfigArgs) => {
6369
let { port, fsAllow } = args;
6470
let hmrPort = await getPort();
6571
let text = dedent`
@@ -72,14 +78,15 @@ export const viteConfig = {
7278
`;
7379
return text;
7480
},
75-
basic: async (args: { port: number; fsAllow?: string[] }) => {
81+
basic: async (args: ViteConfigArgs) => {
7682
return dedent`
7783
import { reactRouter } from "@react-router/dev/vite";
7884
import { envOnlyMacros } from "vite-env-only";
7985
import tsconfigPaths from "vite-tsconfig-paths";
8086
8187
export default {
8288
${await viteConfig.server(args)}
89+
envDir: ${args.envDir ? `"${args.envDir}"` : "undefined"},
8390
plugins: [
8491
reactRouter(),
8592
envOnlyMacros(),

integration/vite-dotenv-test.ts

Lines changed: 95 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -8,73 +8,113 @@ import {
88
viteConfig,
99
} from "./helpers/vite.js";
1010

11-
let files = {
12-
".env": `
13-
ENV_VAR_FROM_DOTENV_FILE=Content from .env file
14-
`,
15-
"app/routes/dotenv.tsx": String.raw`
16-
import { useState, useEffect } from "react";
17-
import { useLoaderData } from "react-router";
18-
19-
export const loader = () => {
20-
return {
21-
loaderContent: process.env.ENV_VAR_FROM_DOTENV_FILE,
22-
}
23-
}
11+
let getFiles = async ({ envDir, port }: { envDir?: string; port: number }) => {
12+
let envPath = `${envDir ? `${envDir}/` : ""}.env`;
2413

25-
export default function DotenvRoute() {
26-
const { loaderContent } = useLoaderData();
14+
return {
15+
"vite.config.js": await viteConfig.basic({ port, envDir }),
16+
"server.mjs": EXPRESS_SERVER({ port }),
17+
[envPath]: `
18+
ENV_VAR_FROM_DOTENV_FILE=Content from ${envPath} file
19+
`,
20+
"app/routes/dotenv.tsx": String.raw`
21+
import { useState, useEffect } from "react";
22+
import { useLoaderData } from "react-router";
2723
28-
const [clientContent, setClientContent] = useState('');
29-
useEffect(() => {
30-
try {
31-
setClientContent("process.env.ENV_VAR_FROM_DOTENV_FILE shouldn't be available on the client, found: " + process.env.ENV_VAR_FROM_DOTENV_FILE);
32-
} catch (err) {
33-
setClientContent("process.env.ENV_VAR_FROM_DOTENV_FILE not available on the client, which is a good thing");
24+
export const loader = () => {
25+
return {
26+
loaderContent: process.env.ENV_VAR_FROM_DOTENV_FILE,
3427
}
35-
}, []);
36-
37-
return <>
38-
<div data-dotenv-route-loader-content>{loaderContent}</div>
39-
<div data-dotenv-route-client-content>{clientContent}</div>
40-
</>
41-
}
42-
`,
28+
}
29+
30+
export default function DotenvRoute() {
31+
const { loaderContent } = useLoaderData();
32+
33+
const [clientContent, setClientContent] = useState('');
34+
useEffect(() => {
35+
try {
36+
setClientContent("process.env.ENV_VAR_FROM_DOTENV_FILE shouldn't be available on the client, found: " + process.env.ENV_VAR_FROM_DOTENV_FILE);
37+
} catch (err) {
38+
setClientContent("process.env.ENV_VAR_FROM_DOTENV_FILE not available on the client, which is a good thing");
39+
}
40+
}, []);
41+
42+
return <>
43+
<div data-dotenv-route-loader-content>{loaderContent}</div>
44+
<div data-dotenv-route-client-content>{clientContent}</div>
45+
</>
46+
}
47+
`,
48+
};
4349
};
4450

45-
test.describe(async () => {
46-
let port: number;
47-
let cwd: string;
48-
let stop: () => void;
49-
50-
test.beforeAll(async () => {
51-
port = await getPort();
52-
cwd = await createProject({
53-
"vite.config.js": await viteConfig.basic({ port }),
54-
"server.mjs": EXPRESS_SERVER({ port }),
55-
...files,
51+
test.describe("Vite .env", () => {
52+
test.describe("defaults", async () => {
53+
let port: number;
54+
let cwd: string;
55+
let stop: () => void;
56+
57+
test.beforeAll(async () => {
58+
port = await getPort();
59+
cwd = await createProject(await getFiles({ port }));
60+
stop = await customDev({ cwd, port });
61+
});
62+
test.afterAll(() => stop());
63+
64+
test("express", async ({ page }) => {
65+
let pageErrors: unknown[] = [];
66+
page.on("pageerror", (error) => pageErrors.push(error));
67+
68+
await page.goto(`http://localhost:${port}/dotenv`, {
69+
waitUntil: "networkidle",
70+
});
71+
expect(pageErrors).toEqual([]);
72+
73+
let loaderContent = page.locator("[data-dotenv-route-loader-content]");
74+
await expect(loaderContent).toHaveText("Content from .env file");
75+
76+
let clientContent = page.locator("[data-dotenv-route-client-content]");
77+
await expect(clientContent).toHaveText(
78+
"process.env.ENV_VAR_FROM_DOTENV_FILE not available on the client, which is a good thing"
79+
);
80+
81+
expect(pageErrors).toEqual([]);
5682
});
57-
stop = await customDev({ cwd, port });
5883
});
59-
test.afterAll(() => stop());
6084

61-
test("Vite / Load context / express", async ({ page }) => {
62-
let pageErrors: unknown[] = [];
63-
page.on("pageerror", (error) => pageErrors.push(error));
85+
test.describe("custom env dir", async () => {
86+
let port: number;
87+
let cwd: string;
88+
let stop: () => void;
6489

65-
await page.goto(`http://localhost:${port}/dotenv`, {
66-
waitUntil: "networkidle",
90+
test.beforeAll(async () => {
91+
const envDir = "custom-env-dir";
92+
port = await getPort();
93+
cwd = await createProject(await getFiles({ envDir, port }));
94+
stop = await customDev({ cwd, port });
6795
});
68-
expect(pageErrors).toEqual([]);
96+
test.afterAll(() => stop());
97+
98+
test("express", async ({ page }) => {
99+
let pageErrors: unknown[] = [];
100+
page.on("pageerror", (error) => pageErrors.push(error));
69101

70-
let loaderContent = page.locator("[data-dotenv-route-loader-content]");
71-
await expect(loaderContent).toHaveText("Content from .env file");
102+
await page.goto(`http://localhost:${port}/dotenv`, {
103+
waitUntil: "networkidle",
104+
});
105+
expect(pageErrors).toEqual([]);
72106

73-
let clientContent = page.locator("[data-dotenv-route-client-content]");
74-
await expect(clientContent).toHaveText(
75-
"process.env.ENV_VAR_FROM_DOTENV_FILE not available on the client, which is a good thing"
76-
);
107+
let loaderContent = page.locator("[data-dotenv-route-loader-content]");
108+
await expect(loaderContent).toHaveText(
109+
"Content from custom-env-dir/.env file"
110+
);
77111

78-
expect(pageErrors).toEqual([]);
112+
let clientContent = page.locator("[data-dotenv-route-client-content]");
113+
await expect(clientContent).toHaveText(
114+
"process.env.ENV_VAR_FROM_DOTENV_FILE not available on the client, which is a good thing"
115+
);
116+
117+
expect(pageErrors).toEqual([]);
118+
});
79119
});
80120
});

packages/react-router-dev/vite/plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
955955
process.env,
956956
vite.loadEnv(
957957
viteConfigEnv.mode,
958-
ctx.rootDirectory,
958+
viteUserConfig.envDir ?? ctx.rootDirectory,
959959
// We override default prefix of "VITE_" with a blank string since
960960
// we're targeting the server, so we want to load all environment
961961
// variables, not just those explicitly marked for the client

0 commit comments

Comments
 (0)