Javascript

Define global variable with webpack

27 September 2026 · 8 min read

Define global variable with webpack

In the evolving landscape of modern JavaScript development, managing variables effectively is crucial for building robust and maintainable applications. While the concept of global variables often carries a negative connotation due to potential conflicts and code unpredictability, there are legitimate scenarios where injecting application-wide constants or configuration values is necessary. This is where Webpack, a powerful module bundler, steps in with elegant solutions. Understanding how to define global variable with webpack allows developers to inject compile-time constants, environment-specific configurations, and feature flags directly into their bundled code, ensuring consistency and enhancing security without polluting the actual global scope of the browser.

The Challenge of Global Variables in Modern JavaScript

Historically, developers often relied on global variables for shared state or configuration, leading to issues like variable shadowing, naming collisions, and difficult debugging. The advent of module systems in JavaScript, such as ES Modules and CommonJS, largely mitigated these problems by providing isolated scopes for code. However, certain constants or environment-dependent values still need to be accessible across different parts of an application without being hardcoded or passed through every function call. For instance, an application might need to know if it’s running in development or production mode, or require an API key that varies per environment.

Directly attaching these values to the global window object is generally discouraged in complex applications as it breaks encapsulation and makes code harder to reason about. Webpack offers a superior alternative by allowing you to inject these “global-like” variables during the build process itself. This approach ensures that the values are baked into the final bundle, making them immutable and accessible where needed, while maintaining the integrity of your module system. It’s a fundamental aspect of modern frontend development that bridges the gap between static code and dynamic configurations, preparing your JavaScript application for various deployment scenarios.

Leveraging Webpack’s DefinePlugin for Global Constants

The primary tool Webpack provides to define global variable with webpack is the DefinePlugin. This plugin allows you to create global constants that can be configured at compile time. What makes DefinePlugin incredibly powerful is its simple string replacement mechanism: any instance of the defined “variable” in your source code is literally replaced by its configured value during the bundling process. This isn’t merely assigning a value at runtime; it’s a static replacement that occurs before your code even reaches the browser, making it highly efficient and secure.

For example, if you define 'process.env.NODE_ENV': JSON.stringify('production'), every occurrence of process.env.NODE_ENV in your code will be replaced with the string 'production'. This static replacement has a significant benefit: it enables dead code elimination. If your code includes conditional blocks like if (process.env.NODE_ENV === 'production') { / production-only code / }, Webpack’s minification step can completely remove the development-specific code when bundling for production, leading to smaller, more optimized bundles. This capability is crucial for delivering performant web applications and is a cornerstone of modern build process optimization. You can learn more about its capabilities in the official Webpack DefinePlugin documentation.

Basic Configuration Example

To use the DefinePlugin, you’ll need to add it to your webpack.config.js file. Here’s a simple example:

const webpack = require('webpack'); module.exports = { // ... other webpack configurations plugins: [ new webpack.DefinePlugin({ 'APP_VERSION': JSON.stringify('1.0.0'), 'API_BASE_URL': JSON.stringify('https://api.example.com/v1'), 'DEBUG_MODE': JSON.stringify(true), }) ] }; 

In your JavaScript code, you can then directly reference these constants:

console.log(Application Version: ${APP_VERSION}); fetch(${API_BASE_URL}/data); if (DEBUG_MODE) { console.log("Debug mode is active."); } 

Remember that the values provided to DefinePlugin must be fully JSON-stringified expressions, including strings themselves, which need extra quotes (e.g., JSON.stringify('value')). This ensures that the replacement is valid JavaScript. Using JSON.stringify() is a best practice to correctly handle different data types and prevent syntax errors after replacement.

Integrating Environment Variables with DefinePlugin

One of the most common and powerful use cases for DefinePlugin is injecting environment variables into your frontend application. This allows you to configure different behaviors or API endpoints based on the deployment environment (development, staging, production, etc.) without modifying your source code. You typically load environment variables from your shell or a .env file, then pass them to Webpack during the build process.

For instance, you might have a .env file containing NODE_ENV=development or NODE_ENV=production. When you run your build command, these variables become available in your Node.js environment via process.env. You can then map them directly within your DefinePlugin configuration. This approach centralizes your configuration and makes your build process more robust and less error-prone across different environments. It’s a critical component for managing configurations in any significant JavaScript application.

const webpack = require('webpack'); const dotenv = require('dotenv'); // Make sure to install 'dotenv' // Load environment variables from .env file const env = dotenv.config().parsed; // Reduce it to a nice object, ensuring values are stringified for DefinePlugin const envKeys = Object.keys(env).reduce((prev, next) => { prev[process.env.${next}] = JSON.stringify(env[next]); return prev; }, {}); module.exports = { // ... other webpack configurations plugins: [ new webpack.DefinePlugin(envKeys) ] }; 

This setup allows you to use process.env.YOUR_VARIABLE directly in your client-side code, and Webpack will replace it with the correct value at compile time. For example, if your .env file contains API_KEY=abc123xyz, then process.env.API_KEY in your application code will be replaced with "abc123xyz". This method is far superior to exposing sensitive keys on the client-side without a build step, which can lead to security vulnerabilities. Always be cautious about which variables you expose to the client-side, especially sensitive ones like database credentials, which should remain server-side.

Securing Sensitive Information

While DefinePlugin is excellent for injecting non-sensitive environment variables, it’s crucial to understand that any variable injected this way becomes part of your client-side bundle and is therefore visible to anyone who inspects your source code. This means you should never inject truly sensitive information like database passwords or private API keys directly into your frontend code. For such secrets, always rely on backend services, server-side environment variables, or secure credential management systems. More information Question & Answer :

Is it possible to define a global variable with webpack to result something like this:

var myvar = {}; 

All of the examples I saw were using external file require("imports?$=jquery!./file.js")

There are several way to approach globals:


  1. Put your variables in a module.

Webpack evaluates modules only once, so your instance remains global and carries changes through from module to module. So if you create something like a globals.js and export an object of all your globals then you can import './globals' and read/write to these globals. You can import into one module, make changes to the object from a function and import into another module and read those changes in a function. Also remember the order things happen. Webpack will first take all the imports and load them up in order starting in your entry.js. Then it will execute entry.js. So where you read/write to globals is important. Is it from the root scope of a module or in a function called later?

config.js

export default { FOO: 'bar' } 

somefile.js

import CONFIG from './config.js' console.log(`FOO: ${CONFIG.FOO}`) 

Note: If you want the instance to be new each time, then use an ES6 class. Traditionally in JS you would capitalize classes (as opposed to the lowercase for objects) like
import FooBar from './foo-bar' // <-- Usage: myFooBar = new FooBar()


  1. Use Webpack’s ProvidePlugin.

Here’s how you can do it using Webpack’s ProvidePlugin (which makes a module available as a variable in every module and only those modules where you actually use it). This is useful when you don’t want to keep typing import Bar from 'foo' again and again. Or you can bring in a package like jQuery or lodash as global here (although you might take a look at Webpack’s Externals).

Step 1. Create any module. For example, a global set of utilities would be handy:

utils.js

export function sayHello () { console.log('hello') } 

Step 2. Alias the module and add to ProvidePlugin:

webpack.config.js

var webpack = require("webpack"); var path = require("path"); // ... module.exports = { // ... resolve: { extensions: ['', '.js'], alias: { 'utils': path.resolve(__dirname, './utils') // <-- When you build or restart dev-server, you'll get an error if the path to your utils.js file is incorrect. } }, plugins: [ // ... new webpack.ProvidePlugin({ 'utils': 'utils' }) ] } 

Now just call utils.sayHello() in any js file and it should work. Make sure you restart your dev-server if you are using that with Webpack.

Note: Don’t forget to tell your linter about the global, so it won’t complain. For example, see my answer for ESLint here.


  1. Use Webpack’s DefinePlugin.

If you just want to use const with string values for your globals, then you can add this plugin to your list of Webpack plugins:

new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), VERSION: JSON.stringify("5fa3b9"), BROWSER_SUPPORTS_HTML5: true, TWO: "1+1", "typeof window": JSON.stringify("object") }) 

Use it like:

console.log("Running App version " + VERSION); if(!BROWSER_SUPPORTS_HTML5) require("html5shiv"); 

  1. Use the global window object (or Node’s global).

window.foo = 'bar' // For SPA's, browser environment. global.foo = 'bar' // Webpack will automatically convert this to window if your project is targeted for web (default), read more here: https://webpack.js.org/configuration/node/ 

You’ll see this commonly used for polyfills, for example: window.Promise = Bluebird


  1. Use a package like dotenv.

(For server side projects) The dotenv package will take a local configuration file (which you could add to your .gitignore if there are any keys/credentials) and adds your configuration variables to Node’s process.env object.

// As early as possible in your application, require and configure dotenv. require('dotenv').config() 

Create a .env file in the root directory of your project. Add environment-specific variables on new lines in the form of NAME=VALUE. For example:

DB_HOST=localhost DB_USER=root DB_PASS=s1mpl3 

That’s it.

process.env now has the keys and values you defined in your .env file.

var db = require('db') db.connect({ host: process.env.DB_HOST, username: process.env.DB_USER, password: process.env.DB_PASS }) 

Notes

Regarding Webpack’s Externals, use it if you want to exclude some modules from being included in your built bundle. Webpack will make the module globally available but won’t put it in your bundle. This is handy for big libraries like jQuery (because tree shaking external packages doesn’t work in Webpack) where you have these loaded on your page already in separate script tags (perhaps from a CDN).