You are browsing Nuxt 2 docs. Go to Nuxt 3 docs, or learn more about Nuxt 2 Long Term Support.
In our frontend applications, we often use APIs and third-party integrations which require us to use configuration data which is usually provided by environment variables. These variables should not be exposed to the frontend as the browser environment is accessible by all visitors.
It's time to migrate from @nuxtjs/dotenv module to use our new runtime config which has been released as of Nuxt v2.13.
In our frontend applications, we often use APIs and third-party integrations which require us to use configuration data which is usually provided by environment variables. These variables should not be exposed to the frontend as the browser environment is accessible by all visitors. Instead, we can store sensitive information, like keys and secrets, in password-protected CI tools or deployment pipelines. However, when we are developing applications locally we might not have access to deployment pipelines and therefore need somewhere to store these environment variables.
It is very easy to think that your secret keys are safe by placing them somewhere other than your source code such as a .env
file, which makes it very easy to expose your secret keys to client-side bundles. Adding your .env
file to .gitignore
means this file is not pushed to your version control and therefore not available for people to see which is important if your repo is public. However, the .env file is not encrypted, and therefore placing secrets in environment variables doesn't really provide us with an increase in security and really it just keeps sensitive data out of plain sight. A .env
option can easily mislead developers to expose secret keys to client-side bundles so always make sure this file is added to your .gitignore.
Isomorphic applications, otherwise known as universal applications, need to share code between both the server and the client. Babel is used to compile our modern ES6 JavaScript code down to ES5 JavaScript so that it can work across all platforms. Node.js which is an asynchronous event-driven JavaScript runtime that can be used in computers and servers outside of a browser environment, uses the module system.
Using modules in Node.js is done using require, e.g. require('lodash'). However, browser support for modules is still incomplete and therefore we need bundling tools such as webpack to transpile these modules into code that the browsers can read. Webpack basically makes client-side development more "Node-like" with the same module system semantics. This means that a require statement or an ES6 import statement will resolve the same way. And as our applications are not only JavaScript but also HTML, CSS and images we can require these using webpack's loaders.
At runtime, Node.js automatically loads environment variables into process.env
so that they are available to use in your application. The reference to the environment variable is replaced with the correct value. For example, if you had an API_SECRET
key with the value of 'my-secret'
then in your application where you had used process.env.API_SECRET
this would be replaced with the value of my-secret.
Values are read during build time and persisted in the webpack bundle. Therefore if we change our API_SECRET
we will need to rebuild our application so that it can read the new value.
With Nuxt 2.13+ we have runtime config and built-in dotenv support providing better security and faster development! Two new options are added to your nuxt.config.js
file which will allow passing runtime configuration which is then accessible using $config
from the context. Despite the env
option, runtime config is added to the Nuxt payload so there is no need to rebuild in order to update the runtime configuration when working in development or with Server-side rendering or single-page applications. Although for static sites you will still need to regenerate your site to see these changes.
export default {
publicRuntimeConfig: {},
privateRuntimeConfig: {}
}
publicRuntimeConfig
should hold all env variables that are public as these will be exposed on the frontend. This could include a reference to your public URL for example.
privateRuntimeConfig
should hold all env variables that are private and that should not be exposed on the frontend. This could include a reference to your API secret tokens for example.
$config
in server mode is { ...public, ...private } but for client mode only { ...public }If you have the @nuxtjs/dotenv
module installed then you can remove this module by uninstalling it and removing it from the modules section of your nuxt.config file. You can then migrate to the Nuxt runtime config by adding the new properties to your nuxt.config.js file. And then you can add your variables from your .env
files into your public and private runtime config properties so that Nuxt has access to these variables at runtime.
If your .env
file looks something like this:
BASE_URL=https://v2.nuxt.com
API_SECRET=1234
Then migrating it to the new runtime config would look something like:
export default {
publicRuntimeConfig: {
baseURL: process.env.BASE_URL
},
privateRuntimeConfig: {
apiSecret: process.env.API_SECRET
}
}
This can be simplified even further by using a default value instead of having to maintain the value in both the runtime config and the .env
file when using non-sensitive values.
export default {
publicRuntimeConfig: {
baseURL: process.env.BASE_URL || 'https://v2.nuxt.com'
}
}
Also this can be a better replacement for .env.example
and the default values can point to staging keys/configs.
export default {
publicRuntimeConfig: {
baseURL: process.env.NODE_ENV === 'production' ? 'https://v2.nuxt.com' : 'https://dev-v2.nuxt.com'
}
}
If you have your env variables stored in your nuxt.config then you can migrate these to use the new runtime configs by adding them to your nuxt.config file.
If your env variables in your nuxt.config look like this:
export default {
env: {
BASE_URL: 'https://v2.nuxt.com',
API_SECRET: '1234'
}
}
Then migrating it to the new runtime config would look something like:
export default {
publicRuntimeConfig: {
baseURL: 'https://v2.nuxt.com'
},
privateRuntimeConfig: {
apiSecret: process.env.API_SECRET
}
}
You can still use the env property and it is still useful for env variables that are required at build time rather than runtime such as NODE_ENV=staging or VERSION=1.2.3. However for runtime env variables the runtime config is preferred as using the env property can be as dangerous as using the dotenv module when used incorrectly.
Once you have stored your values in the public or private runtime config in your nuxt.config
file you can then access these values anywhere by using the context in your pages, store, components and plugins by using this.$config
or context.$config
instead.
<script>
asyncData ({ $config: { baseURL } }) {
const posts = await fetch(`${baseURL}/posts`)
.then(res => res.json())
}
</script>
And inside your templates you can access it directly using {{ $config.* }}
<template>
<p>Our Url is: {{ $config.baseURL}}</p>
</template>
If you are already using the env variable in your script tags such as in async data
async asyncData ({ env }) {
then you can just replace env for $config when passing into the context. Here we also pass in the key from the config that we want to access. In this case baseURL.
async asyncData ({ $config: { baseURL } }) {
Then instead of using env.apiUrl
const posts = await fetch(`${env.baseURL}/posts`)
you can use baseURL direct in your code as we have already passed this in into the config option above and therefore we don't have to reference $config in our fetch.
const posts = await fetch(`${baseURL}/posts`)
If you have code that is using the env variables you can migrate to using the $config option. For example if in your code you had
<p>{{process.env.baseURL}}</p>
You can change this by using $config instead
<p>{{$config.baseURL}}</p>
Expand for run time config happens only if there is already a key.
API_SECRET=1234
export default {
privateRuntimeConfig: {
API_SECRET: ''
}
}
Interpolation allows nesting env vars.
BASE_URL=/api
PUBLIC_URL=https://v2.nuxt.com
export default {
privateRuntimeConfig: {
baseURL: '${PUBLIC_URL}${BASE_URL}'
}
}
.env
unless is gitignored
env
option