How to share envs in a monorepo with vite and nextjs apps
Thiago Marinho

Thiago Marinho @tgmarinhodev

About: Passionate Software Engineer 💻 React · GraphQL · Node.js 🚀 React Native, Relay, Web 3.0 - AI Apps Development, cryptos enthusiast 🪙

Location:
Remote
Joined:
Dec 13, 2018

How to share envs in a monorepo with vite and nextjs apps

Publish Date: May 4 '23
8 7

To share environment variables between two projects in a monorepo, with specific prefixes for each project, you can create a .env.shared file with common environment variables and then use scripts to create specific .env files for each project. Here's how to do that:

Create a .env.shared file at the root of the monorepo with the common environment variables:

SECRET_KEY=your_secret_key
API_URL=your_api_url
Enter fullscreen mode Exit fullscreen mode

Create a script to generate specific .env files for each project. In the example below, we will create a generate-env.js file at the root of the monorepo:

// generate-env.js
const fs = require('fs');
const path = require('path');

const envShared = path.join(__dirname, '.env.shared');
const envVite = path.join(__dirname, 'vite-project', '.env');
const envNext = path.join(__dirname, 'next-project', '.env');

const sharedVars = fs.readFileSync(envShared, 'utf-8').split('\n');

const viteVars = sharedVars.map((line) => {
  if (line.startsWith('SECRET_KEY') || line.startsWith('API_URL')) {
    return `VITE_PUBLIC_${line}`;
  }
  return line;
});

const nextVars = sharedVars.map((line) => {
  if (line.startsWith('SECRET_KEY') || line.startsWith('API_URL')) {
    return `NEXT_PUBLIC_${line}`;
  }
  return line;
});

fs.writeFileSync(envVite, viteVars.join('\n'), 'utf-8');
fs.writeFileSync(envNext, nextVars.join('\n'), 'utf-8');
Enter fullscreen mode Exit fullscreen mode

Run the generate-env.js script to generate the specific .env files for each project:

node generate-env.js
Enter fullscreen mode Exit fullscreen mode

This will create an .env file in the vite-project folder with environment variables prefixed with VITE_PUBLIC_ and an .env file in the next-project folder with environment variables prefixed with NEXT_PUBLIC_.

Now, each project will have its own .env file with the correctly prefixed environment variables. Be sure to add the generated .env files to your .gitignore rules to prevent committing sensitive information to the repository.

Remember to run the generate-env.js script whenever you make changes to the .env.shared file to update the specific project .env files. You can also add this script as a step in your build or deployment process.

Comments 7 total

  • Thiago Marinho
    Thiago MarinhoMay 4, 2023

    eu particularmente prefiro ter uma .env para todo no monorepo no root e fazer um link para cada projeto e repetir o mesmo valor para keys diferentes, se for o caso.
    NEXT_PUBLIC_API=123
    VITE_API=123
    só vou separar isso no ambiente de prod para cada projeto
    tres formas de resolver isso:
    1 - 2 env
    2 - iqual ao artigo
    3 - usando prompts e separar os ambientes: npm: inquirer
    yarn dev --mainnet --api=production --strapi=production --no-prompt

    • Thiago Marinho
      Thiago MarinhoMay 4, 2023

      I like to use it

      gen-env.sh

      
      # In repository root
      cd "$(dirname $0)/.."
      
      cp -n .env.example .env && echo 'Generated: .env'
      ln -sf "$(pwd)/.env" apps/vite/.env && echo 'Linked: apps/vite/.env'
      ln -sf "$(pwd)/.env" apps/nextjs/.env && echo 'Linked: apps/nextjs/.env'
      
      Enter fullscreen mode Exit fullscreen mode
  • Jay @ Designly
    Jay @ DesignlyNov 11, 2023

    here's the sh way:

    #!/bin/sh
    
    # Path to the .env.api and .env.common files
    env_api="./env/.env.api"
    env_common="./env/.env.common"
    
    # Iterate over each directory in packages/*
    for dir in packages/*; do
        # Extract just the directory name without path
        package_name=$(basename "$dir")
    
        # Check if $dir is a directory
        if [ -d "$dir" ]; then
            echo "Processing directory: $dir"
    
            # Switch case based on the directory name
            case "$package_name" in
                admin)
                    echo "Creating env for admin package"
                    cat "$env_common" > "${dir}/.env.local"
                ;;
                api)
                    echo "Creating env for api package"
                    cat "$env_common" "$env_api" > "${dir}/.env.local"
                ;;
                player)
                    echo "Creating env for player package"
                    cat "$env_common" > "${dir}/.env.local"
                ;;
                ui-common)
                    echo "Creating env for ui-common package"
                    cat "$env_common" > "${dir}/.env.local"
                ;;
            esac
        else
            echo "Skipping ${dir}, not a directory."
        fi
    done
    
    echo "All directories processed."
    
    Enter fullscreen mode Exit fullscreen mode
  • Andrei
    AndreiDec 28, 2023

    Just use the dotenv-cli NPM package. Add it to your workspace then prepend dotenv to any script and it will have access to your root env file at runtime.
    Works cross-platform too and you don't have to maintain another script if you prefer a dependency over that.

Add comment