nuxt-env
nuxt-env copied to clipboard
Getting undefined
Hello, I'm trying to get this module working but no luck. I have followed the steps stated:
- added dependency via yarn
- added the module and configure it using a key from the env section of nuxt.config.js
- when I use it I get undefined every time.
modules: [
"bootstrap-vue/nuxt",
"cookie-universal-nuxt",
['nuxt-env', {
keys: ['baseUrl']
}]
],
export default {
mounted(){
console.log(this.$env.baseUrl); // undefined
console.log(process.env.baseUrl); // correct url
}
};
I'm getting the same error even when I wrap in this.$nextTick()
How are you injecting your environment variables?
Mine are undefined in spa mode
If this is still occuring can someone use code sandbox to recreate this, so I can debug?
I think @aarcoraci means, in nuxt.config.js
module.exports = {
env: {
baseUrl: 'some thing'
},
...
modules: [
['nuxt-env', {
keys: ['baseUrl']
}]
],
...
}
and with the output of this.$env.baseUrl === undefined
?
i am confused at first, and realize the key means key of the actual process.env
that is accessible in nuxt.config.js file, like:
// BASE_URL=https://example.com npm run dev
// this.$env.BASE_URL === 'https://example.com'
['nuxt-env', {
keys: ['BASE_URL']
}]
Currently this module does not support SPA mode, as for that you can just use the normal env
property and the vars will get baked in at build time.
I'm working on support for this but I'm not quite sure what it, any ideas would be appreciated.
Idea for SPA mode (if possible with current nuxt):
- register a startup hook (as of
nuxt start
or whatever brings up the server to serve the SPA). In this hook: - read your list of desired env vars, get the value from the env vars of the system and paste them to a file (so that the name and value of the env var is hardcoded)
- add into some basic step of the SPA to download and execute the file from 2.
- run a little routine to add every existing env var in the downloaded file to process.$env
There is a related discussion about making runtime env vars supported out of the box: https://github.com/nuxt/nuxt.js/issues/5100.
@samtgarson Maybe you should alter the nuxt server nuxt start
to add a custom header on each response containing serialized env variables.
And on the client side, make a small script to populate app.$env
with the payload shipped in the response header. I'm not sure you can read the headers of the initial response from js, but if you can't, you can use the Set-Cookie
header through document.cookie
.
EDIT: Tested with a serverMiddleware in spa
mode, and it works:
// nuxt.config.js
export default {
mode: 'spa',
// ...
serverMiddleware: [
function(req, res, next) {
// Authorized env variables to be sent to the client
const allowed = ['BACKEND_URL', 'BACKEND_PORT']
// Filter process.env with allowed env variables
const filtered = Object.keys(process.env)
.filter(key => allowed.includes(key))
.reduce((obj, key) => {
obj[key] = process.env[key]
return obj
}, {})
// Set the ENV cookie with JSON encoded variables
res.setHeader('Set-Cookie', [`ENV=${JSON.stringify(filtered)}`])
next()
}
],
// ...
}
Maybe a track to explore...
That is an interesting one—I also recently saw this implementation which uses the head metadata to store the public env...
(unfortunately this repo also includes "shims" for other libraries which I strongly disagree with 😞 )
Not sure which personally I prefer as both are using mechanisms which are not designed for this, but if I had to chose I think I'd chose the head meta route... I always shy away from setting cookies where possible 🍪
Don't have any time right now to work on this but would definitely look at PRs!
OK got your point, I agree but if you exclude the hacky option (meta/cookie), I guess the only "proper" option requires some async stuff:
- Add a route to the
nuxt start
server and make it serves a json representation of the allowed environments variables (defined in the nuxt.config). - Fetch the route from the client very early + JSON.parse the response body + assign the result object to
Vue.prototype.$env
+ probably need to return a promise somewhere to deal with async.
If this kind of option sounds ok for you, I'll try to make a PR.
Yeah, that is an alternative but of course its an extra HTTP request so has performance/network implications, plus seems more fragile to your point about dealing with async-ness.
I'd be happy with either of the meta/cookie options right now 👍
Really glad I found this conversation. Hard to believe Nuxt still has this limitation. Big problem for projects that use CI/CD build servers.
Useful thread, thanks. Are there plans to support a 12 factor style approach for env vars in SPA mode from the nuxt core team or would it need to come through this project? Cheers.
There is a very easy trick that works with SPA mode:
app.html
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
</head>
<body {{ BODY_ATTRS }}>
<script>window.ENV = {{ ENV_INJECT }}</script>
{{ APP }}
</body>
</html>
add this to your nuxt.config.js:
const { map, fromPairs, defaultTo } = require('ramda')
{
hooks: {
'vue-renderer:spa:templateParams': meta => {
const injectVariablesWithDefaults = [
['INITIAL_SETUP', false],
]
const processEnvDefault = ([key, defaultValue]) => [key, defaultTo(defaultValue, process.env[key])]
const injectVariables = fromPairs(map(processEnvDefault, injectVariablesWithDefaults))
meta.ENV_INJECT = JSON.stringify(injectVariables)
}
},
}
This picks the desired environment variables from process.env
and injects them to the global window object.
This is designed for spa mode *only, since the window object will be not available during SSR.
Surely there is a way to also append to the other meta variables like APP
. But I wanted to be future proof, in case they change the order of hooks or overwrite the variable again somehow.
See here: https://github.com/nuxt/nuxt.js/blob/b17f331fe51bb85776213988eb13559342955fcd/packages/vue-renderer/src/renderers/spa.js
Also: you can write this without ramda. I just found it to be easier for me.
Best, Martin :)
I have a similar issue, but in the vuex store getter. App throws this: [Vue warn]: Error in render: "TypeError: Cannot read property '$env' of undefined". My application is working in universal mode.
Part of nuxt.config.js
configuration is:
modules: [
['nuxt-env', {
keys: [
'TEST'
]
}]
]
Then in the store I try to debug a value of the TEST
env:
someStoreGetter() {
console.log(this.$env.TEST);
},
Do you have any ideas, why the issue occured?
@coderua that is a different issue, please don't hijack the thread—the error is saying that this
is undefined.
This suggests to me your store is not being setup like a normal store. Could you take another look as to why that might be, it's not really within the scope of this library to fix but if you're still stuck please open another ticket with an expanded snippet of your store and I might be able to help.