How to set up environment variables?

What’s the proper way of setting environment variables in netlify? I would like to be able to set different values for the variables depending on the environment.

Pseudo code:

let host;
if (process.env.GATSBY_CUSTOM_CONTEXT === 'production') {
	host = process.env.PRODUCTION_HOST
} else if (process.env.GATSBY_CUSTOM_CONTEXT === 'development') {
	host = process.env.DEVELOPMENT_HOST
}

I have tried passing env variable thru CLI, like GATSBY_CUSTOM_CONTEXT=production gatsby build and I also tried using same command with cross-env.

My other attempt used netlify.toml:

[build]
  base = "/"
  publish = "public"
  command = "yarn build"
  functions = "src/functions"

[context.production]
  [context.production.environment]
    GATSBY_CUSTOM_CONTEXT = "production"

All of these options worked with netlify dev locally, but in production GATSBY_CUSTOM_CONTEXT is always undefined.

I can’t offer an official answer here but in my very limited experience (only been using Functions for 3 days now) the things you put into Netlify’s environment variables config are available at both Function runtime as well as at build time. However, the Netlify “pre-defined” env stuff is only available at build time. Thus, if you want to be able to query the context (production, feature preview, etc.), you can only do so at build time.

What I have done so far is to therefore add a custom webpack config for my functions that uses webpack’s DefinePlugin to “bake in” the context. Also, while I’m there I also bake in the stuff that relies on that rather than doing it at runtime, thus I’d like use prcoess.env.HOST in the code, and in the webpack do something like:

module.exports = {
    plugins: [
        new webpack.DefinePlugin({
            'process.env.HOST': process.env.CONTEXT === 'production'
                ? process.env. PRODUCTION_HOST
                : process.env. DEVELOPMENT_HOST
        })
    ]
}

I’m currently debating whether baking the “final” env vars in is a good idea though, because it means that if you change the env vars in Netlify’s settings, you need to rebuild to get the update, which somewhat breaks an expectation. As such, it might be better to just bake in the context and still “decide” on which env vars to use at runtime based on that.

Anyway, hope this helps.

@iamskok, if you are looking to test if your script is being run in the Netlify build image/environment itself, then one great way to do this is by looking for the environment variable NETLIFY=true. For example:

if (process.env.NETLIFY === 'true') {
 <do something Netlify specific here>
}

We set this environment variable in the build image specifically so CI/CD scripts can make conditional rules/tests for our build environment.

I hope this will meet the requirements for this use case and, either way, please feel free to follow-up with additional comments or questions here. We’re happy to discuss this further.

Thanks for your detailed answer. Were you using netlify-lambda? The issue I’m having is that process.env.CONTEXT is undefined in production.

Yep I’m using netlify-lambda and yes, indeed, CONTEXT is not available in production, hence m e using a custom webpack config (with netlify-lambda) to bake in my env vars based on CONTEXT at build time.

You can either do like I demonstrate above, or just bake in 'process.env.CONTEXT': process.env.CONTEXT to have context available at runtime, so your standard logic can then run.

As I allude to in my post I may change my Functions to work like that soon, because baking in env var at the time of build is not always ideal.