nuxt-env icon indicating copy to clipboard operation
nuxt-env copied to clipboard

Getting undefined

Open aarcoraci opened this issue 6 years ago • 17 comments

Hello, I'm trying to get this module working but no luck. I have followed the steps stated:

  1. added dependency via yarn
  2. added the module and configure it using a key from the env section of nuxt.config.js
  3. 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   
 }
};

aarcoraci avatar Aug 02 '18 10:08 aarcoraci

I'm getting the same error even when I wrap in this.$nextTick()

ezynda3 avatar Aug 22 '18 05:08 ezynda3

How are you injecting your environment variables?

samtgarson avatar Sep 18 '18 12:09 samtgarson

Mine are undefined in spa mode

saratitan avatar Sep 21 '18 12:09 saratitan

If this is still occuring can someone use code sandbox to recreate this, so I can debug?

samtgarson avatar Oct 29 '18 07:10 samtgarson

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']
}]

aalenliang avatar Dec 25 '18 07:12 aalenliang

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.

samtgarson avatar Feb 14 '19 10:02 samtgarson

Idea for SPA mode (if possible with current nuxt):

  1. register a startup hook (as of nuxt start or whatever brings up the server to serve the SPA). In this hook:
  2. 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)
  3. add into some basic step of the SPA to download and execute the file from 2.
  4. run a little routine to add every existing env var in the downloaded file to process.$env

rmeissn avatar Mar 22 '19 12:03 rmeissn

There is a related discussion about making runtime env vars supported out of the box: https://github.com/nuxt/nuxt.js/issues/5100.

simplesmiler avatar Jul 25 '19 20:07 simplesmiler

@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...

MarlBurroW avatar Sep 23 '19 15:09 MarlBurroW

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!

samtgarson avatar Sep 23 '19 16:09 samtgarson

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.

MarlBurroW avatar Sep 24 '19 09:09 MarlBurroW

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 👍

samtgarson avatar Sep 24 '19 16:09 samtgarson

Really glad I found this conversation. Hard to believe Nuxt still has this limitation. Big problem for projects that use CI/CD build servers.

itsrachelfish avatar Oct 26 '19 22:10 itsrachelfish

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.

marcpaskell avatar Dec 03 '19 08:12 marcpaskell

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 :)

MartinMuzatko avatar Feb 18 '20 14:02 MartinMuzatko

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 avatar Apr 22 '20 14:04 coderua

@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.

samtgarson avatar Apr 22 '20 16:04 samtgarson