Mastodon hachyterm.io

For $DAYJOB I had to build a new feature for our internal VuePress 2 documentation.

I needed to fetch data from an API that needs an API token. That’s why I wanted to use environment variables to store the token, both locally as well in our CI pipeline.

Surprisingly this was hard to figure out. It didn’t help that I’ve never worked with Vue.js or VuePress. The documentation was of limited help.

For example, I stumbled upon the famous error when trying to use process.env in a Vue component:

process is not defined

I’ll show you how you can use environment variables in VuePress in the following article.

Goal

We want to be able to use a local file called .env (or something similar like .env.local) to store sensitive data.

Example content of the .env file:

GOOGLE_API_TOKEN='abcdefghi12345'

We want to be able to use this token in the JavaScript part of Vue.

Example:

<script>
import fetch from 'cross-fetch'

async function fetchData() {
  const response = await fetch('some-url', {
    method: 'GET',
    headers: {
      // here we need our token 👇
      Authorization: `Token token=`,
    },
  })
  return response.json()
}
</script>
Note about cross-fetch

I've installed this library to be able to use the fetch API in Node.js during VuePress's generate step.

In the generate phase Node.js builds all pages, so we don't have the fetch API (browser-only until Node 18) at our disposal.

Problem

I couldn’t find a guide in the VuePress documentation, the top StackOverflow question seems outdated, and the GitHub issue only got me 90% to the solution.

Solution

There is one library we need to install:

npm i dotenv

dotenv is a popular JavaScript library which allows us to load environment variables from files. Exactly our use case!

Now we need to adjust the configuration for VuePress. You can read more about the Config file in the docs.

Add dotenv to the Vue config file (config.js):

// all other imports, e.g.
// import { registerComponentsPlugin } from '@vuepress/plugin-register-components';
import * as dotenv from 'dotenv'

dotenv.config()

The above code allows us to read our API token from the environment file. But how can we pass the variable to our frontend Vue component?

You cannot do this:

<script>
const TOKEN = process.env.GOGGLE_API_TOKEN
</script>

The Vue component in VuePress can be a client-side component. The browser can’t access process, that’s Node.js-only.

You’ll see this error:

process is not defined

VuePress has a hook to define global constants for the client code.

Add the following to your config object in config.js:

export default defineUserConfig({
  // previous configuration
  // dest: 'public',
  // lang: 'de-DE',
  define: {
    __TOKEN__: process.env.GOOGLE_API_TOKEN,
  },
})

Now you can do the following in your Vue component:

<script>
import fetch from 'cross-fetch'

async function fetchData() {
  const response = await fetch('some-url', {
    method: 'GET',
    headers: {
      // here we can access the global constant 👇
      Authorization: `Token token=${__TOKEN__}`,
    },
  })
  return response.json()
}
</script>

The __TOKEN__ variable will “magically” work.

Summary

Here we have a working solution. Maybe there’s a better way.
I don’t like to use global constants. If you work with the Vue component it’s not clear where the variable comes from.

But that’s at least a working solution.