8

I am trying to achieve the following:

  • bundle (in this order) jquery, tether, and bootstrap.js.
  • load this bundle within a HTMLpage and beneath it load other page specific scripts.

To achieve this I am using webpack 2 and the CommonsChunkPlugin. Here is my config.

For entries I have:

const scriptsEntry = {
    blog_index: SRC_DIR + "/js/pages/blog_index.js",
    blog_about: SRC_DIR + "/js/pages/blog_about.js",
    vendor: ["jquery", "tether", "bootstrap"]
};

In the plugins section:

scriptsPlugins.push(
    new webpack.optimize.CommonsChunkPlugin({
        name: "vendor", 
        filename:"vendor.bundle.js", 
        minChunks: 2
    }),
    ...
}));

Inside 'index.html' I load the bundles:

<script src="{{ url_for('static', filename='dist/js/vendor.bundle.js') + anti_cache_token }}"></script>
<script src="{{ url_for('static', filename='dist/js/home.js') + anti_cache_token }}"></script>

Inside the source directory in the blog_index.js I make use of jquery:

import $ from "jquery";

$(".home-click").click(function () {
    alert("clicked from .home-click");
});

The result:

  • everything bundles without any errors.
  • when I click .home-click the alert box fires as expected.
  • checking the bundled files I see that:
    • vendor.bundle.js contains: jquery, tether, and bootstrap.
    • looking inside, for instance, blog_index.js (after it was run through webpack 2), I notice that the jquery import is not bundled inside this file, but vendor.bundle.js (this is as expected).

However, I have the following problem when I check the browser console: enter image description here

I tried switching the order of the libraries in this line vendor: ["jquery", "tether", "bootstrap"], but nothing changed--the error is still there.

Do you know how can I solve this, preferably without using additional webpack plugins?

1 Answer 1

11

Bootstrap's javascript assumes that jQuery is hooked on the window object, it does not require it or anything.

By bundling stuff up, you do not expose variables to the global scope, or at least you should not be doing that. So the bootstrap code cannot find jQuery.

Add this to your plugins and you should be ok

new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    'window.jQuery': 'jquery',
    tether: 'tether',
    Tether: 'tether',
    'window.Tether': 'tether',
})

This will replace all instances where jQuery is assumed as global with the export of the jQuery package, which is the jQuery object. Same for Tether

Sign up to request clarification or add additional context in comments.

11 Comments

Thanks a lot for your answer. I have a short question: does adding this have an effect on the vendor.bundle.js?
Yes, it will be replacing instances of the word jQuery, $, window.jQuery etc, with something that actually points to the jQuery object. For example, something like this * WEBPACK VAR INJECTION */(function(jQuery, __webpack_provided_window_dot_Tether, Tether) {/*!. It does not affect functionality in any way,
Thanks! I think I understand, but just to make sure: because it only exposes the plugin it means that I don't have to modify the configuration of entry and CommonChunksPlugin. Did I get it correctly?
You definitely don't need to modify your entry or anything in the CommonChunksPlugin, but I don't understand what is that confuses you. What do you mean by 'only exposes the plugin' ? Help me help you
Sorry for the confusion. My concern was that I would end up bundling the libraries twice (ProvidePlugin and CommonChunksPlugin). However, reading your explanations I understand that only modules that are already loaded inside vendor.bundle.js will be exposed using the ProvidePlugin if specified so. Is this a little more clear?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.