ProvidePlugin & Global Vars

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Delete the window.jQuery line. Instead, go to webpack.js.org. This time, skip straight to the Documentation, Plugins, then find the ProvidePlugin. This plugin is crazy cool: it's both massively useful and shows off the power of the dark side... I mean Webpack.

At the top, it says:

Automatically load modules instead of having to require them everywhere.

Let's see what that means. In webpack.config.js, there is a new key we can put here called plugins, set to an array. Add new webpack.ProvidePlugin() with {}. Inside, pass a key called jQuery set to the string jquery in all lowercase... like the module's name:

... lines 1 - 3
module.exports = {
... lines 5 - 13
plugins: [
new webpack.ProvidePlugin({
jQuery: 'jquery',
... line 17
})
]
};

The ProvidePlugin() is bananas. Thanks to this line, whenever Webpack finds a variable in any file named jQuery that has not been initialized - in other words, some module like bootstrap where it's trying to use jQuery as a global variable - it will automatically require the jquery module and set the jQuery variable to that in the dumped file.

This is a game-changer: whenever we try to use any module that relies on jQuery as a global variable, this plugin will rewrite that code to use a proper require statement. Let's do the same thing for the $ variable, which should also use the jquery module:

... lines 1 - 3
module.exports = {
... lines 5 - 13
plugins: [
new webpack.ProvidePlugin({
jQuery: 'jquery',
$: 'jquery'
})
]
};

Tip

There is also something called the imports-loader, where you can do something similar to the ProvidePlugin on a module-by-module basis.

Oh, but PhpStorm says the webpack element "is not exported". At the top, add const webpack = require('webpack'):

... line 1
const webpack = require('webpack');
module.exports = {
... lines 5 - 13
plugins: [
new webpack.ProvidePlugin({
... lines 16 - 17
})
]
};

The plugin comes from Webpack, which we need to require like anything else. My editor still doesn't look super happy, but it will work, I promise!

Let's give it a shot! Go back and restart webpack:

./node_modules/.bin/webpack --watch

Then, find your browser and refresh. Ha! It's alive!!!

Take a look at the built layout.js file. These files are not meant to be easy to read: Webpack adds a lot of magic to get things working. But, it can be really interesting while learning. At the top, Webpack adds its bootstrap code. Next, search for the word "bootstrap".

Woh, check out this "VAR INJECTION" stuff: Webpack wraps Bootstrap in a self-executing function and passes jQuery as an argument. Inside, instead of Bootstrap using a global jQuery variable, it's using whatever is being passed as jQuery.

And... what is that? If you follow the green line on the left to the bottom of the self-executing function, it calls itself with .call() and passes a cryptic __webpack_require__(0) as the first argument. Internally, this is the require call to the jquery module. When it dumps the file, Webpack gives each module a number, and if you did some digging, you'd find out that 0 means jquery in this case.

Like I said... these files aren't meant to be read by humans, but it's really amazing to see how Webpack manages to build this one, final file.

Leave a comment!

This tutorial explains the concepts of an old version of Webpack using an old version of Symfony. The most important concepts are still the same, but you should expect significant differences in new versions.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.2.0",
        "symfony/symfony": "3.3.*", // v3.3.16
        "twig/twig": "2.10.*", // v2.10.0
        "doctrine/orm": "^2.5", // v2.7.0
        "doctrine/doctrine-bundle": "^1.6", // 1.10.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.5
        "symfony/swiftmailer-bundle": "^2.3", // v2.6.3
        "symfony/monolog-bundle": "^2.8", // v2.12.1
        "symfony/polyfill-apcu": "^1.0", // v1.4.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.26
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "friendsofsymfony/user-bundle": "^2.0", // v2.1.2
        "doctrine/doctrine-fixtures-bundle": "~2.3", // v2.4.1
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.3.2
        "friendsofsymfony/jsrouting-bundle": "^1.6" // 1.6.0
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.6
        "symfony/phpunit-bridge": "^3.0" // v3.3.5
    }
}

What JavaScript libraries does this tutorial use?

// package.json
{
    "dependencies": [],
    "devDependencies": {
        "babel-core": "^6.25.0", // 6.25.0
        "babel-loader": "^7.1.1", // 7.1.1
        "babel-plugin-syntax-dynamic-import": "^6.18.0", // 6.18.0
        "babel-preset-env": "^1.6.0", // 1.6.0
        "bootstrap-sass": "^3.3.7", // 3.3.7
        "clean-webpack-plugin": "^0.1.16", // 0.1.16
        "copy-webpack-plugin": "^4.0.1", // 4.0.1
        "core-js": "^2.4.1", // 2.4.1
        "css-loader": "^0.28.4", // 0.28.4
        "extract-text-webpack-plugin": "^3.0.0", // 3.0.0
        "file-loader": "^0.11.2", // 0.11.2
        "font-awesome": "^4.7.0", // 4.7.0
        "jquery": "^3.2.1", // 3.2.1
        "lodash": "^4.17.4", // 4.17.4
        "node-sass": "^4.5.3", // 4.5.3
        "resolve-url-loader": "^2.1.0", // 2.1.0
        "sass-loader": "^6.0.6", // 6.0.6
        "style-loader": "^0.18.2", // 0.18.2
        "sweetalert2": "^6.6.6", // 6.6.6
        "webpack": "^3.4.1", // 3.4.1
        "webpack-chunk-hash": "^0.4.0", // 0.4.0
        "webpack-dev-server": "^2.6.1", // 2.6.1
        "webpack-manifest-plugin": "^1.2.1" // 1.2.1
    }
}