Unable to access environment variables with square bracket notation
-
I have a plugin that I use to get environment variables with a prefix, that is easy for me to search and replace with a bash script in a prod docker container.
This does no longer work after quasar 2.0. See the problem in action below
console.log(process.env['VUE_APP_FOO']) // returns 'bar' from env console.log(process.env.VUE_APP_FOO) // returns 'bar' from env const something = 'VUE_APP_FOO' console.log(process.env[something]) // This will return undefined. How can I fix this?
This is the script I’m using, but Configuration.value will always return undefined because of the issue above.
import Vue from 'vue'; type ConfigTypes = 'backendHost' | 'domain'; export default class Configuration { static get CONFIG() { return { backendHost: '$VUE_APP_BACKEND', domain: '$VUE_APP_DOMAIN', }; } static value(name: ConfigTypes) { if (!(name in this.CONFIG)) { console.log(`Configuration: There is no key named "${name}"`); return; } const value: string = this.CONFIG[name]; if (!value) { console.log(`Configuration: Value for "${name}" is not defined`); return; } if (value.startsWith('$VUE_APP_')) { // value was not replaced, it seems we are in development. // Remove $ and get current value from process.env const envName = value.substr(1); const envValue = process.env[envName]; if (envValue) { return envValue; } else { console.log(`Configuration: Environment variable "${envName}" is not defined`); } } else { // value was already replaced, it seems we are in production. return value; } } } Vue.prototype.$conf = Configuration;
-
@jvik I think it may have to do with this PR: https://github.com/quasarframework/quasar/pull/8084
Maybe try in quasar.conf.js under build:
build: { env: Object.entries(process.env).reduce((acc, [key,val]) => { if(key.startsWith('VUE_APP')) { acc[key] = val } return acc }, {}) }
I typed this directly into the forum, so it’s not tested.
-
@beets Hmmm. Doesn’t seem like it made any difference unfortunately.
-
@jvik Maybe you need
if(key.startsWith('VUE_APP') || key.startsWith('$VUE_APP')) {
instead?Can you try putting:
const tmp = Object.entries(process.env).reduce((acc, [key,val]) => { if(key.startsWith('VUE_APP') || key.startsWith('$VUE_APP')) { acc[key] = val } return acc }, {}) console.log('ENV VARS:', tmp)
at the top of quasar.conf.js and see what the output on the command line is during a quasar dev or quasar build
-
@beets This is the output from the console.log
ENV VARS: {} <prototype>: Object { … } configuration.ts:11
So just an empty object
-
@jvik hm, and if you just put
console.log(process.env)
at the top of quasar.conf.js, do you see any variables starting with
VUE_APP
? -
@beets Forget my last comment. I added the snippet to the wrong file.
When adding it to my quasar.conf.js it outputs this
ENV VARS: { VUE_APP_BACKEND: 'localhost:3020' }
, so that part seems to work.Still, with the snippet from your first comment, I am not able to make it work.
-
Shouldn’t the following:
foo: "bar"
under build in quasar.conf.js make me able toconsole.log(process.env.foo)
in my quasar plugin and get “bar”?It does just output undefined as well.
-
@jvik It should be
build: { env: { foo: "bar" } }
but yes, that should make it available in your vue files / plugins. Let me know if that isn’t working.
-
@beets Okay, yeah. That works as expected, but I’m still not able to dynamically get my environment variables.
Even if I define like below inside quasar.conf.js if I
console.log(process.env)
somewhere else in the project it will still be an empty object.build: { env: { foo: "bar" } }
Edit: I put it all inside a child property. THat seems to solve it:
build: { vueRouterMode: 'history', // available values: 'hash', 'history', env: { props: Object.entries(process.env).reduce((acc, [key, val]) => { if (key.startsWith('VUE_APP')) { acc[key] = val; } return acc; }, {}), }, }
-
@jvik If your edited solution works, then great. It’s was a security improvement by quasar in a recent version so ENV vars aren’t bundled without being explicitly defined, which is a good thing, but would cause using the square brackets to have some issues.
You could also stringify the object into json if you’re still having problems:
build: { vueRouterMode: 'history', // available values: 'hash', 'history', env: { props: JSON.stringify(Object.entries(process.env).reduce((acc, [key, val]) => { if (key.startsWith('VUE_APP')) { acc[key] = val; } return acc; }, {})), }, }
And in a boot file :
export default async ({ Vue }) => { Vue.prototype.$env = JSON.parse(process.env.props) }
And then access it as
this.$env[some_var]