Search code examples
typescriptnpmbuild

Inject variables environment after build


Let's see if anyone can enlighten me

I have been doing some research, and I found some library that inject after build but that's not what I want. What I want is to build the project and then inject the environment of staging or production. So basically I want to build just one time and inject then any file of environment(staging or production) after. Now I'm using webpack where I have the Dotenv library and if I want to use staging or production environment I have to build two times.

Is that possible? Thanksbuild


Solution

  • You've said that this is for server-side code and that you're using dotenv.

    You don't need to rebuild for production. There are at least a couple of approaches you can take:

    1. Use environment variables rather than dotenv, or

    2. Use environment variables to control what .env.xyz file dotenv loads, or

    3. Both.

    I suggest #1.

    1. Use environment variables (without dotenv)

    You can just use environment variables without using dotenv. (This is how most of my projects are done.) dotenv cites the Twelve-Factor App guidelines while simultaneously encouraging you to break them — by having a .env file, which is a config file. The guidelines frown on using config files for environment information; from the link:

    The twelve-factor app stores config in environment variables (often shortened to env vars or env). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally...

    (I'm not saying the Twelve-Factor App guidelines are gospel, just that it seems odd to cite them while encouraging using a config file.) I think the idea of dotenv is that you don't ever check .env into source control, but create it manually in the root of each of your environments. But that's not how I see it used in the wild.

    So instead, of dotenv, you could do what those guidelines suggest: Use environment variables. Your hosting platform will provide a way to set environment variables for the environment your code runs in. Those variables will be available on process.env, no need for dotenv.

    Here's a simple example:

    index.js:

    console.log(process.env.EXAMPLE);
    

    If you run that in an environment with an EXAMPLE environment variable, you'll see that variable's value in the console. So you use the features of your hosting platform to set your environment variables, and you're all set.

    (If you want to just try that out locally, you can do it like this on *nix:

    $ EXAMPLE=hi node index.js
    hi
    

    ...or like this on Windows:

    C:\Temp> cmd /C "set EXAMPLE=hi && node index.js"
    hi
    

    ...but don't get the wrong impression from that. You don't set the environment variables at the command line, you set them in whatever way your hosting platform makes available to you.)

    2. Using environment variables (with dotenv)

    If you want to use dotenv and have config files, though, you can use an environment variable to control what config file gets loaded. (This is how a couple of projects I work with are done.)

    You might set an environment variable telling your code what environment it's running in (dev, staging, production, etc.), and then use that to tell dotenv what .env.xyz file to load. create-react-app has made NODE_ENV popular, for instance, using NODE_ENV=DEV for dev and NODE_ENV=PROD for production. You might use that to control dotenv, telling it to use .env.PROD for production but (say) .env.DEV for development or .env.STAGING for staging, etc.

    import path from "path";
    import dotenv from "dotenv";
    
    const env = process.env.NODE_ENV ?? "DEV";
    dotenv.config({
        path: path.resolve(process.cwd(), `.env.${env}`),
    });
    

    3. Both

    You can do a combination of the above. dotenv won't overwrite something in process.env if it's already there (because it's set in the environment). So you could have information in an .env file and override it using the environment features of your hosting platform. But that seems unnecessarily complex.