Loading Bootstrap 3's JavaScript Components With RequireJS

Use Only What You Need

I previously wrote about using Twitter Bootsrap 3 with RequireJS. That approach loaded Boostrap’s entire JavaScript library at once.

Now we’ll look at using RequireJS to only load the Boostrap 3 JavaScript components you want.

First, download the individual Bootstrap components you wish to use. You can get them directly from Bootstrap’s GitHub repo

Let's look at our RequireJS setup file. I'll use the require.config(...) technique instead of the var require = {...} approach I've used elsewhere.


require.config({
    shim: {
        'bootstrap/affix':      { deps: ['jquery'], exports: '$.fn.affix' }, 
        'bootstrap/alert':      { deps: ['jquery'], exports: '$.fn.alert' },
        'bootstrap/button':     { deps: ['jquery'], exports: '$.fn.button' },
        'bootstrap/carousel':   { deps: ['jquery'], exports: '$.fn.carousel' },
        'bootstrap/collapse':   { deps: ['jquery'], exports: '$.fn.collapse' },
        'bootstrap/dropdown':   { deps: ['jquery'], exports: '$.fn.dropdown' },
        'bootstrap/modal':      { deps: ['jquery'], exports: '$.fn.modal' },
        'bootstrap/popover':    { deps: ['jquery'], exports: '$.fn.popover' },
        'bootstrap/scrollspy':  { deps: ['jquery'], exports: '$.fn.scrollspy' },
        'bootstrap/tab':        { deps: ['jquery'], exports: '$.fn.tab'        },
        'bootstrap/tooltip':    { deps: ['jquery'], exports: '$.fn.tooltip' },
        'bootstrap/transition': { deps: ['jquery'], exports: '$.fn.transition' }
    },
    paths: {
        /* path to folder where individual bootstrap files have been saved. (affix.js, alert.js, etc) */
        'bootstrap': '/js/vendor/bootstrap',
        /* jQuery from CDN  */
        'jquery': '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min'
    },
});

Note - the exports property is not necessary when declaring the shims. But by using export each component returns a value into our anonymous function executed by RequireJS.


require(['jquery', 'bootstrap/carousel', 'other/module'], function($, carousel, otherModule){
    // otherModule.foo();
    // $('.element').carousel();
    // 'carsousel' is unused
});

Without the exports property in the shim, no value would be returned. Your RequireJS you implementation code would change to:


require(['jquery', 'other/module', 'bootstrap/carousel'], function($, otherModule){
    // otherModule.foo();
    // $('.element').carousel()
});

Because bootstrap/carousel would not return a value it must be referenced at the end.

Summary

The shim and the jquery dependency are critical. The exports property, no so much.

My preference is to not use exports with the Bootstrap 3 components. Just remove it from the first code sample.

Boostrap 3's component are jQuery plugins, which is great. But from a RequireJS point-of-view that means they're not returning self-contained modules. Their code is stored inside of the famous jQuery $.

It could be said that using exports gives us a cleaner require() because every modules maps to an argument. But think it's bad practice to have arguments that are not in use. To a future developer, it may add more confusion and noise than clarity.

This would be my final condensed snippet:


// FILE: require-setup.js

require.config({
    shim: {
        'bootstrap/affix':      { deps: ['jquery'] }
    },
    paths: {
        /* path to folder where individual bootstrap files have been saved. (affix.js, alert.js, etc) */
        'bootstrap': '/js/vendor/bootstrap',
        /* jQuery from CDN  */
        'jquery': '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min'
    },
});

// FILE: app.js
require(['jquery', 'bootstrap/carousel'], function($){
    // $('.element').carousel()
});

This article was written using Markdown For Sitecore.

Fish