Skip to content

Commit 9efb7bb

Browse files
Implement .env support in local development
1 parent cb2fd2e commit 9efb7bb

File tree

12 files changed

+594
-114
lines changed

12 files changed

+594
-114
lines changed

packages/wrangler/e2e/dev.test.ts

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,3 +2294,224 @@ This is a random email body.
22942294
`);
22952295
});
22962296
});
2297+
2298+
describe(".env support in local dev", () => {
2299+
const seedFiles = {
2300+
"wrangler.jsonc": JSON.stringify({
2301+
name: workerName,
2302+
main: "src/index.ts",
2303+
compatibility_date: "2025-07-01",
2304+
vars: {
2305+
WRANGLER_ENV_VAR_0: "default-0",
2306+
WRANGLER_ENV_VAR_1: "default-1",
2307+
WRANGLER_ENV_VAR_2: "default-2",
2308+
WRANGLER_ENV_VAR_3: "default-3",
2309+
},
2310+
}),
2311+
"src/index.ts": dedent`
2312+
export default {
2313+
fetch(request, env) {
2314+
return new Response(JSON.stringify(env, null, 2));
2315+
}
2316+
}
2317+
`,
2318+
};
2319+
2320+
it("should load environment variables from .env file", async () => {
2321+
const helper = new WranglerE2ETestHelper();
2322+
await helper.seed(seedFiles);
2323+
await helper.seed({
2324+
".env": dedent`
2325+
WRANGLER_ENV_VAR_1=env-1
2326+
WRANGLER_ENV_VAR_2=env-2
2327+
`,
2328+
});
2329+
2330+
const worker = helper.runLongLived("wrangler dev");
2331+
const { url } = await worker.waitForReady();
2332+
expect(await (await fetch(url)).text()).toMatchInlineSnapshot(`
2333+
"{
2334+
"WRANGLER_ENV_VAR_0": "default-0",
2335+
"WRANGLER_ENV_VAR_1": "env-1",
2336+
"WRANGLER_ENV_VAR_2": "env-2",
2337+
"WRANGLER_ENV_VAR_3": "default-3"
2338+
}"
2339+
`);
2340+
});
2341+
2342+
it("should not load load environment variables from .env files if there is a .dev.vars file", async () => {
2343+
const helper = new WranglerE2ETestHelper();
2344+
await helper.seed(seedFiles);
2345+
await helper.seed({
2346+
".env": dedent`
2347+
WRANGLER_ENV_VAR_1=env-1
2348+
WRANGLER_ENV_VAR_2=env-2
2349+
`,
2350+
});
2351+
await helper.seed({
2352+
".dev.vars": dedent`
2353+
WRANGLER_ENV_VAR_1=dev-vars-1
2354+
WRANGLER_ENV_VAR_2=dev-vars-2
2355+
`,
2356+
});
2357+
2358+
const worker = helper.runLongLived("wrangler dev");
2359+
const { url } = await worker.waitForReady();
2360+
expect(await (await fetch(url)).text()).toMatchInlineSnapshot(`
2361+
"{
2362+
"WRANGLER_ENV_VAR_0": "default-0",
2363+
"WRANGLER_ENV_VAR_1": "dev-vars-1",
2364+
"WRANGLER_ENV_VAR_2": "dev-vars-2",
2365+
"WRANGLER_ENV_VAR_3": "default-3"
2366+
}"
2367+
`);
2368+
});
2369+
2370+
it("should load environment variables from .env.staging if it exists and --env=staging", async () => {
2371+
const helper = new WranglerE2ETestHelper();
2372+
await helper.seed(seedFiles);
2373+
await helper.seed({
2374+
".env.staging": dedent`
2375+
WRANGLER_ENV_VAR_2=staging-2
2376+
WRANGLER_ENV_VAR_3=staging-3
2377+
`,
2378+
});
2379+
2380+
const worker = helper.runLongLived("wrangler dev --env=staging");
2381+
const { url } = await worker.waitForReady();
2382+
expect(await (await fetch(url)).text()).toMatchInlineSnapshot(`
2383+
"{
2384+
"WRANGLER_ENV_VAR_0": "default-0",
2385+
"WRANGLER_ENV_VAR_1": "default-1",
2386+
"WRANGLER_ENV_VAR_2": "staging-2",
2387+
"WRANGLER_ENV_VAR_3": "staging-3"
2388+
}"
2389+
`);
2390+
});
2391+
2392+
it("should prefer to load environment variables from .env.staging over .env, if --env=staging", async () => {
2393+
const helper = new WranglerE2ETestHelper();
2394+
await helper.seed(seedFiles);
2395+
await helper.seed({
2396+
".env": dedent`
2397+
WRANGLER_ENV_VAR_1=env-1
2398+
WRANGLER_ENV_VAR_2=env-2
2399+
`,
2400+
});
2401+
await helper.seed({
2402+
".env.staging": dedent`
2403+
WRANGLER_ENV_VAR_2=staging-2
2404+
WRANGLER_ENV_VAR_3=staging-3
2405+
`,
2406+
});
2407+
2408+
const worker = helper.runLongLived("wrangler dev --env=staging");
2409+
const { url } = await worker.waitForReady();
2410+
expect(await (await fetch(url)).text()).toMatchInlineSnapshot(`
2411+
"{
2412+
"WRANGLER_ENV_VAR_0": "default-0",
2413+
"WRANGLER_ENV_VAR_1": "env-1",
2414+
"WRANGLER_ENV_VAR_2": "staging-2",
2415+
"WRANGLER_ENV_VAR_3": "staging-3"
2416+
}"
2417+
`);
2418+
});
2419+
2420+
it("should load environment variables from .env file if --env=xxx and .env.xxx does not exist", async () => {
2421+
const helper = new WranglerE2ETestHelper();
2422+
await helper.seed(seedFiles);
2423+
await helper.seed({
2424+
".env": dedent`
2425+
WRANGLER_ENV_VAR_1=env-1
2426+
WRANGLER_ENV_VAR_2=env-2
2427+
`,
2428+
});
2429+
await helper.seed({
2430+
".env.staging": dedent`
2431+
WRANGLER_ENV_VAR_2=staging-2
2432+
WRANGLER_ENV_VAR_3=staging-3
2433+
`,
2434+
});
2435+
2436+
const worker = helper.runLongLived("wrangler dev --env=xxx");
2437+
const { url } = await worker.waitForReady();
2438+
expect(await (await fetch(url)).text()).toMatchInlineSnapshot(`
2439+
"{
2440+
"WRANGLER_ENV_VAR_0": "default-0",
2441+
"WRANGLER_ENV_VAR_1": "env-1",
2442+
"WRANGLER_ENV_VAR_2": "env-2",
2443+
"WRANGLER_ENV_VAR_3": "default-3"
2444+
}"
2445+
`);
2446+
});
2447+
2448+
it("should prefer to load environment variables from .env.local over .env", async () => {
2449+
const helper = new WranglerE2ETestHelper();
2450+
await helper.seed(seedFiles);
2451+
await helper.seed({
2452+
".env": dedent`
2453+
WRANGLER_ENV_VAR_1=env-1
2454+
WRANGLER_ENV_VAR_2=env-2
2455+
`,
2456+
});
2457+
await helper.seed({
2458+
".env.local": dedent`
2459+
WRANGLER_ENV_VAR_2=local-2
2460+
WRANGLER_ENV_VAR_3=local-3
2461+
`,
2462+
});
2463+
2464+
const worker = helper.runLongLived("wrangler dev");
2465+
const { url } = await worker.waitForReady();
2466+
expect(await (await fetch(url)).text()).toMatchInlineSnapshot(`
2467+
"{
2468+
"WRANGLER_ENV_VAR_0": "default-0",
2469+
"WRANGLER_ENV_VAR_1": "env-1",
2470+
"WRANGLER_ENV_VAR_2": "local-2",
2471+
"WRANGLER_ENV_VAR_3": "local-3"
2472+
}"
2473+
`);
2474+
});
2475+
2476+
it("should prefer to load environment variables from .env.staging.local over .env.staging, etc", async () => {
2477+
const helper = new WranglerE2ETestHelper();
2478+
await helper.seed(seedFiles);
2479+
await helper.seed({
2480+
".env": dedent`
2481+
WRANGLER_ENV_VAR_1=env-1
2482+
WRANGLER_ENV_VAR_2=env-2
2483+
`,
2484+
});
2485+
await helper.seed({
2486+
".env.local": dedent`
2487+
WRANGLER_ENV_VAR_2=local-2
2488+
WRANGLER_ENV_VAR_3=local-3
2489+
`,
2490+
});
2491+
await helper.seed({
2492+
".env.staging": dedent`
2493+
WRANGLER_ENV_VAR_3=staging-3
2494+
WRANGLER_ENV_VAR_4=staging-4
2495+
`,
2496+
});
2497+
await helper.seed({
2498+
".env.staging.local": dedent`
2499+
WRANGLER_ENV_VAR_4=staging-local-4
2500+
WRANGLER_ENV_VAR_5=staging-local-5
2501+
`,
2502+
});
2503+
2504+
const worker = helper.runLongLived("wrangler dev --env=staging");
2505+
const { url } = await worker.waitForReady();
2506+
expect(await (await fetch(url)).text()).toMatchInlineSnapshot(`
2507+
"{
2508+
"WRANGLER_ENV_VAR_0": "default-0",
2509+
"WRANGLER_ENV_VAR_1": "env-1",
2510+
"WRANGLER_ENV_VAR_2": "local-2",
2511+
"WRANGLER_ENV_VAR_3": "staging-3",
2512+
"WRANGLER_ENV_VAR_4": "staging-local-4",
2513+
"WRANGLER_ENV_VAR_5": "staging-local-5"
2514+
}"
2515+
`);
2516+
});
2517+
});

packages/wrangler/e2e/helpers/wrangler.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,6 @@ export async function runWrangler(
2525
return runCommand(getWranglerCommand(wranglerCommand), { cwd, env, timeout });
2626
}
2727

28-
export function runWranglerLongLived(
29-
wranglerCommand: string,
30-
options: WranglerCommandOptions = {}
31-
) {
32-
return new WranglerLongLivedCommand(wranglerCommand, options);
33-
}
34-
3528
export class WranglerLongLivedCommand extends LongLivedCommand {
3629
constructor(wranglerCommand: string, options: WranglerCommandOptions = {}) {
3730
super(getWranglerCommand(wranglerCommand), getOptions(options));

packages/wrangler/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
"date-fns": "^4.1.0",
117117
"devtools-protocol": "^0.0.1182435",
118118
"dotenv": "^16.3.1",
119+
"dotenv-expand": "^12.0.2",
119120
"execa": "^6.1.0",
120121
"find-up": "^6.3.0",
121122
"get-port": "^7.0.0",

0 commit comments

Comments
 (0)