5

I found this great post to properly manage environment variables in a Nuxt v2.13 app. I simply tried to implement the proposed logic, but I am encountering some problems that I would like to ask you.

I set publicRuntimeConfig and privateRuntimeConfig as follow. I'm using Contentful, so I've to properly set Contentful tokens to be able to make API calls.

export default {
  // Nuxt target - See https://nuxtjs.org/api/configuration-target
  target: 'static',

  // Nuxt rendering mode - See https://nuxtjs.org/api/configuration-mode
  mode: 'universal',

  // Both server and client.
  publicRuntimeConfig: {
    backendApi: process.env.BACKEND_API_URL
    shopUrl: process.env.SHOP_URL
  },

  // Only available on server using same $config (it overrides publicRuntimeConfig)
  privateRuntimeConfig: {
    ctfSpaceId: CTF_SPACE_ID,
    ctfCdaAccessToken: CTF_CDA_ACCESS_TOKEN,
    ctfCpaAccessToken: CTF_CPA_ACCESS_TOKEN,
    ctfEnvironment: CTF_ENVIRONMENT
  },

Above to module export statement I've to define the data from .env, so:

require('dotenv').config()

const {
  CTF_SPACE_ID,
  CTF_CDA_ACCESS_TOKEN,
  CTF_CPA_ACCESS_TOKEN,
  CTF_ENVIRONMENT,
} = process.env

Next, moving in a Nuxt page component (pick pages/index.vue as reference ), remembering that privateRuntimeConfig is available only on server side, I boost asyncData hook with $config:

 async asyncData({ app, $config: { ctfSpaceId, ctfCdaAccessToken } }) {
    const $i18n = app.i18n
    const client = contentful.createClient({
      space: ctfSpaceId,
      accessToken: ctfCdaAccessToken,
    })
   ...
}

Cool, I refresh the browser tab where Nuxt is running, asyncData does its job and private config variables are suitably set.

Next, I browse other app pages, and come back to index and .

Nuxt crashed and $config private variables are undefined.

I don't want to find workarounds to this because we're talking about security and therefore I can only ask if my configuration is correct and what is happening to Nuxt under the hood.

Nuxt.js documentation is explicit:

asyncData is called every time before loading the page component. It will be called server-side once (on the first request to the Nuxt app) and client-side when navigating to further routes.

So the question is how to properly load private config variables on client side.

A fellow mentor friend would say the magic word: Noob.

Wonderman
  • 931
  • 10
  • 21

1 Answers1

7

There is no way to properly load private variables client side. To do so would be to expose all your secrets, and is exactly why privateRuntimeConfig exists now. Before, many people made the mistake of adding their secrets to Nuxt env, exposing them client side.

Unfortunately, if you want to access these APIs at runtime you need to change the way you're doing this.

You either need to statically generate your project, or you need to run an API that handles calling your 3rd party services with the API keys.

See https://nuxtjs.org/guide#static-generated-pre-rendering- for statically generating a project (does not require a server). You'll likely also need to use https://nuxtjs.org/api/configuration-generate#routes for generating dynamic pages (ex. _product.vue)

See https://nuxtjs.org/api/configuration-servermiddleware/ for what is probably the easiest way to get an API running alongside a Nuxt server.

If you're just running a blog or a small shop, I would highly recommend going with static generation. Hosting is much simpler, it's cheaper, and your project is already probably able to be exported as is. You'll just need to find a good host, such as Netlify.

HMilbradt
  • 3,980
  • 16
  • 31
  • You rock man! I take time to implement your solution. This thins out some fog in my head – Wonderman Jul 26 '20 at 20:06
  • 1
    @Wonderman can you share the solution you implemented? Thanks. – Çağlar Duman May 16 '21 at 17:47
  • Hey, can you please explain what you meant about statically generated? Because the .env variables will be injected at build time with nuxt target:'static' so they will be exposed on client side. – ihor.eth Feb 18 '22 at 23:32