Use RequireJS with WordPress (plugins) & jQuery (UI)

I recently found myself really wanting to use RequireJS with WordPress, to manage the various JavaScript dependencies a client site had. Unfortunately, this was easier said than done.

WordPress is historically not very compatible with RequireJS, as it provides jQuery and a myriad of other JavaScript files out of the box, which are difficult to shoehorn into your RequireJS configuration. There are loads of WordPress plugins out there which rely on jQuery being a global variable in the page.

Also, any attempt at loading RequireJS into the page will often result in errors because many JavaScript modules first check if require is defined before they execute. This means that the very act of including RequireJS in the page will change how some code is executed, and cause you lots of headaches!

We need require to be defined so that we can make lots of lovely require calls throughout our webpage, but we can’t actually define require until all of WordPress’ native dependencies and plugin JS files have sorted themselves out.

I managed to hack together a solution, and it seems to work rather well.

Edit your header

First of all, edit header.php (I put this just above the wp_head() call):

<script>
window.queueForRequire = [];
 
window.r = function (deps, callback) {
    window.queueForRequire.push({
        deps:     deps,
        callback: callback
    });
};
</script>

We’re going to store any require() calls in a queue: queueForRequire.

Then require your modules as normal. Well, as semi-normal: as mentioned previously, many JavaScript files will check if require is defined and misbehave if it is, so instead of mocking require, I’ve made a custom function r which we’ll use instead.

<script>
r(['subscribe-cta'], function (subscribe) {
    console.log('This is my callback');
});
 
<?php if (is_home() && apply_filters('require_slider', $shouldLoadSlider)) : ?>
r(['slider']);
<?php endif; ?>
 
<?php if (is_archive() || is_home()) : ?>
r(['infinite-scroll']);
<?php endif; ?>
</script>

At this stage, all we’re doing is adding require calls to a queue – nothing is being downloaded just yet.

Edit your footer

Now edit footer.php (put this right before the closing </body> tag):

<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js"></script>
<script>
    require.config({
        baseUrl: '/wordpress/wp-content/themes/tc-magazine-core/js',
        paths: {
            'readmore': 'https://cdnjs.cloudflare.com/ajax/libs/Readmore.js/2.1.0/readmore.min'
        },
        waitSeconds: 15
    });
 
    if (typeof jQuery === 'function') {
        define('jquery', function () { return jQuery; });
    }
 
    for (var i = 0; i < window.queueForRequire.length; i++) {
        require(window.queueForRequire[i].deps, window.queueForRequire[i].callback);
    }
</script>

Only at the very end of the document do we go “now I’m ready to load RequireJS. WordPress has done its thing, so it should be safe for us to do ours now”.

So, this is pretty standard stuff: we’re downloading the RequireJS library from a CDN and initialising it with a config. jQuery is a strange special case handled in lines 11-13: we want our modules to be able to pull in jQuery as a module, but know jQuery is probably a global already, so here we’re creating a jQuery AMD module on the fly.

The magic happens on lines 15-17: now that we have RequireJS, we can go ahead and download all the things we’ve queued already (and call their callbacks if those were passed as arguments).

RequireJS with WordPress

There you have it – RequireJS working nicely with WordPress and all its plugins!

Loading...