Using environment variables allows us to to store configuration values outside of the source files. During the build, the reference to the environment variable will be replaced with the values specified. The configuration data is the part of the project that can vary between test and production. Storing the configuration values in one place it makes it easy to update the values outside of the source code. As dotenv points out this is based on The Twelve-Factor methodology of storing configuration data separate from the code. I will show how I added environment variables to Docusaurus.
Custom Fields
Using the docusaurus.config.js file we can create custom fields that we can use in our source code files. The custom fields in the source code then point back to the configuration file. We can extend that by using environment variables to store the values outside the configuration file. The Docusaurus config file is the only method of accessing the Node.js environment. Even if you decide not to use environment variables you should still consider using the custom fields in your source code so you can manage the values in one place. For instance, if you implemented a commenting system in Docusaurus, instead of going to the source files to change something such as the theme you can manage that change from the configuration file. It is giving you the same functionality that other built-in variables in the configuration file give you such as a central place to change the Google Analytics ID or the website title.
Dotenv
We will be using the module Dotenv to load the .env file into process.env.
Installing
To install dotenv:
npm install dotenv --save
.env file
Then we need to create a .env file at the root of our site.
# Comment
GISCUS_PROJECTNAMECOMMENTS = "ds-blog-comments"
GISCUS_REPO_ID = "R2D2_kOIM5g"
GISCUS_CATEGORY = "Announcements"
GISCUS_CATEGORY_ID = "DIC_kwDM3a6s4"
GISCUS_MAPPING = "title"
Most recommendations are, if you are using source control such as git then do not track the .env file. If this is the route you are taking make sure to put .env in your .gitignore. There are solutions like dotenv-vault for syncing and securing files.
Configure
You need to import and configure dotenv by putting this in the docusaurus.config.js file near the top:
require('dotenv').config()
Testing
One of the ways you can test that it is working is by putting this in the docusaurus.config.js file under the require statement.
console.log(process.env)
This will print out all the environment variables to the command prompt you are running docusaurus with. You can also specify one variable to print out such as:
console.log(process.env.GISCUS_REPO_ID)
Options
There are lots of options in the documentation. The two most common that I have used are the debug and path. One time I needed the debug to see that my path was not correct so it was failing to load the env file.
debug:
require('dotenv').config({debug: true})
path:
require('dotenv').config({path: './.devenv/.env'})
combined path and debug:
require('dotenv').config({path: './.devenv/.env', debug: true})
Referencing it from Docusaurus
To reference one of the environment variables in your configuration file prefix the variable with "process.env". For instance process.env.GISCUS_REPO_ID
Here is an example docusaurus config file that has custom fields that are being used in a source code file for the comment system implementation. In this sample file there is a mix of explicit values and using environment variables.
const config = {
title:
...
customFields: {
Giscus_theme: 'light',
Giscus_organizationName: 'thedaxshepherd',
Giscus_projectNameComments: process.env.GISCUS_PROJECTNAMECOMMENTS,
Giscus_repoId: process.env.GISCUS_REPO_ID,
Giscus_category: process.env.GISCUS_CATEGORY,
...
},
...
}
Then in the source code files, we reference the custom fields since the environment variables are not directly accessible outside the docusaurus configuration file. To use the custom fields we need to add two lines to our file to make them available.
...
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; //needed for siteConfig
export default function GiscusComments()
{
const { siteConfig } = useDocusaurusContext(); //needed for customFields
return (
<Giscus
id = {`${siteConfig.customFields.Giscus_Id}`}
repo = {`${siteConfig.customFields.Giscus_organizationName}/${siteConfig.customFields.Giscus_projectNameComments}`}
repoId = {`${siteConfig.customFields.Giscus_repoId}`}
...
/>
)
}
Using Multiple Files
Most of the documentation and advice is to have only one .env file per environment. This means not having having multiple .env files such as .env.development or .env.production. If you go down the path to the dark side, you can load a different file depending on which environment you are running in.
One of the built-in variables that we can use is process.env.NODE_ENV. This allows us to see if we are currently running in development or production mode. If we launch docusaurus with the below commands it will return the environment specified:
- npm run start
- process.env.NODE_ENV will return development
- npm run serve -- --build
- process.env.NODE_ENV will return production
console.log("Environment is: " + process.env.NODE_ENV )
if(process.env.NODE_ENV === 'development') {
require('dotenv').config({ path: './.devenv/.env' })
}
else if (process.env.NODE_ENV === 'production') {
require('dotenv').config({ path: './.env' })
}
else //if environment is undefined - using swizzle
require('dotenv').config({ path: './.env' })
Better together
Using custom fields in Docusaurus goes a long way towards managing configuration details in one file. Using environment variables we can store those details that may change based on the environment or values we don't want to store in the docusaurus config file. Combining the two methods gives you more flexibility in how you manage deployments.