nuxt / bridge

🌉 Experience Nuxt 3 features on existing Nuxt 2 projects
MIT License
273 stars 29 forks source link

Correct way to read environment variables from a .js file using Webpack #855

Closed Jesus82 closed 1 year ago

Jesus82 commented 1 year ago

Environment

Nuxi 3.6.1

Reproduction

I have set the .env variables in nuxt.config.ts (using webpack)

runtimeConfig: {
    public: {
      MY_VAR: process.env.MY_VAR,
   }
}

Then, in .vue files, I can access them via $config.public.MY_VAR On the server folder I can access them with process.env.MY_VAR

Describe the bug

I have several .js files with constants that I import to my .vue components. There I cannot access them neither this.$config / $config, nor via process.env. With $config I get an error, while with process.env I get null.

Example constant.js

export const mySlugCollection = [
  {
    slug: 'mySlug',
    links: 'a-cool-slug',
  },
  {
    slug: 'myOtherSlug',
    links: process.env.MY_VAR,
  },

myComponent.vue

<template>
    <nuxt-link v-for="slug in mySlugCollection" :to="slug">
</template>

<script>
import { mySlugCollection } from './constant'
data() {
    return {
      mySlugCollection,
    }
}

What would be the recommended way to to this?

Additional context

No response

Logs

No response

wattanx commented 1 year ago

@Jesus82

If you want to separate them into different files, how about making them composables? (useRuntimeConfig is also only available for Vue components or Composables.)

export const useSlugCollection = () => {
  const config = useRuntimeConfig();
  const mySlugCollection = [
    {
      slug: 'mySlug',
      links: 'a-cool-slug',
    },
    {
      slug: 'myOtherSlug',
      links: config.MY_VAR,
    },
  ]
  return { mySlugCollection }
}

This is not a Bug, so it is preferable to ask in Discussions or Discord.

Jesus82 commented 1 year ago

@wattanx I can see an easy way of using composables with a constants.js file. However, I have other use case where I use a service that makes API calls to an endpoint, and then this service is called by a Vuex hook. Here I cannot find the way to make it work with composables in order to be able to use environment variables. See SO question here and minimal reproduction here.

wattanx commented 1 year ago

@Jesus82 In nuxtServerInit, you can use $config to get the value from the second argument, context. (composables are intended for use within Vue Component or composables.)

export const actions = {
  async nuxtServerInit(vuexContext, { $config }) {
    console.log($config.API_URL)
    vuexContext.dispatch('loadApiData');
  },
};
Jesus82 commented 1 year ago

@wattanx thanks a lot for your quick response. I see I could make it work, but this would also break a bit the service structure, where I set the base api call in one place, and then I implement several methods based on that and in other different api calls.

export const useApi = (config) => {
    const apiClient = axios.create({
        baseURL: config.API_URL,
    })

    const anotherApiClient = axios.create({
        baseURL: config.ANOTHER_API_URL,
    })

   const fetchApiData = () => {
        return apiClient.get()
    }
   const fetchAnotherApiData = () => {
       return anotherApiClient.get()
    }
}

I'm trying to pass instead the nuxt context from Vuex to the composable (or instead to a plain services.js) file, something like

loadApiData({ commit }, { $config }) {
  const myApiData = useApi.fetchApiData($config)
  commit('SET_API_DATA', myApiData)
}
}

And then being able to access config there, but I get a config is not defined error when doing so. Is there any way to do that in order to be able to keep current architecture? (See updated reproduction)

wattanx commented 1 year ago

@Jesus82 I think the method of passing config as an argument looks good. How about like this? https://stackblitz.com/edit/github-dwx287-xvszrr