From d619460b14c09982d588085ec4dafd673a3cad68 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Wed, 5 Oct 2022 15:19:46 +0800 Subject: [PATCH] fix: env variables override (#10113) --- packages/vite/src/node/__tests__/env.spec.ts | 53 ++++++++++++++++ packages/vite/src/node/__tests__/env/.env | 5 ++ .../src/node/__tests__/env/.env.development | 4 ++ .../src/node/__tests__/env/.env.production | 1 + packages/vite/src/node/env.ts | 61 ++++++++++--------- 5 files changed, 95 insertions(+), 29 deletions(-) create mode 100644 packages/vite/src/node/__tests__/env.spec.ts create mode 100644 packages/vite/src/node/__tests__/env/.env create mode 100644 packages/vite/src/node/__tests__/env/.env.development create mode 100644 packages/vite/src/node/__tests__/env/.env.production diff --git a/packages/vite/src/node/__tests__/env.spec.ts b/packages/vite/src/node/__tests__/env.spec.ts new file mode 100644 index 00000000000000..4e2a88f95b1665 --- /dev/null +++ b/packages/vite/src/node/__tests__/env.spec.ts @@ -0,0 +1,53 @@ +import { join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { describe, expect, test } from 'vitest' +import { loadEnv } from '../env' + +const __dirname = fileURLToPath(new URL('.', import.meta.url)) + +describe('loadEnv', () => { + test('basic', () => { + expect(loadEnv('development', join(__dirname, './env'))) + .toMatchInlineSnapshot(` + { + "VITE_APP_BASE_ROUTE": "/", + "VITE_APP_BASE_URL": "/", + "VITE_ENV1": "ENV1", + "VITE_ENV2": "ENV2", + "VITE_ENV3": "ENV3", + } + `) + }) + + test('specific prefix', () => { + expect(loadEnv('development', join(__dirname, './env'), 'VVITE')) + .toMatchInlineSnapshot(` + { + "VVITE_A": "A", + "VVITE_B": "B", + } + `) + }) + + test('override', () => { + expect(loadEnv('production', join(__dirname, './env'))) + .toMatchInlineSnapshot(` + { + "VITE_APP_BASE_ROUTE": "/app/", + "VITE_APP_BASE_URL": "/app/", + "VITE_USER_NODE_ENV": "production", + } + `) + }) + + test('VITE_USER_NODE_ENV', () => { + loadEnv('development', join(__dirname, './env')) + expect(process.env.VITE_USER_NODE_ENV).toEqual('production') + }) + + test('Already exists VITE_USER_NODE_ENV', () => { + process.env.VITE_USER_NODE_ENV = 'test' + loadEnv('development', join(__dirname, './env')) + expect(process.env.VITE_USER_NODE_ENV).toEqual('test') + }) +}) diff --git a/packages/vite/src/node/__tests__/env/.env b/packages/vite/src/node/__tests__/env/.env new file mode 100644 index 00000000000000..7a34658dc46559 --- /dev/null +++ b/packages/vite/src/node/__tests__/env/.env @@ -0,0 +1,5 @@ +VITE_APP_BASE_ROUTE=/ +VITE_APP_BASE_URL=$VITE_APP_BASE_ROUTE + +VVITE_A=A +VVITE_B=B diff --git a/packages/vite/src/node/__tests__/env/.env.development b/packages/vite/src/node/__tests__/env/.env.development new file mode 100644 index 00000000000000..f961c7335f1352 --- /dev/null +++ b/packages/vite/src/node/__tests__/env/.env.development @@ -0,0 +1,4 @@ +NODE_ENV=production +VITE_ENV1=ENV1 +VITE_ENV2=ENV2 +VITE_ENV3=ENV3 diff --git a/packages/vite/src/node/__tests__/env/.env.production b/packages/vite/src/node/__tests__/env/.env.production new file mode 100644 index 00000000000000..108c69a7ae9588 --- /dev/null +++ b/packages/vite/src/node/__tests__/env/.env.production @@ -0,0 +1 @@ +VITE_APP_BASE_ROUTE=/app/ diff --git a/packages/vite/src/node/env.ts b/packages/vite/src/node/env.ts index 0472f6fc829d49..a69be1ed233043 100644 --- a/packages/vite/src/node/env.ts +++ b/packages/vite/src/node/env.ts @@ -18,10 +18,10 @@ export function loadEnv( prefixes = arraify(prefixes) const env: Record = {} const envFiles = [ - /** mode local file */ `.env.${mode}.local`, - /** mode file */ `.env.${mode}`, + /** default file */ `.env`, /** local file */ `.env.local`, - /** default file */ `.env` + /** mode file */ `.env.${mode}`, + /** mode local file */ `.env.${mode}.local` ] // check if there are actual env variables starting with VITE_* @@ -35,35 +35,38 @@ export function loadEnv( } } - for (const file of envFiles) { - const path = lookupFile(envDir, [file], { pathOnly: true, rootDir: envDir }) - if (path) { - const parsed = dotenv.parse(fs.readFileSync(path), { - debug: process.env.DEBUG?.includes('vite:dotenv') || undefined + const parsed = Object.fromEntries( + envFiles.flatMap((file) => { + const path = lookupFile(envDir, [file], { + pathOnly: true, + rootDir: envDir }) + if (!path) return [] + return Object.entries( + dotenv.parse(fs.readFileSync(path), { + debug: process.env.DEBUG?.includes('vite:dotenv') + }) + ) + }) + ) - // let environment variables use each other - dotenvExpand({ - parsed, - // prevent process.env mutation - ignoreProcessEnv: true - } as any) + // let environment variables use each other + dotenvExpand({ + parsed, + // prevent process.env mutation + ignoreProcessEnv: true + } as any) - // only keys that start with prefix are exposed to client - for (const [key, value] of Object.entries(parsed)) { - if ( - prefixes.some((prefix) => key.startsWith(prefix)) && - env[key] === undefined - ) { - env[key] = value - } else if ( - key === 'NODE_ENV' && - process.env.VITE_USER_NODE_ENV === undefined - ) { - // NODE_ENV override in .env file - process.env.VITE_USER_NODE_ENV = value - } - } + // only keys that start with prefix are exposed to client + for (const [key, value] of Object.entries(parsed)) { + if (prefixes.some((prefix) => key.startsWith(prefix))) { + env[key] = value + } else if ( + key === 'NODE_ENV' && + process.env.VITE_USER_NODE_ENV === undefined + ) { + // NODE_ENV override in .env file + process.env.VITE_USER_NODE_ENV = value } } return env