Currently, the httpEndpoint in the clientConfigs is baked into the apollo-module.js template at build time. This causes issues in deployment pipelines that rely on immutable builds and promoting compiled code from staging to production (e.g. Heroku), i.e.
鈥⒙燗pp is first built in staging environment, with httpEndpoint defined by staging env var being hardcoded into resulting .nuxt/apollo-module.js.
鈥⒙燙ompiled code is promoted from staging to production.
鈥⒙燩roduction environment is now using staging httpEndpoint.
See this issue for a more in-depth explanation.
No API/config changes would be required, just that the apollo-module.js template would be updated to instead evaluate the apollo options in nuxt.config.js at runtime.
I will try to put together a PR when I have some time 馃憤
EDIT: After some deeper investigation, it seems like this isn't possible with Nuxt in its current state. Will have to revisit this if/when Nuxt allows runtime template plugin compilation.
I'd like to point out that there is a way to modify httpEndpoint (and other clientConfig variables) at runtime, although it is a little janky. Instead of putting your config directly in nuxt.config.js, put your clientConfig in a separate file like this...
// apollo-default-client-config.js
export default (context) => {
return {
httpEndpoint: process.env.API_PATH || '<default-endpoint-path>'
}
}
Then configure nuxt.config.js as follows...
// nuxt.config.js
{
apollo: {
clientConfigs: {
default: '~~/apollo-default-client-config.js'
}
}
}
In this example I'm assuming that apollo-default-client-config.js is in the same directory as nuxt.config.js but you can change that.
Now you can configure your httpEndpoint using an API_PATH environment variable, and it will update at runtime. Alternatively, you could probably pass data into apollo-default-client-config.js through the context (although I haven't tried that).
See more on the separate config file setup in the README and in the local state example.
@evanrlong Thanks for the heads up, although I just tested this out and in order to access the environment variable client-side, it needs to be passed to the context via the env property in nuxt.config.js, and the value are baked-in on build.
The result is that the Apollo client will always fall back to the default endpoint when trying to make API calls in the browser.
@slavanossar Oh my mistake, I forgot the project I'm working on uses a (somewhat janky) custom solution for injecting environment variables at runtime. I won't share that, but you should be able to achieve the same effect with the nuxt-env module.
We're having exactly this issue although we're using nuxt-env already. When I console.log(app.$env) I get undefined. Does nuxt-apollo not play nicely with nuxt-env?
Example:
export default ({ app }) => {
console.log(app.$env) // returns undefined, why?
return {
wsEndpoint: app.$env.WEBSOCKETS_URI || 'ws://localhost:4000/graphql',
// etc.
cache: new InMemoryCache({ fragmentMatcher }), // this is the reason why we cannot put the configuration into `nuxt.config.js`
}
}
Also, we would love to change the configuration in nuxt.config.js based on process.env. This would work, because the nuxt.config.js is not built and therefore baked into .nuxt/. However, if we do that, then we cannot setup IntrospectionFragmentMatcher anymore. :disappointed:
@roschaefer, try app.store.$env. This is how we use it:
export default function (app) {
const { store: { $env: { GRAPHQL_HTTP_URL } } } = app
return {
httpEndpoint: GRAPHQL_HTTP_URL
}
}
And don't forget to register your variable in nuxt.config.js:
[
'nuxt-env',
{
keys: [
'GRAPHQL_HTTP_URL'
]
}
]
@antmorozov oops, sorry for not posting the solution we found here: https://github.com/Human-Connection/Human-Connection/commit/2e19cf6592d546ffa1ce31ed40da80a5f554a9b4
After some debugging, I discovered that req is present on the server and nuxtState is present on the client and that both have env respectively with whitelisted environment variables set at runtime.
So, it's also possible to do
export default ({ req, nuxtState }) => {
const { env } = req || nuxtState
// env has your runtime env vars
}
Basically the same solution as yours.
Any update about this issue? I just ran into the same situation
@antmorozov oops, sorry for not posting the solution we found here: Human-Connection/Human-Connection@2e19cf6
After some debugging, I discovered that
reqis present on the server andnuxtStateis present on the client and that both haveenvrespectively with whitelisted environment variables set at runtime.So, it's also possible to do
export default ({ req, nuxtState }) => { const { env } = req || nuxtState // env has your runtime env vars }Basically the same solution as yours.
Where does this code go? Can't seem to get it working
@koalado Nuxt recently released 2.13 which introduced runtimeConfig support. There's also a blog post that describes the change in detail here.
I haven't had a chance to try it out yet, but from what I understand you can just define runtime variables in nuxt.config.js and then access them through the context with $config.
EDIT:
I just tried it out, here's a working example
// apollo.config.js
export default function({ $config }) {
return {
httpEndpoint: $config.baseUrl
}
}
// nuxt.config.js
export default {
apollo: {
clientConfigs: {
default: '~/apollo.config.js'
}
},
publicRuntimeConfig: {
baseUrl: process.env.BASE_URL
}
}
@slavanossar you sure? it's not working here... $config inside the apollo.config.js file is always undefined. Or am I missing something?
What version of Nuxt do you have installed in node_modules? $config will only be available on 2.13+. You can upgrade Nuxt to the latest version:
# yarn
$ yarn upgrade nuxt
# npm
$ npm update nuxt
I have removed the node_modules folder and npm install everything and it works now. Not sure what was wrong.
Mistake on my side, sorry :)
Can be closed again.
Most helpful comment
@koalado Nuxt recently released 2.13 which introduced
runtimeConfigsupport. There's also a blog post that describes the change in detail here.I haven't had a chance to try it out yet, but from what I understand you can just define runtime variables in
nuxt.config.jsand then access them through the context with$config.EDIT:
I just tried it out, here's a working example