feat(core): support .env.local (#5491)

* feat(core): support .env.local

* fix(core): fix e2e tests for env variables

Co-authored-by: Jason Jean <jasonjean1993@gmail.com>
This commit is contained in:
Naoyoshi Aikawa 2021-05-05 05:30:03 +09:00 committed by GitHub
parent cf2f42d3ba
commit c9e79ab84e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 14 deletions

View File

@ -41,20 +41,22 @@ set "NODE_ENV=development" && nx build myapp
By default, Nx will load any environment variables you place in the following files:
1. `workspaceRoot/apps/my-app/.local.env`
2. `workspaceRoot/apps/my-app/.env`
3. `workspaceRoot/.local.env`
4. `workspaceRoot/.env`
2. `workspaceRoot/apps/my-app/.env.local`
3. `workspaceRoot/apps/my-app/.env`
4. `workspaceRoot/.local.env`
5. `workspaceRoot/.env.local`
6. `workspaceRoot/.env`
Order is important. Nx will move through the above list, ignoring files it can't find, and loading environment variables into the current process for the ones it can find. If it finds a variable that has already been loaded into the process, it will ignore it. It does this for two reasons:
1. Developers can't accidentally overwrite important system level variables (like `NODE_ENV`)
2. Allows developers to create `.local.env` files for their local environment and override any project defaults set in `.env`
2. Allows developers to create `.env.local` or `.local.env` files for their local environment and override any project defaults set in `.env`
For example:
1. `workspaceRoot/apps/my-app/.local.env` contains `AUTH_URL=http://localhost/auth`
1. `workspaceRoot/apps/my-app/.env.local` contains `AUTH_URL=http://localhost/auth`
2. `workspaceRoot/apps/my-app/.env` contains `AUTH_URL=https://prod-url.com/auth`
3. Nx will first load the variables from `apps/my-app/.local.env` into the process. When it tries to load the variables from `apps/my-app/.env`, it will notice that `AUTH_URL` already exists, so it will ignore it.
3. Nx will first load the variables from `apps/my-app/.env.local` into the process. When it tries to load the variables from `apps/my-app/.env`, it will notice that `AUTH_URL` already exists, so it will ignore it.
We recommend nesting your **app** specific `env` files in `apps/your-app`, and creating workspace/root level `env` files for workspace-specific settings (like the [Nx Cloud token](/{{framework}}/core-concepts/computation-caching#nx-cloud-and-distributed-computation-memoization)).

View File

@ -128,7 +128,7 @@ describe('Web Components Applications', () => {
function sealed(target: any) {
return target;
}
@sealed
class Foo {
@enumerable(false) bar() {}
@ -174,20 +174,40 @@ describe('CLI - Environment Variables', () => {
`.env`,
'NX_WS_BASE=ws-base\nNX_SHARED_ENV=shared-in-workspace-base'
);
updateFile(
`.env.local`,
'NX_WS_ENV_LOCAL=ws-env-local\nNX_SHARED_ENV=shared-in-workspace-env-local'
);
updateFile(
`.local.env`,
'NX_WS_LOCAL=ws-local\nNX_SHARED_ENV=shared-in-workspace-local'
'NX_WS_LOCAL_ENV=ws-local-env\nNX_SHARED_ENV=shared-in-workspace-local-env'
);
updateFile(
`apps/${appName}/.env`,
'NX_APP_BASE=app-base\nNX_SHARED_ENV=shared-in-app-base'
);
updateFile(
`apps/${appName}/.env.local`,
'NX_APP_ENV_LOCAL=app-env-local\nNX_SHARED_ENV=shared-in-app-env-local'
);
updateFile(
`apps/${appName}/.local.env`,
'NX_APP_LOCAL=app-local\nNX_SHARED_ENV=shared-in-app-local'
'NX_APP_LOCAL_ENV=app-local-env\nNX_SHARED_ENV=shared-in-app-local-env'
);
const main = `apps/${appName}/src/main.ts`;
const newCode = `const envVars = [process.env.NODE_ENV, process.env.NX_BUILD, process.env.NX_API, process.env.NX_WS_BASE, process.env.NX_WS_LOCAL, process.env.NX_APP_BASE, process.env.NX_APP_LOCAL, process.env.NX_SHARED_ENV];`;
const newCode = `
const envVars = [process.env.NODE_ENV, process.env.NX_BUILD, process.env.NX_API, process.env.NX_WS_BASE, process.env.NX_WS_ENV_LOCAL, process.env.NX_WS_LOCAL_ENV, process.env.NX_APP_BASE, process.env.NX_APP_ENV_LOCAL, process.env.NX_APP_LOCAL_ENV, process.env.NX_SHARED_ENV];
const nodeEnv = process.env.NODE_ENV;
const nxBuild = process.env.NX_BUILD;
const nxApi = process.env.NX_API;
const nxWsBase = process.env.NX_WS_BASE;
const nxWsEnvLocal = process.env.NX_WS_ENV_LOCAL;
const nxWsLocalEnv = process.env.NX_WS_LOCAL_ENV;
const nxAppBase = process.env.NX_APP_BASE;
const nxAppEnvLocal = process.env.NX_APP_ENV_LOCAL;
const nxAppLocalEnv = process.env.NX_APP_LOCAL_ENV;
const nxSharedEnv = process.env.NX_SHARED_ENV;
`;
runCLI(`generate @nrwl/web:app ${appName} --no-interactive`);
@ -201,12 +221,16 @@ describe('CLI - Environment Variables', () => {
`apps/${appName2}/.env`,
'NX_APP_BASE=app2-base\nNX_SHARED_ENV=shared2-in-app-base'
);
updateFile(
`apps/${appName2}/.env.local`,
'NX_APP_ENV_LOCAL=app2-env-local\nNX_SHARED_ENV=shared2-in-app-env-local'
);
updateFile(
`apps/${appName2}/.local.env`,
'NX_APP_LOCAL=app2-local\nNX_SHARED_ENV=shared2-in-app-local'
'NX_APP_LOCAL_ENV=app2-local-env\nNX_SHARED_ENV=shared2-in-app-local-env'
);
const main2 = `apps/${appName2}/src/main.ts`;
const newCode2 = `const envVars = [process.env.NODE_ENV, process.env.NX_BUILD, process.env.NX_API, process.env.NX_WS_BASE, process.env.NX_WS_LOCAL, process.env.NX_APP_BASE, process.env.NX_APP_LOCAL, process.env.NX_SHARED_ENV];`;
const newCode2 = `const envVars = [process.env.NODE_ENV, process.env.NX_BUILD, process.env.NX_API, process.env.NX_WS_BASE, process.env.NX_WS_ENV_LOCAL, process.env.NX_WS_LOCAL_ENV, process.env.NX_APP_BASE, process.env.NX_APP_ENV_LOCAL, process.env.NX_APP_LOCAL_ENV, process.env.NX_SHARED_ENV];`;
runCLI(`generate @nrwl/web:app ${appName2} --no-interactive`);
@ -223,10 +247,10 @@ describe('CLI - Environment Variables', () => {
},
});
expect(readFile(`dist/apps/${appName}/main.js`)).toContain(
'const envVars = ["test", "52", "QA", "ws-base", "ws-local", "app-base", "app-local", "shared-in-app-local"];'
'const envVars = ["test", "52", "QA", "ws-base", "ws-env-local", "ws-local-env", "app-base", "app-env-local", "app-local-env", "shared-in-app-env-local"];'
);
expect(readFile(`dist/apps/${appName2}/main.js`)).toContain(
'const envVars = ["test", "52", "QA", "ws-base", "ws-local", "app2-base", "app2-local", "shared2-in-app-local"];'
'const envVars = ["test", "52", "QA", "ws-base", "ws-env-local", "ws-local-env", "app2-base", "app2-env-local", "app2-local-env", "shared2-in-app-env-local"];'
);
});
});

View File

@ -350,8 +350,10 @@ export class TaskOrchestrator {
const envsFromFiles = {
...parseEnv('.env'),
...parseEnv('.local.env'),
...parseEnv('.env.local'),
...parseEnv(`${task.projectRoot}/.env`),
...parseEnv(`${task.projectRoot}/.local.env`),
...parseEnv(`${task.projectRoot}/.env.local`),
};
const env: NodeJS.ProcessEnv = {