Explain Codes LogoExplain Codes Logo

Passing environment-dependent variables in Webpack

javascript
webpack
environment-variables
config-management
Alex KataevbyAlex Kataev·Sep 26, 2024
TLDR

Want to inject environment variables in Webpack? DefinePlugin is the way to go:

// Just pulling in some epic Webpack goodness const webpack = require('webpack'); // Don't forget to stringify your vars (they have feelings too) const envVars = { NODE_ENV: JSON.stringify(process.env.NODE_ENV) }; module.exports = { plugins: [ // It's okay, DefinePlugin, everyone likes replacing one thing with another new webpack.DefinePlugin({ 'process.env': envVars }) ] };

Simply set NODE_ENV in your process.env directly from your webpack config. Now you can tell apart your development from your production modes. Go ahead and use JSON.stringify because, you know, DefinePlugin can be a bit picky. Reach your environment in your code like this: process.env.NODE_ENV.

Going beyond the basics: Multiple environments

Sometimes, you're faced with more than just development and production - things get extra fancy. You might have staging, integration, or custom environments. And DefinePlugin is totally up for the ride.

Pick a config, any config

Your environment-specific configuration files can be set up with ease:

// Oh boy, didn't see this switcharoo coming, did ya? const envConfig = require(`./config/${process.env.NODE_ENV}.config`); // Now who's a good DefinePlugin? Yes, you are! new webpack.DefinePlugin(envConfig);

And your package.json can then differ depending on the environment:

// Mother of NPM Scripts! "scripts": { "build:dev": "webpack --env development", "build:prod": "webpack --env production" }

Embrace the complexity

Got complex environment variables? DefinePlugin says, "Bring it on!"

// I see you're an environment variable of culture as well new webpack.DefinePlugin({ 'config': { 'endpoint': JSON.stringify(process.env.API_ENDPOINT), 'featureFlags': JSON.stringify(process.env.FEATURE_FLAGS) } });

The HTML magic trick

Need to replace variables directly in your HTML? html-webpack-plugin and some creative adjustments are your best friends:

// Meet HtmlWebpackPlugin, the magic wand of HTML file manipulations new HtmlWebpackPlugin({ templateParameters: { 'API_URL': JSON.stringify(process.env.API_URL) } })

Set Sail with resolve.alias

Transitioning to webpack from gulp or similar setups? Say hello to resolve.alias. This allows for aliasing modules' identifiers and makes swapping versions feel like a breeze:

// I mustache you a question: ever heard of module aliasing? resolve: { alias: { Config$: path.resolve(__dirname, 'path/to/environment/config') } }

By referencing the Config alias in your application, Webpack will redirect to the correct environment config.

Lint-friendly approach

Linting tools could get jealous with all these global constants inserted via Webpack. Pacify them by updating your ESlint configuration with the following:

"globals": { "API_URL": true }

Quick environment flags

For passing flags or making some minor environment-specific modifications, you can use the --env flag in webpack directly:

webpack --env.TEST=true --config webpack.config.js

It makes your webpack config a fun playground for condition-based configurations.