isomorphic-env-webpack-plugin

Webpack plugin and utilities to pass environment variables from server to client via server-side rendering.

Usage no npm install needed!

<script type="module">
  import isomorphicEnvWebpackPlugin from 'https://cdn.skypack.dev/isomorphic-env-webpack-plugin';
</script>

README

isomorphic-env-webpack-plugin

Webpack plugin and utilities to pass environment variables from server to client via server-side rendering.

Installation

# yarn
yarn add isomorphic-env-webpack-plugin

# or npm
npm install isomorphic-env-webpack-plugin

Credits

It was built in alfabank.com by @aapolkovsky and later rewritten in aviasales.com by @7rulnik. Thanks to these awesome companies to make it open source.


Sponsored by Alfa Bank

Sponsored by Aviasales

Motivation

Sometimes you want to change frontend configuration without rebuilding it.

For example, you need to change hostname time to time.

So you will have something like this in source code

fetch(process.env.GOOGLE_HOST)

But if you will use DefinePlugin or EnvironmentPlugin you will get hardcoded values into bundle. Like this:

// After run GOOGLE_HOST=http://google.com webpack
fetch('http://google.com')

And later, if you need to change GOOGLE_HOST you need build your app again.

With this plugin you can set environment variables on a server and pass it to client without rebuilding entire frontend.

Configuration

1. Setup webpack plugin for client config

const {
    IsomorphicEnvWebpackPlugin,
} = require('isomorphic-env-webpack-plugin/dist/plugin')
module.exports = {
    // ...
    plugins: [new IsomorphicEnvWebpackPlugin()],
}

Note that you can't use DefinePlugin after IsomorphicEnvWebpackPlugin.

It will replace your env variables from this:

console.log(process.env.GOOGLE_HOST)

to this:

console.log(self.__ISOMORPHIC_ENV.GOOGLE_HOST)

2. Inject variables into HTML before your script tags

import { getScriptTag } from 'isomorphic-env-webpack-plugin/dist'

const scriptTag = getScriptTag()

function render() {
    return `
    <!doctype html>
    <html>
      <head>
        ...
      </head>
      <body>
        ...
        ${scriptTag}
        <script src="./main.js"></script>
      </body>
    </html>
  `
}

It will inject script tag with variables for client-side:

<!-- ... -->
<script>
    self.__ISOMORPHIC_ENV__ = {
        GOOGLE_HOST: 'https://google.com',
    }
</script>
<script src="./main.js"></script>

3. Add server runtime

It's optional, but without it you can't use server prefixes: S_, SC_, CS_.

// Note, that import should be before any process.env usage
import 'isomorphic-env-webpack-plugin/dist/runtime'

import express from 'express'
// ...

It will add aliases for server-side variables. So you can access it without prefix:

// S_GOOGLE_HOST="https://google.com" node server.js
process.env.S_GOOGLE_HOST === process.env.GOOGLE_HOST // true

Usage

We have 4 prefixes for env variables:

  • S_ — variable for server-side and will not be exposed to client-side. For example: S_YOUR_SERVER_ENV. It works only with server runtime and exists just for more obvious separataion. If you don't want to use runtime you can use just normal YOUR_SERVER_ENV.
  • C_ — variable for client-side. For example: C_YOUR_CLIENT_ENV.
  • CS_ — same variable for server-side and client-side. For example: CS_BOTH_CLIENT_AND_SERVER_ENV. Works only with server runtime.
  • SC_ — same as CS_. The only reason to have it that you don't need to remember which variant is correct: SC_ or CS_.

In code you should access them without prefix:

// S_YOUR_SERVER_ENV
process.env.YOUR_SERVER_ENV

// C_YOUR_CLIENT_ENV
process.env.YOUR_CLIENT_ENV

// CS_BOTH_CLIENT_AND_SERVER_ENV or SC_BOTH_CLIENT_AND_SERVER_ENV
process.env.BOTH_CLIENT_AND_SERVER_ENV

Diferent values on client and server

If you want to use different values on server and client you need to set both C_ and S_ variables:

C_SOME_ENV="I'm client env" S_SOME_ENV="I'm server env" node server.js
// server.js
process.env.SOME_ENV // I'm server env
// client.js
process.env.SOME_ENV // I'm client env

Same value on client and server

If you want to use same value on server and client you need to set CS_ or SC_ variable

It requires server runtime

CS_SOME_ENV="I'm equal on server and client" node server.js
// server.js
process.env.SOME_ENV // I'm equal on server and client
// client.js
process.env.SOME_ENV // I'm equal on server and client

Options

If you don't comfortable with self.__ISOMORPHIC_ENV__ you can change it:

// Pass variableName into plugin
new IsomorphicEnvWebpackPlugin({ variableName: '__SOME_CUSTOM_VARIABLE__' })

// And don't forget to pass same value into getScriptTag
getScriptTag('__SOME_CUSTOM_VARIABLE__')

After that you will have this script tag in your HTML:

<script>
    self.__SOME_CUSTOM_VARIABLE__ = {
        GOOGLE_HOST: 'https://google.com',
    }
</script>