isomorphic-env-webpack-plugin v1.2.0
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-pluginCredits
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.
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
DefinePluginafterIsomorphicEnvWebpackPlugin.
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 // trueUsage
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 normalYOUR_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 asCS_. The only reason to have it that you don't need to remember which variant is correct:SC_orCS_.
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_ENVDiferent 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 envSame 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 clientOptions
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>filter
Any of getter-functions (getClientEnvs, getServerEnvs, getScriptContent, getScriptTag) accepts optional filter to exclude some variables from the result.
import { getScriptTag } from 'isomorphic-env-webpack-plugin/dist'
const scriptTag = getScriptTag('__ISOMORPHIC_ENV__', {
filter: (key, value) => key.includes('ALLOW'),
})
function render() {
return `
<!doctype html>
<html>
<head>
...
</head>
<body>
...
${scriptTag}
<script src="./main.js"></script>
</body>
</html>
`
}