The env variables loaded from .env file cannot be used inside quasar.config file
app-vite v2 / app-webpack v4 added automatic .env file loading feature. Before that, the developers were encouraged to manually load env variables using dotenv at the top of quasar.config file, allowing process.env.* to be used anywhere inside the config file. However, with Quasar’s new built-in env handling, env variables are only injected into the app code (src/*), not quasar.config.*.
Due to this, cases like the following will not work out of the box:
// quasar.config.js
import { defineConfig } from '#q-app/wrappers'
export default defineConfig({
build: {
analyze: process.env.ANALYZE === 'true'
},
devServer: {
proxy: {
'/api': {
target: process.env.API_URL,
changeOrigin: true
}
}
}
})
The user will have to use dotenv at the top of the file as before, rendering the new feature useless for them.
Additional Case
Anyone using Docker, CI/CD, or any other environment where the env variables are provided externally, rather than in a .env file, will have to specify the variables in quasar.config file > build > env like FOO: process.env.FOO to use them in the app code. This is another case where the new feature is meaningless due to the requirement of specifying the variables manually.
To make matters worse, since the variables are not available inside the config file, user's manual mapping will result in all variables being undefined. This will cause the values from the env file to get overridden with undefined values. So, the user will have to manually load the env file using dotenv anyway, making the new feature useless for them. Example:
// quasar.config.js
export default defineConfig({
build: {
env: {
// This will work fine when in Docker, CI/CD, etc.
// But, it will be undefined when running locally.
// Since build > env overrides the values from .env file, the .env file will be useless.
// So, the user will have to use dotenv to load the env file as before.
FOO: process.env.FOO
}
}
})
The Chicken and Egg Problem
Quasar checks quasar.config file > build > envFolder/envFiles/envFilter for deciding on what/how to load the env files. So, to be able to use the env variables inside the config file, Quasar must process the config file first. But, to be able to process the config file, Quasar must load the env files first. This creates a chicken and egg problem. So, it's not straightforward to add this feature.
So, it can only be achieved by not respecting envFolder/envFiles/envFilter during the config file processing. This could be confusing for users which use those options. So, the limitations must be documented clearly. The env variables will be loaded according to the default load order, e.g. .env, .env.local, etc.
Proposed Solutions
- Add a note to the migration guide: The migration guide should mention that the env variables are not available inside the config file and that users will have to use dotenv at the top of the file as before.
- Add a note to the documentation: The documentation should mention that the env variables are not available inside the config file and that users will have to use dotenv at the top of the file as before.
-
Add an option to preload the env variables: Add an option like
preloadEnvto opt-in to load the env variables before processing the config file. This will allow users to use the env variables inside the config file without having to use dotenv at the top of the file. The limitations of this feature must be documented clearly.
- If this happens without a flag, anyone using dotenv or some other mechanism may face unexpected behavior.
- It would be a good idea to make this the new "recommended default" by scaffolding the option set to true in newly created projects and update the docs accordingly.
-
Future behavior: In the future, this "preloading" behavior can be made the default behavior while making
envFolder/envFiles/envFilteroptions as advanced and with the necessary warnings.
I just spent some time chasing the problem described as "Additional Case". I have a .env file locally and use Cloudflare pages to build and host the production version of the app. I also think that this is not such a rare use case.
Before I used require("dotenv").config(); on top of the config file and passed them via build: { env: { "KEY": "Value" }}.
Following the migration guide I removed the dotenv call and the manual passing of the env vars.
After I realize that broke the CI build, I added the env config option back, only to realize that broke the dev build again.
Now I'm back using dotenv.
I think this explains the issue I'm experiencing too. None of my envs are loading when the dev server boots up, until I get the quasar dev server to reload at least once, then the envs load in correctly. Just saving quasar.config.js with no changes is enough to trigger the reload / it to open as expected.
I too just encountered this problem while trying to setup Sentry: I am using variables defined in .env files but they are not defined when I try to use their values to initialize the Sentry Vite plugin 😩
I'll load the .env files manually, but it's clearly not very great :-\