Search code examples
requirejsbootbox

Using bootbox in RequireJS app


I have a sample app.js file with:

requirejs.config({
    "baseUrl": "js/lib",
    "paths": {
      "jquery": "jquery",
      "app": "../app",
      "bootstrap": "bootstrap/js/bootstrap.bundle",
      "bootbox": "bootbox.min"
    },
    "shim": {
        "bootstrap": {
            "deps": ["jquery"],
            "exports": 'bootbox'
             },
        "main": { "deps": ["jquery","bootstrap"] },
        "bootbox": {
            "deps": ["jquery","bootstrap"],
            "exports": 'bootbox'
        },
    }
});

require(['jquery','bootstrap','bootbox'], function($){

    $(function(jquery) {
        bootbox.alert("bla")
    });
});

When I run my page, I can see the correct JS files being grabbed:

enter image description here

...yet my code fails:

bootbox.alert("bla")

Gives:

ReferenceError: bootbox is not defined

I must be missing something simple (again, apologies if this is a newbie error - I'm still trying to get my head around this library)


Solution

  • Don't use shim with Bootbox. If you look at the source code of Bootbox, you'll see it calls define, which registers it as a proper AMD module. The shim option is only for code which is not a proper AMD module.

    Now, the define in Bootbox does this:

    define(["jquery"], factory);
    

    It sets a dependency on jQuery, but that is wrong, because in fact Bootbox also depends on Bootstrap being present. So we need to fix this. The following shows how you can fix it. You can use a map configuration option so that when Bootbox requires jQuery, it gets Bootstrap. And you set a shim for Bootstrap so that, in addition to having a dependency on jQuery, its module value is the same as jQuery ($).

    Without the map setup, there's no guarantee that Bootstrap will load before Bootbox and you'll be facing a race condition: sometimes it'll work, sometimes not.

    requirejs.config({
      baseUrl: ".",
      paths: {
        jquery: "//ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min",
        bootstrap: "//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min",
        bootbox: "//github.com/makeusabrew/bootbox/releases/download/v4.4.0/bootbox.min"
      },
      shim: {
        "bootstrap": {
          "deps": ["jquery"],
          // We set bootstrap up so that when we require it, the value with get is just $.
          // This enables the map below.
          "exports": "$"
        },
      },
      map: {
        // When bootbox requires jquery, give it bootstrap instead. This makes it so that
        // bootstrap is **necessarily** loaded before bootbox.
        bootbox: {
          jquery: "bootstrap",
        },
      }
    });
    
    require(["jquery", "bootbox"], function($, bootbox) {
      $(function(jquery) {
        bootbox.alert("bla");
      });
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.5/require.min.js"></script>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />