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")
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:
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()
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.
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");
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
(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
})
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).
externals
instead if you need to create a global variable. Example: externals: { 'webpackVariables': `{ serverUrl: '${ env.server }', cordovaBuild: '${ env.cordova }', }`, },
Then use it as const webpackVariables = require('webpackVariables');
–
Anglicism foo: null
, then in component-a.js you do utils.foo = 'bar'
. Then in component-b.js you do console.log(utils.foo) // bar
. Just don't do import utils from '../utils
in the component files or that will get you a new utils object. Not sure why I got a downvote just now. –
Netsuke utils.foo = 'bar'
. Then all the other functions ran after this point in main.js (those modules WILL need to do import utils from '../utils'
also) will have 'bar'
. Remember, must be ran after main.js. Webpack will grab all the imports first (in order starting from main.js) then actually run main.js. It's a little confusing, so just experiment and you'll get it. –
Netsuke window.globalVars
in real world, but I'll try to understand your update. –
Nicholasnichole declare const isProduction: bool;
For reference, check this out typescriptlang.org/docs/handbook/declaration-files/templates/… –
Eleazar export const routingService = new RoutingService();
. I would like to access routingService from everywhere in the document, How to do that ? –
Altheaalthee import { routingService } from '...'
in any other module and they will all share that same instance of RoutingService. Easy peasy. –
Netsuke I was about to ask the very same question. After searching a bit further and decyphering part of webpack's documentation I think that what you want is the output.library
and output.libraryTarget
in the webpack.config.js
file.
For example:
js/index.js:
var foo = 3;
var bar = true;
webpack.config.js
module.exports = {
...
entry: './js/index.js',
output: {
path: './www/js/',
filename: 'index.js',
library: 'myLibrary',
libraryTarget: 'var'
...
}
Now if you link the generated www/js/index.js
file in a html script tag you can access to myLibrary.foo
from anywhere in your other scripts.
export { foo }
from the index.js
? –
Naranjo export { foo }
in the script that is used as an entrypoint (e.g. index.js
). WARNING: For some reason it did not work when using devServer
(e.g. webpack serve
) even after restart. I had to manually perform webpack build
for the configuration to take effect. –
Gauntlett Use DefinePlugin.
The DefinePlugin allows you to create global constants which can be configured at compile time.
new webpack.DefinePlugin(definitions)
plugins: [
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true)
})
//...
]
console.log(`Environment is in production: ${PRODUCTION}`);
window.*
variable e.g. for external scripts, DefinePlugin won't work. –
Stanch window.*
var to a relative import of a static file in bumbled dest? –
Circassian You can use define window.myvar = {}
.
When you want to use it, you can use like window.myvar = 1
var window.CKEDITOR_BASEPATH = {};
Error is "Unexpected Token" after window.
–
Cupronickel var
keyword. window.CKEDITOR_BASEPATH = {};
–
Moen DefinePlugin doesn't actually define anything. What it does is replace variables that exist in your bundle code. If the variable doesn't exist in your code, it will do nothing. So it doesn't create global variables.
In order to create a global variable, write it in your code:
window.MyGlobal = MY_GLOBAL;
And use DefinePlugin to replace MY_GLOBAL
with some code:
new webpack.DefinePlugin({
'MY_GLOBAL': `'foo'`,
// or
'MY_GLOBAL': `Math.random()`,
}),
Then your output JS will be like this:
window.MyGlobal = 'foo';
// or
window.MyGlobal = Math.random();
But MY_GLOBAL
will never actually exist at runtime, because it is never defined. So that's why DefinePlugin has a misleading name.
You may hit this issue, when triing bundle < script > tag js files in some old project. Do not use webpack for this, it may be even impossible if joining 50+ libraries like jquery and then figuring out all global variables or if they used nested require. I would advice to simply use uglify js instead , which drops all this problems in 2 commands.
npm install uglify-js -g
uglifyjs --compress --mangle --output bundle.js -- js/jquery.js js/silly.js
I solved this issue by setting the global variables as a static properties on the classes to which they are most relevant. In ES5 it looks like this:
var Foo = function(){...};
Foo.globalVar = {};
© 2022 - 2024 — McMap. All rights reserved.
utils
namespace in the target file - initially I had just put a breakpoint in the browser's source window and I kept puzzling over whyutils
wasn't defined. Finally I discovered that webpack (rather smartly) only includes a module if its namespace is referenced at least once. Therefore, once I did preface one of the target file's utility functions withutils
, the module was included. – Heavyarmed