DEV Community

Erik Vullings
Erik Vullings

Posted on

Getting environment variables to your web application

Getting environment variables to your web application

It is often useful during development to inform your build process that it is working in development mode or production mode. And there are multiple ways to do this, e.g. you can often specify them on the command line, use an environment variable, or put them all together in a .env file.

When you are developing a node.js application, getting access to these environment variables in your code is also easy, for example by using process.env.SOME_VAR, optionally combined with dotenv to read those .env files before startup.

However, when you need those environment variables also in your web application, e.g. to specify the URL for the production or development service, it is less well documented if you don't know where to look. As it turns out, fortunately, it is not too difficult either:

Parcel

Parcel is a very easy to use build tool, which transpiles and minifies your JavaScript or TypeScript code, CSS files, etc. without any configuration. But as it happens, Parcel also exposes your environment variables to your web application's code. So you can use process.env.SOME_VAR directly in your JavaScript code. In case you are working with TypeScript, you need to add a declaration for it too, e.g.

declare const process: {
  env: {
    SOME_VAR: string;
  };
};

Webpack

Webpack is also a very popular choice to build your application, but requires much more configuration too. So in order to pass environment variables to your web application code, you need to use a default Webpack plugin, the DefinePlugin (see also here). For example, your webpack config file could look as follows (when you use TypeScript). Note that you use JSON.stringify to pass the value of your variable.

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

// Import environment variables into your build configuration.
module.exports = (env = {}) => {
  const plugins = [
    new HtmlWebpackPlugin({
      meta: {
        description: 'MY_DESCRIPTION',
      },
      title: 'MY_TITLE',
      favicon: './src/assets/favicon.ico',
    }),
    new webpack.HotModuleReplacementPlugin(),
  ];
  // In non-production environment, set the SERVICE_URL
  if (!env.production) {
    plugins.push(
      new webpack.DefinePlugin({
        SERVICE_URL: JSON.stringify('http://localhost:3210'),
      })
    );
  }

  return {
    entry: './src/index.ts',
    mode: 'development',
    devtool: 'inline-source-map',
    devServer: {
      contentBase: './dist',
      hot: true,
    },
    plugins,
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          use: 'awesome-typescript-loader',
          exclude: /node_modules/,
        },
        {
          test: /\.css$/,
          use: ['style-loader', 'css-loader'],
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: ['file-loader'],
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          use: ['file-loader'],
        },
      ],
    },
    resolve: {
      extensions: ['.ts', '.js'],
    },
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
  };
};

In order to use the previously declared SERVICE_URL in your web app, you still need to declare it (e.g. in declarations.d.ts)

declare var SERVICE_URL: string;

As Webpack replaces your SERVICE_URL everywhere, complete dead code blocks (if (false) { ... }) can be removed during the minification, so that is rather need.

Other build environments

For React or Vue applications, their build tools do this automatically for you: environment variables that follow a specific naming syntax, e.g. start with VUE_, are exposed into your web app.

REST-EASY-LOKI

I follow a similar approach for a small REST service that I built around the in-memory database, lokijs, rest-easy-loki. All environment variables that start with LOKI_ are exposed at SERVER/api/env dynamically.

Top comments (0)