Define Global Variable with Webpack

Define global variable with webpack

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()



2. 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.



3. 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");


4. 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



5. 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).

How to define global variable in Webpack?

I got this fixed as follows:

First to the root of the project I added a file called globals.js with my desired global object

module.exports = {
Math: Math,
String: String,
....
};

Then to the webpack config, I added the following plugin to replace the global module from core-js (I'm using core-js for polyfilling):

const { NormalModuleReplacementPlugin } = require("webpack");
const path = require("path");
....
module.exports = {
....
plugins: [
new NormalModuleReplacementPlugin(
/node_modules[\\/]core-js[\\/]internals[\\/]global.js/,
path.resolve(__dirname, "globals.js")
),
....
],
....
};

And now the global object is replaced with the one I defined in globals.js

Import a global variable in Webpack

Use webpack's externals:

Prevent bundling of certain imported packages and instead retrieve
these external dependencies at runtime.

externals: {
jquery: 'jQuery'
}

Webpack: create global variable

To set a global variable from inside a module (e.g. index.js), you can add it directly to the window object. Otherwise, the variable will only live in the context of the module.

window.msgpack = require("msgpack-lite");

I think there is another solution where you require("msgpack-lite") inside your native Elm module. This way, you don't need a global variable but instead you have another compilation step for your native Elm module.

How to declare in initialize global variable in TS-Node?

Step 1: Make TypeScript aware of your globals

The canonical way to define globals that exist both in Node.js and on the server is to use the var keyword.

declare global {
var __IS_DEVELOPMENT_BUILDING_MODE__: boolean;
var __IS_TESTING_BUILDING_MODE__: boolean;
var __IS_PRODUCTION_BUILDING_MORE__: boolean;
}

This makes them accessible via globalThis and by referencing them directly.

globalThis.__IS_DEVELOPMENT_BUILDING_MODE__;
__IS_DEVELOPMENT_BUILDING_MODE__;

Step 2: Define them on the client

That's what Webpack.DefinePlugin is already doing for you.

Step 3: Define them on the server

Find the entry point of your Node application and define the variable there.

var __IS_DEVELOPMENT_BUILDING_MODE__ = true;

A common practice is to use environment variables.

var __IS_DEVELOPMENT_BUILDING_MODE__ = process.env.NODE_ENV === 'development;

Access TypeScript global variables with webpack

You can write your application as a Node.js one and then use WebPack to create a bundle.

Here's a simple example. I assume all input files are in one directory.
webpack, webpack-cli, ts-loader, typescript packages should be installed.

globals.ts

export let foo = null;
export let bar = null;

index.ts

import * as globals from "./globals";

globals.foo = "foo";
globals.bar = "bar";

console.log(globals);

tsconfig.json

{
"compilerOptions": {
"target": "esnext",
"module": "commonjs"
}
}

webpack.config.js

let path = require("path");

module.exports = {
entry: "./index.ts",
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/
}
]
},
resolve: {
extensions: [".tsx", ".ts", ".js"]
},
output: {
path: path.resolve(__dirname, "scripts"),
filename: "bundle.js"
},
mode: "development"
};

Setting global variables in a custom webpack plugin

I found my answer in this question: webpack plugin that adds other plugins

I can run this to also call DefinePlugin during the build process:

apply(compiler: webpack.Compiler) {
const versionId = '1234';

new webpack.DefinePlugin({
VERSION: JSON.stringify(versionId)
}).apply(compiler);

// other code
}

Webpack and TypeScript Global Variables / Global Functions

This worked for me, after searching for more answers I stumbled upon this Stack Overflow Answer, I tried it our and it worked! This is the answer that I found to work.

// tsconfig.json
"compilerOptions": {
// ...
"baseUrl": "./",
"rootDir": "./",
// ...
}


Related Topics



Leave a reply



Submit